require File.dirname(__FILE__) + '/test_helper' class RemoteS3ObjectTest < Test::Unit::TestCase def setup establish_real_connection end def teardown disconnect! end def test_object key = 'testing_s3objects' value = 'testing' content_type = 'text/plain' fetch_object_at = Proc.new {|url| Net::HTTP.get_response(URI.parse(url))} unauthenticated_url = ['http:/', Base.connection.http.address, TEST_BUCKET, key].join('/') # Create an object response = nil assert_nothing_raised do response = S3Object.create(key, value, TEST_BUCKET, :access => :public_read, :content_type => content_type) end # Check response assert response.success? # Extract the object's etag etag = nil assert_nothing_raised do etag = response.etag end assert etag # Confirm we can't create an object unless the bucket is set assert_raises(NoBucketSpecified) do object = S3Object.new object.key = 'hello' object.store end # Fetch newly created object to show it was actually created object = nil assert_nothing_raised do object = S3Object.find(key, TEST_BUCKET) end assert object # Confirm it has the right etag assert_equal etag, object.etag # Check if its owner is properly set assert_nothing_raised do object.owner.display_name end # Confirm we can get the object's key assert_equal key, object.key # Confirm its value was properly set assert_equal value, object.value assert_equal value, S3Object.value(key, TEST_BUCKET) streamed_value = '' assert_nothing_raised do S3Object.stream(key, TEST_BUCKET) do |segment| streamed_value << segment end end assert_equal value, streamed_value # Change its value new_value = "" assert_nothing_raised do object.value = new_value end assert_equal new_value, object.value # Confirm content type was properly set assert_equal content_type, object.content_type # Change its content type new_content_type = 'text/javascript' assert_nothing_raised do object.content_type = new_content_type end assert_equal new_content_type, object.content_type # Test that it is publicly readable response = fetch_object_at[unauthenticated_url] assert (200..299).include?(response.code.to_i) # Confirm that it has no meta data assert object.metadata.empty? # Set some meta data metadata_key = :secret_sauce metadata_value = "it's a secret" object.metadata[metadata_key] = metadata_value # Persist all changes assert_nothing_raised do object.store end # Refetch the object key = object.key object = nil assert_nothing_raised do object = S3Object.find(key, TEST_BUCKET) end # Confirm all changes were persisted assert object assert_equal key, object.key assert_equal new_content_type, object.content_type assert_equal new_value, object.value assert_equal new_value, object.value(:reload) assert !object.metadata.empty? assert_equal metadata_value, object.metadata[metadata_key] # Change acl assert_nothing_raised do S3Object.create(object.key, object.value, TEST_BUCKET, :access => :private, :content_type => object.content_type) end # Confirm object is no longer publicly readable response = fetch_object_at[unauthenticated_url] assert (400..499).include?(response.code.to_i) # Confirm object is accessible from its authenticated url response = fetch_object_at[object.url] assert (200..299).include?(response.code.to_i) # Copy the object assert_nothing_raised do object.copy('testing_s3objects-copy') end # Confirm the object is identical copy = nil assert_nothing_raised do copy = S3Object.find('testing_s3objects-copy', TEST_BUCKET) end assert copy assert_equal object.value, copy.value assert_equal object.content_type, copy.content_type # Delete object assert_nothing_raised do object.delete end # Confirm we can rename objects renamed_to = copy.key + '-renamed' renamed_value = copy.value assert_nothing_raised do S3Object.rename(copy.key, renamed_to, TEST_BUCKET) end # Confirm renamed copy exists renamed = nil assert_nothing_raised do renamed = S3Object.find(renamed_to, TEST_BUCKET) end assert renamed assert_equal renamed_value, renamed.value # Confirm copy is deleted assert_raises(NoSuchKey) do S3Object.find(copy.key, TEST_BUCKET) end # Confirm that you can not store an object once it is deleted assert_raises(DeletedObject) do object.store end assert_raises(NoSuchKey) do S3Object.find(key, TEST_BUCKET) end # Confirm we can pass in an IO stream and have the uploading sent in chunks response = nil test_file_key = File.basename(TEST_FILE) assert_nothing_raised do response = S3Object.store(test_file_key, File.open(TEST_FILE), TEST_BUCKET) end assert response.success? assert_equal File.size(TEST_FILE), Integer(S3Object.about(test_file_key, TEST_BUCKET)['content-length']) result = nil assert_nothing_raised do result = S3Object.delete(test_file_key, TEST_BUCKET) end assert result # Confirm we can create an object with spaces in its key object = S3Object.new(:value => 'just some text') object.key = 'name with spaces' object.bucket = Bucket.find(TEST_BUCKET) assert_nothing_raised do object.store end object = nil assert_nothing_raised do object = S3Object.find('name with spaces', TEST_BUCKET) end assert object assert_equal 'name with spaces', object.key # Confirm authenticated url is generated correctly despite space in file name response = fetch_object_at[object.url] assert (200..299).include?(response.code.to_i) # Confirm we can delete objects with spaces in their key assert_nothing_raised do object.delete end end def test_content_type_inference # Confirm appropriate content type is infered when not specified content_type_objects = {'foo.jpg' => 'image/jpeg', 'no-extension-specified' => 'binary/octet-stream', 'foo.txt' => 'text/plain'} content_type_objects.each_key do |key| S3Object.store(key, 'fake data', TEST_BUCKET) # No content type explicitly set end content_type_objects.each do |key, content_type| assert_equal content_type, S3Object.about(key, TEST_BUCKET)['content-type'] end # Confirm we can update the content type assert_nothing_raised do object = S3Object.find('no-extension-specified', TEST_BUCKET) object.content_type = 'application/pdf' object.store end assert_equal 'application/pdf', S3Object.about('no-extension-specified', TEST_BUCKET)['content-type'] ensure # Get rid of objects we just created content_type_objects.each_key {|key| S3Object.delete(key, TEST_BUCKET) } end end