aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
authorDave Arter <davea@mysociety.org>2018-09-20 16:15:38 +0100
committerDave Arter <davea@mysociety.org>2018-09-28 16:19:47 +0100
commit07bc1188dc149e05b61e0d93ecf3ef1c26dc8690 (patch)
tree1ac3c9d0148b3f98ff29985e8c760740bb8d2548 /t
parent561e01b9b51b62e2566d80cd63d308f9a4f82822 (diff)
Add S3 photo storage backend
Diffstat (limited to 't')
-rw-r--r--t/app/model/photoset.t25
-rw-r--r--t/photostorage/s3.t164
2 files changed, 189 insertions, 0 deletions
diff --git a/t/app/model/photoset.t b/t/app/model/photoset.t
index 708bda891..29a28d232 100644
--- a/t/app/model/photoset.t
+++ b/t/app/model/photoset.t
@@ -72,4 +72,29 @@ subtest 'Photoset with 3 referenced photo' => sub {
};
+subtest 'Correct storage backends are instantiated' => sub {
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => 'FileSystem'
+ }, sub {
+ my $photoset = FixMyStreet::App::Model::PhotoSet->new;
+ isa_ok $photoset->storage, 'FixMyStreet::PhotoStorage::FileSystem';
+ };
+
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => undef
+ }, sub {
+ my $photoset = FixMyStreet::App::Model::PhotoSet->new;
+ isa_ok $photoset->storage, 'FixMyStreet::PhotoStorage::FileSystem';
+ };
+
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => 'S3'
+ }, sub {
+ my $photoset = FixMyStreet::App::Model::PhotoSet->new;
+ isa_ok $photoset->storage, 'FixMyStreet::PhotoStorage::S3';
+ };
+
+};
+
+
done_testing();
diff --git a/t/photostorage/s3.t b/t/photostorage/s3.t
new file mode 100644
index 000000000..fa989374f
--- /dev/null
+++ b/t/photostorage/s3.t
@@ -0,0 +1,164 @@
+#!/usr/bin/env perl
+use FixMyStreet::Test;
+
+use Test::MockModule;
+use Path::Tiny 'path';
+use Net::Amazon::S3::Client::Bucket;
+
+use_ok( 'FixMyStreet::PhotoStorage::S3' );
+
+FixMyStreet::override_config {
+ PHOTO_STORAGE_OPTIONS => {
+ ACCESS_KEY => 'AKIAMYFAKEACCESSKEY',
+ SECRET_KEY => '1234/fAk35eCrETkEy',
+ BUCKET => 'fms-test-photos',
+ PREFIX => '/uploads',
+ },
+}, sub {
+
+ my $s3 = FixMyStreet::PhotoStorage::S3->new();
+
+ subtest "basic attributes are configured correctly" => sub {
+ ok $s3->client, "N::A::S3::Client created";
+ is $s3->client->s3->aws_access_key_id, 'AKIAMYFAKEACCESSKEY', "Correct access key used";
+ is $s3->client->s3->aws_secret_access_key, '1234/fAk35eCrETkEy', "Correct secret key used";
+
+ ok $s3->bucket, "N::A::S3::Bucket created";
+ is $s3->bucket->name, 'fms-test-photos', "Correct bucket name configured";
+
+ is $s3->prefix, '/uploads/', "Correct key prefix with trailing slash";
+ };
+
+ subtest "photos can be stored in S3" => sub {
+ my $photo_blob = path('t/app/controller/sample.jpg')->slurp;
+ is $s3->get_fileid($photo_blob), '74e3362283b6ef0c48686fb0e161da4043bbcc97', "File ID calculated correctly";
+ is $s3->detect_type($photo_blob), 'jpeg', "File type calculated correctly";
+
+ my $s3_object = Test::MockModule->new('Net::Amazon::S3::Client::Object');
+ my $put_called = 0;
+ $s3_object->mock('put', sub {
+ my ($self, $photo) = @_;
+ is $self->key, '/uploads/74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg', 'Object created with correct key';
+ is $self->bucket->name, 'fms-test-photos', 'Object stored in correct bucket';
+ is $photo, $photo_blob, 'Correct photo uploaded';
+ $put_called = 1;
+ });
+
+ is $s3->store_photo($photo_blob), '/uploads/74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg', 'Photo uploaded and correct key returned';
+ ok $put_called, "Object::put called";
+ };
+
+ subtest "photos can be retrieved from S3" => sub {
+ my $photo_blob = path('t/app/controller/sample.jpg')->slurp;
+ my $key = '/uploads/74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg';
+
+ my $s3_object = Test::MockModule->new('Net::Amazon::S3::Client::Object');
+ my $exists_called = 0;
+ $s3_object->mock('exists', sub {
+ my ($self) = @_;
+ is $self->key, $key, 'Object::exists called with correct key';
+ $exists_called = 1;
+ return 1;
+ });
+ my $get_called = 0;
+ $s3_object->mock('get', sub {
+ my ($self) = @_;
+ is $self->key, $key, 'Object::get called with correct key';
+ is $self->bucket->name, 'fms-test-photos', 'Object fetched from correct bucket';
+ $get_called = 1;
+ return $photo_blob;
+ });
+
+ my ($photo, $type) = $s3->retrieve_photo($key);
+ ok $exists_called, "Object::exists called";
+ ok $get_called, "Object::get called";
+ is $photo, $photo_blob, 'Correct file content returned';
+ is $type, 'jpeg', 'Correct file type returned';
+ };
+
+ subtest "init passes if bucket exists" => sub {
+ my $s3_client = Test::MockModule->new('Net::Amazon::S3::Client');
+ my $buckets_called = 0;
+ $s3_client->mock('buckets', sub {
+ my $self = shift;
+ $buckets_called = 1;
+ return (
+ Net::Amazon::S3::Client::Bucket->new(
+ client => $self,
+ name => 'fms-test-photos'
+ )
+ );
+ });
+
+ ok $s3->init(), "PhotoStorage::S3::init succeeded";
+ ok $buckets_called, "Client::buckets called";
+ };
+
+ subtest "init fails if bucket doesn't exist" => sub {
+ my $s3_client = Test::MockModule->new('Net::Amazon::S3::Client');
+ my $buckets_called = 0;
+ $s3_client->mock('buckets', sub {
+ my $self = shift;
+ $buckets_called = 1;
+ return (
+ Net::Amazon::S3::Client::Bucket->new(
+ client => $self,
+ name => 'not-your-bucket'
+ )
+ );
+ });
+ my $create_bucket_called = 0;
+ $s3_client->mock('create_bucket', sub {
+ $create_bucket_called = 1;
+ });
+
+ ok !$s3->init(), "PhotoStorage::S3::init failed";
+ ok $buckets_called, "Client::buckets called";
+ ok !$create_bucket_called, "Client::create_bucket not called";
+ };
+};
+
+FixMyStreet::override_config {
+ PHOTO_STORAGE_OPTIONS => {
+ ACCESS_KEY => 'AKIAMYFAKEACCESSKEY',
+ SECRET_KEY => '1234/fAk35eCrETkEy',
+ BUCKET => 'fms-test-photos',
+ CREATE_BUCKET => 1,
+ REGION => 'eu-west-3',
+ },
+}, sub {
+
+ my $s3 = FixMyStreet::PhotoStorage::S3->new();
+
+ subtest "init creates bucket if CREATE_BUCKET set" => sub {
+ my $s3_client = Test::MockModule->new('Net::Amazon::S3::Client');
+ my $create_bucket_called = 0;
+ $s3_client->mock('create_bucket', sub {
+ my ( $self, %conf ) = @_;
+ $create_bucket_called = 1;
+ is $conf{name}, "fms-test-photos", "Bucket created with correct name";
+ is $conf{location_constraint}, "eu-west-3", "Bucket created in correct region";
+ });
+ my $buckets_called = 0;
+ $s3_client->mock('buckets', sub {
+ my $self = shift;
+ $buckets_called = 1;
+ return (
+ Net::Amazon::S3::Client::Bucket->new(
+ client => $self,
+ name => 'not-your-bucket'
+ ),
+ $create_bucket_called ? Net::Amazon::S3::Client::Bucket->new(
+ client => $self,
+ name => 'fms-test-photos'
+ ) : (),
+ );
+ });
+
+ ok $s3->init(), "PhotoStorage::S3::init succeeded";
+ ok $buckets_called, "Client::buckets called";
+ ok $create_bucket_called, "Client::create_bucket called";
+ };
+};
+
+done_testing();