diff options
Diffstat (limited to 'activestorage/test/service')
-rw-r--r-- | activestorage/test/service/.gitignore | 1 | ||||
-rw-r--r-- | activestorage/test/service/azure_service_test.rb | 14 | ||||
-rw-r--r-- | activestorage/test/service/configurations-example.yml | 31 | ||||
-rw-r--r-- | activestorage/test/service/configurator_test.rb | 14 | ||||
-rw-r--r-- | activestorage/test/service/disk_service_test.rb | 12 | ||||
-rw-r--r-- | activestorage/test/service/gcs_service_test.rb | 42 | ||||
-rw-r--r-- | activestorage/test/service/mirror_service_test.rb | 62 | ||||
-rw-r--r-- | activestorage/test/service/s3_service_test.rb | 52 | ||||
-rw-r--r-- | activestorage/test/service/shared_service_tests.rb | 67 |
9 files changed, 295 insertions, 0 deletions
diff --git a/activestorage/test/service/.gitignore b/activestorage/test/service/.gitignore new file mode 100644 index 0000000000..c102131f3d --- /dev/null +++ b/activestorage/test/service/.gitignore @@ -0,0 +1 @@ +configurations.yml diff --git a/activestorage/test/service/azure_service_test.rb b/activestorage/test/service/azure_service_test.rb new file mode 100644 index 0000000000..0ddbac83e7 --- /dev/null +++ b/activestorage/test/service/azure_service_test.rb @@ -0,0 +1,14 @@ +require "service/shared_service_tests" +require "httparty" +require "uri" + +if SERVICE_CONFIGURATIONS[:azure] + class ActiveStorage::Service::AzureServiceTest < ActiveSupport::TestCase + SERVICE = ActiveStorage::Service.configure(:azure, SERVICE_CONFIGURATIONS) + + include ActiveStorage::Service::SharedServiceTests + end + +else + puts "Skipping Azure Storage Service tests because no Azure configuration was supplied" +end diff --git a/activestorage/test/service/configurations-example.yml b/activestorage/test/service/configurations-example.yml new file mode 100644 index 0000000000..68f6ae4224 --- /dev/null +++ b/activestorage/test/service/configurations-example.yml @@ -0,0 +1,31 @@ +# Copy this file to configurations.yml and edit the credentials to match your IAM test account and bucket +s3: + service: S3 + access_key_id: + secret_access_key: + region: + bucket: + +gcs: + service: GCS + keyfile: { + type: "service_account", + project_id: "", + private_key_id: "", + private_key: "", + client_email: "", + client_id: "", + auth_uri: "https://accounts.google.com/o/oauth2/auth", + token_uri: "https://accounts.google.com/o/oauth2/token", + auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs", + client_x509_cert_url: "" + } + project: + bucket: + +azure: + service: Azure + path: "" + storage_account_name: "" + storage_access_key: "" + container: "" diff --git a/activestorage/test/service/configurator_test.rb b/activestorage/test/service/configurator_test.rb new file mode 100644 index 0000000000..c69b8d5087 --- /dev/null +++ b/activestorage/test/service/configurator_test.rb @@ -0,0 +1,14 @@ +require "service/shared_service_tests" + +class ActiveStorage::Service::ConfiguratorTest < ActiveSupport::TestCase + test "builds correct service instance based on service name" do + service = ActiveStorage::Service::Configurator.build(:foo, foo: { service: "Disk", root: "path" }) + assert_instance_of ActiveStorage::Service::DiskService, service + end + + test "raises error when passing non-existent service name" do + assert_raise RuntimeError do + ActiveStorage::Service::Configurator.build(:bigfoot, {}) + end + end +end diff --git a/activestorage/test/service/disk_service_test.rb b/activestorage/test/service/disk_service_test.rb new file mode 100644 index 0000000000..a625521601 --- /dev/null +++ b/activestorage/test/service/disk_service_test.rb @@ -0,0 +1,12 @@ +require "service/shared_service_tests" + +class ActiveStorage::Service::DiskServiceTest < ActiveSupport::TestCase + SERVICE = ActiveStorage::Service::DiskService.new(root: File.join(Dir.tmpdir, "active_storage")) + + include ActiveStorage::Service::SharedServiceTests + + test "url generation" do + assert_match /rails\/active_storage\/disk\/.*\/avatar\.png\?.+disposition=inline/, + @service.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: "avatar.png", content_type: "image/png") + end +end diff --git a/activestorage/test/service/gcs_service_test.rb b/activestorage/test/service/gcs_service_test.rb new file mode 100644 index 0000000000..134a06e3a4 --- /dev/null +++ b/activestorage/test/service/gcs_service_test.rb @@ -0,0 +1,42 @@ +require "service/shared_service_tests" +require "httparty" + +if SERVICE_CONFIGURATIONS[:gcs] + class ActiveStorage::Service::GCSServiceTest < ActiveSupport::TestCase + SERVICE = ActiveStorage::Service.configure(:gcs, SERVICE_CONFIGURATIONS) + + include ActiveStorage::Service::SharedServiceTests + + test "direct upload" do + begin + key = SecureRandom.base58(24) + data = "Something else entirely!" + checksum = Digest::MD5.base64digest(data) + url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) + + HTTParty.put( + url, + body: data, + headers: { "Content-Type" => "text/plain", "Content-MD5" => checksum }, + debug_output: STDOUT + ) + + assert_equal data, @service.download(key) + ensure + @service.delete key + end + end + + test "signed URL generation" do + freeze_time do + url = SERVICE.bucket.signed_url(FIXTURE_KEY, expires: 120) + + "&response-content-disposition=inline%3B+filename%3D%22test.txt%22" + + "&response-content-type=text%2Fplain" + + assert_equal url, @service.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain") + end + end + end +else + puts "Skipping GCS Service tests because no GCS configuration was supplied" +end diff --git a/activestorage/test/service/mirror_service_test.rb b/activestorage/test/service/mirror_service_test.rb new file mode 100644 index 0000000000..129e11d06f --- /dev/null +++ b/activestorage/test/service/mirror_service_test.rb @@ -0,0 +1,62 @@ +require "service/shared_service_tests" + +class ActiveStorage::Service::MirrorServiceTest < ActiveSupport::TestCase + mirror_config = (1..3).map do |i| + [ "mirror_#{i}", + service: "Disk", + root: Dir.mktmpdir("active_storage_tests_mirror_#{i}") ] + end.to_h + + config = mirror_config.merge \ + mirror: { service: "Mirror", primary: "primary", mirrors: mirror_config.keys }, + primary: { service: "Disk", root: Dir.mktmpdir("active_storage_tests_primary") } + + SERVICE = ActiveStorage::Service.configure :mirror, config + + include ActiveStorage::Service::SharedServiceTests + + test "uploading to all services" do + begin + data = "Something else entirely!" + key = upload(data, to: @service) + + assert_equal data, SERVICE.primary.download(key) + SERVICE.mirrors.each do |mirror| + assert_equal data, mirror.download(key) + end + ensure + @service.delete key + end + end + + test "downloading from primary service" do + data = "Something else entirely!" + key = upload(data, to: SERVICE.primary) + + assert_equal data, @service.download(key) + end + + test "deleting from all services" do + @service.delete FIXTURE_KEY + assert_not SERVICE.primary.exist?(FIXTURE_KEY) + SERVICE.mirrors.each do |mirror| + assert_not mirror.exist?(FIXTURE_KEY) + end + end + + test "URL generation in primary service" do + freeze_time do + assert_equal SERVICE.primary.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain"), + @service.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain") + end + end + + private + def upload(data, to:) + SecureRandom.base58(24).tap do |key| + io = StringIO.new(data).tap(&:read) + @service.upload key, io, checksum: Digest::MD5.base64digest(data) + assert io.eof? + end + end +end diff --git a/activestorage/test/service/s3_service_test.rb b/activestorage/test/service/s3_service_test.rb new file mode 100644 index 0000000000..fa2df263a6 --- /dev/null +++ b/activestorage/test/service/s3_service_test.rb @@ -0,0 +1,52 @@ +require "service/shared_service_tests" +require "httparty" + +if SERVICE_CONFIGURATIONS[:s3] + class ActiveStorage::Service::S3ServiceTest < ActiveSupport::TestCase + SERVICE = ActiveStorage::Service.configure(:s3, SERVICE_CONFIGURATIONS) + + include ActiveStorage::Service::SharedServiceTests + + test "direct upload" do + begin + key = SecureRandom.base58(24) + data = "Something else entirely!" + checksum = Digest::MD5.base64digest(data) + url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum) + + HTTParty.put( + url, + body: data, + headers: { "Content-Type" => "text/plain", "Content-MD5" => checksum }, + debug_output: STDOUT + ) + + assert_equal data, @service.download(key) + ensure + @service.delete key + end + end + + test "signed URL generation" do + assert_match /#{SERVICE_CONFIGURATIONS[:s3][:bucket]}\.s3.(\S+)?amazonaws.com.*response-content-disposition=inline.*avatar\.png.*response-content-type=image%2Fpng/, + @service.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: "avatar.png", content_type: "image/png") + end + + test "uploading with server-side encryption" do + config = SERVICE_CONFIGURATIONS.deep_merge(s3: { upload: { server_side_encryption: "AES256" }}) + service = ActiveStorage::Service.configure(:s3, config) + + begin + key = SecureRandom.base58(24) + data = "Something else entirely!" + service.upload key, StringIO.new(data), checksum: Digest::MD5.base64digest(data) + + assert_equal "AES256", service.bucket.object(key).server_side_encryption + ensure + service.delete key + end + end + end +else + puts "Skipping S3 Service tests because no S3 configuration was supplied" +end diff --git a/activestorage/test/service/shared_service_tests.rb b/activestorage/test/service/shared_service_tests.rb new file mode 100644 index 0000000000..07620d91e4 --- /dev/null +++ b/activestorage/test/service/shared_service_tests.rb @@ -0,0 +1,67 @@ +require "test_helper" +require "active_support/core_ext/securerandom" + +module ActiveStorage::Service::SharedServiceTests + extend ActiveSupport::Concern + + FIXTURE_KEY = SecureRandom.base58(24) + FIXTURE_DATA = "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\000\020\000\000\000\020\001\003\000\000\000%=m\"\000\000\000\006PLTE\000\000\000\377\377\377\245\331\237\335\000\000\0003IDATx\234c\370\377\237\341\377_\206\377\237\031\016\2603\334?\314p\1772\303\315\315\f7\215\031\356\024\203\320\275\317\f\367\201R\314\f\017\300\350\377\177\000Q\206\027(\316]\233P\000\000\000\000IEND\256B`\202".force_encoding(Encoding::BINARY) + + included do + setup do + @service = self.class.const_get(:SERVICE) + @service.upload FIXTURE_KEY, StringIO.new(FIXTURE_DATA) + end + + teardown do + @service.delete FIXTURE_KEY + end + + test "uploading with integrity" do + begin + key = SecureRandom.base58(24) + data = "Something else entirely!" + @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data)) + + assert_equal data, @service.download(key) + ensure + @service.delete key + end + end + + test "uploading without integrity" do + begin + key = SecureRandom.base58(24) + data = "Something else entirely!" + + assert_raises(ActiveStorage::IntegrityError) do + @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest("bad data")) + end + + assert_not @service.exist?(key) + ensure + @service.delete key + end + end + + test "downloading" do + assert_equal FIXTURE_DATA, @service.download(FIXTURE_KEY) + end + + test "existing" do + assert @service.exist?(FIXTURE_KEY) + assert_not @service.exist?(FIXTURE_KEY + "nonsense") + end + + test "deleting" do + @service.delete FIXTURE_KEY + assert_not @service.exist?(FIXTURE_KEY) + end + + test "deleting nonexistent key" do + assert_nothing_raised do + @service.delete SecureRandom.base58(24) + end + end + end +end |