PageRenderTime 66ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/test/remote/object_test.rb

https://github.com/culturecode/aws-s3
Ruby | 425 lines | 373 code | 37 blank | 15 comment | 0 complexity | 29f2d47ee616e074773bb8217c363d19 MD5 | raw file
  1. require File.dirname(__FILE__) + '/test_helper'
  2. class RemoteS3ObjectTest < Test::Unit::TestCase
  3. def setup
  4. establish_real_connection
  5. end
  6. def teardown
  7. disconnect!
  8. end
  9. def test_object
  10. key = 'testing_s3objects'
  11. value = 'testing'
  12. content_type = 'text/plain'
  13. unauthenticated_url = ['http:/', Base.connection.http.address, TEST_BUCKET, key].join('/')
  14. # Create an object
  15. response = nil
  16. assert_nothing_raised do
  17. response = S3Object.create(key, value, TEST_BUCKET, :access => :public_read, :content_type => content_type)
  18. end
  19. # Check response
  20. assert response.success?
  21. # Extract the object's etag
  22. etag = nil
  23. assert_nothing_raised do
  24. etag = response.etag
  25. end
  26. assert etag
  27. # Confirm we can't create an object unless the bucket is set
  28. assert_raises(NoBucketSpecified) do
  29. object = S3Object.new
  30. object.key = 'hello'
  31. object.store
  32. end
  33. # Fetch newly created object to show it was actually created
  34. object = nil
  35. assert_nothing_raised do
  36. object = S3Object.find(key, TEST_BUCKET)
  37. end
  38. assert object
  39. # Confirm it has the right etag
  40. assert_equal etag, object.etag
  41. # Check if its owner is properly set
  42. assert_nothing_raised do
  43. object.owner.display_name
  44. end
  45. # Confirm we can get the object's key
  46. assert_equal key, object.key
  47. # Confirm its value was properly set
  48. assert_equal value, object.value
  49. assert_equal value, S3Object.value(key, TEST_BUCKET)
  50. streamed_value = ''
  51. assert_nothing_raised do
  52. S3Object.stream(key, TEST_BUCKET) do |segment|
  53. streamed_value << segment
  54. end
  55. end
  56. assert_equal value, streamed_value
  57. # Change its value
  58. new_value = "<script>alert('foo');</script>"
  59. assert_nothing_raised do
  60. object.value = new_value
  61. end
  62. assert_equal new_value, object.value
  63. # Confirm content type was properly set
  64. assert_equal content_type, object.content_type
  65. # Change its content type
  66. new_content_type = 'text/javascript'
  67. assert_nothing_raised do
  68. object.content_type = new_content_type
  69. end
  70. assert_equal new_content_type, object.content_type
  71. # Test that it is publicly readable
  72. response = fetch_object_at(unauthenticated_url)
  73. assert (200..299).include?(response.code.to_i)
  74. # Confirm that it has no meta data
  75. assert object.metadata.empty?
  76. # Set some meta data
  77. metadata_key = :secret_sauce
  78. metadata_value = "it's a secret"
  79. object.metadata[metadata_key] = metadata_value
  80. # Persist all changes
  81. assert_nothing_raised do
  82. object.store
  83. end
  84. # Refetch the object
  85. key = object.key
  86. object = nil
  87. assert_nothing_raised do
  88. object = S3Object.find(key, TEST_BUCKET)
  89. end
  90. # Confirm all changes were persisted
  91. assert object
  92. assert_equal key, object.key
  93. assert_equal new_content_type, object.content_type
  94. assert_equal new_value, object.value
  95. assert_equal new_value, object.value(:reload)
  96. assert !object.metadata.empty?
  97. assert_equal metadata_value, object.metadata[metadata_key]
  98. # Change acl
  99. assert_nothing_raised do
  100. S3Object.create(object.key, object.value, TEST_BUCKET, :access => :private, :content_type => object.content_type)
  101. end
  102. # Confirm object is no longer publicly readable
  103. response = fetch_object_at(unauthenticated_url)
  104. assert (400..499).include?(response.code.to_i)
  105. # Confirm object is accessible from its authenticated url
  106. response = fetch_object_at(object.url)
  107. assert (200..299).include?(response.code.to_i)
  108. # Copy the object
  109. assert_nothing_raised do
  110. object.copy('testing_s3objects-copy')
  111. end
  112. # Confirm the object is identical
  113. copy = nil
  114. assert_nothing_raised do
  115. copy = S3Object.find('testing_s3objects-copy', TEST_BUCKET)
  116. end
  117. assert copy
  118. assert_equal object.value, copy.value
  119. assert_equal object.content_type, copy.content_type
  120. # Test copy to an filename with an accent
  121. copy_to_accent = nil
  122. assert_nothing_raised do
  123. object.copy('testing_s3objects-copy-to-accent-é')
  124. copy_to_accent = S3Object.find('testing_s3objects-copy-to-accent-é', TEST_BUCKET)
  125. assert copy_to_accent
  126. assert_equal copy_to_accent.value, object.value
  127. assert_equal copy_to_accent.content_type, object.content_type
  128. end
  129. # Test copy from an filename with an accent
  130. assert_nothing_raised do
  131. object_with_accent = S3Object.find('testing_s3objects-copy-to-accent-é')
  132. object_with_accent.copy('testing_s3objects-copy-from-accent')
  133. copy_from_accent = S3Object.find('testing_s3objects-copy-from-accent', TEST_BUCKET)
  134. assert copy_from_accent
  135. assert_equal copy_from_accent.value, object_with_accent.value
  136. assert_equal copy_from_accent.content_type, object_with_accent.content_type
  137. end
  138. # Delete object
  139. assert_nothing_raised do
  140. object.delete
  141. end
  142. # Confirm we can rename objects
  143. renamed_to = copy.key + '-renamed'
  144. renamed_value = copy.value
  145. assert_nothing_raised do
  146. S3Object.rename(copy.key, renamed_to, TEST_BUCKET)
  147. end
  148. # Confirm renamed copy exists
  149. renamed = nil
  150. assert_nothing_raised do
  151. renamed = S3Object.find(renamed_to, TEST_BUCKET)
  152. end
  153. assert renamed
  154. assert_equal renamed_value, renamed.value
  155. # Confirm copy is deleted
  156. assert_raises(NoSuchKey) do
  157. S3Object.find(copy.key, TEST_BUCKET)
  158. end
  159. # Confirm that you can not store an object once it is deleted
  160. assert_raises(DeletedObject) do
  161. object.store
  162. end
  163. assert_raises(NoSuchKey) do
  164. S3Object.find(key, TEST_BUCKET)
  165. end
  166. # Confirm we can pass in an IO stream and have the uploading sent in chunks
  167. response = nil
  168. test_file_key = File.basename(TEST_FILE)
  169. assert_nothing_raised do
  170. response = S3Object.store(test_file_key, open(TEST_FILE), TEST_BUCKET)
  171. end
  172. assert response.success?
  173. assert_equal File.size(TEST_FILE), Integer(S3Object.about(test_file_key, TEST_BUCKET)['content-length'])
  174. result = nil
  175. assert_nothing_raised do
  176. result = S3Object.delete(test_file_key, TEST_BUCKET)
  177. end
  178. assert result
  179. end
  180. def test_content_type_inference
  181. # Confirm appropriate content type is inferred when not specified
  182. content_type_objects = {'foo.jpg' => 'image/jpeg', 'no-extension-specified' => 'binary/octet-stream', 'foo.txt' => 'text/plain'}
  183. content_type_objects.each_key do |key|
  184. S3Object.store(key, 'fake data', TEST_BUCKET) # No content type explicitly set
  185. end
  186. content_type_objects.each do |key, content_type|
  187. assert_equal content_type, S3Object.about(key, TEST_BUCKET)['content-type']
  188. end
  189. # Confirm we can update the content type
  190. assert_nothing_raised do
  191. object = S3Object.find('no-extension-specified', TEST_BUCKET)
  192. object.content_type = 'application/pdf'
  193. object.store
  194. end
  195. assert_equal 'application/pdf', S3Object.about('no-extension-specified', TEST_BUCKET)['content-type']
  196. ensure
  197. # Get rid of objects we just created
  198. content_type_objects.each_key {|key| S3Object.delete(key, TEST_BUCKET) }
  199. end
  200. def test_body_can_be_more_than_just_string_or_io
  201. require 'stringio'
  202. key = 'testing-body-as-string-io'
  203. io = StringIO.new('hello there')
  204. S3Object.store(key, io, TEST_BUCKET)
  205. assert_equal 'hello there', S3Object.value(key, TEST_BUCKET)
  206. ensure
  207. S3Object.delete(key, TEST_BUCKET)
  208. end
  209. def test_fetching_information_about_an_object_that_does_not_exist_raises_no_such_key
  210. assert_raises(NoSuchKey) do
  211. S3Object.about('asdfasdfasdfas-this-does-not-exist', TEST_BUCKET)
  212. end
  213. end
  214. # Regression test for http://developer.amazonwebservices.com/connect/thread.jspa?messageID=49152&tstart=0#49152
  215. def test_finding_an_object_with_slashes_in_its_name_does_not_escape_the_slash
  216. S3Object.store('rails/1', 'value does not matter', TEST_BUCKET)
  217. S3Object.store('rails/1.html', 'value does not matter', TEST_BUCKET)
  218. object = nil
  219. assert_nothing_raised do
  220. object = S3Object.find('rails/1.html', TEST_BUCKET)
  221. end
  222. assert_equal 'rails/1.html', object.key
  223. ensure
  224. %w(rails/1 rails/1.html).each {|key| S3Object.delete(key, TEST_BUCKET)}
  225. end
  226. def test_finding_an_object_with_spaces_in_its_name
  227. assert_nothing_raised do
  228. S3Object.store('name with spaces', 'value does not matter', TEST_BUCKET)
  229. end
  230. object = nil
  231. assert_nothing_raised do
  232. object = S3Object.find('name with spaces', TEST_BUCKET)
  233. end
  234. assert object
  235. assert_equal 'name with spaces', object.key
  236. # Confirm authenticated url is generated correctly despite space in file name
  237. response = fetch_object_at(object.url)
  238. assert (200..299).include?(response.code.to_i)
  239. ensure
  240. S3Object.delete('name with spaces', TEST_BUCKET)
  241. end
  242. def test_copying_an_object_should_copy_over_its_acl_also_if_requested
  243. key = 'copied-objects-inherit-acl'
  244. copy_key = key + '2'
  245. S3Object.store(key, 'value does not matter', TEST_BUCKET)
  246. original_object = S3Object.find(key, TEST_BUCKET)
  247. original_object.acl.grants << ACL::Grant.grant(:public_read)
  248. original_object.acl.grants << ACL::Grant.grant(:public_read_acp)
  249. S3Object.acl(key, TEST_BUCKET, original_object.acl)
  250. acl = S3Object.acl(key, TEST_BUCKET)
  251. assert_equal 3, acl.grants.size
  252. S3Object.copy(key, copy_key, TEST_BUCKET, :copy_acl => true)
  253. copied_object = S3Object.find(copy_key, TEST_BUCKET)
  254. assert_equal acl.grants, copied_object.acl.grants
  255. ensure
  256. S3Object.delete(key, TEST_BUCKET)
  257. S3Object.delete(copy_key, TEST_BUCKET)
  258. end
  259. def test_handling_a_path_that_is_not_valid_utf8
  260. key = "318597/620065/GTL_75\24300_A600_A610.zip"
  261. assert_nothing_raised do
  262. S3Object.store(key, 'value does not matter', TEST_BUCKET)
  263. end
  264. object = nil
  265. assert_nothing_raised do
  266. object = S3Object.find(key, TEST_BUCKET)
  267. end
  268. assert object
  269. url = nil
  270. assert_nothing_raised do
  271. url = S3Object.url_for(key, TEST_BUCKET)
  272. end
  273. assert url
  274. assert_equal object.value, fetch_object_at(url).body
  275. ensure
  276. assert_nothing_raised do
  277. S3Object.delete(key, TEST_BUCKET)
  278. end
  279. end
  280. def test_updating_an_object_should_replace_its_metadata
  281. key = 'updated-object'
  282. S3Object.store(key, 'value does not matter', TEST_BUCKET)
  283. object = S3Object.find(key, TEST_BUCKET)
  284. object.content_type = 'foo/bar'
  285. object.metadata[:foo] = 'bar'
  286. object.update
  287. reloaded_object = S3Object.find(key, TEST_BUCKET)
  288. assert_equal 'foo/bar', reloaded_object.content_type
  289. assert_equal 'bar', reloaded_object.metadata[:foo]
  290. ensure
  291. S3Object.delete(key, TEST_BUCKET)
  292. end
  293. def test_updating_an_object_with_unicode_name
  294. key = 'ʇɔǝɾqo-pǝʇɐpdn'
  295. S3Object.store(key, 'value does not matter', TEST_BUCKET)
  296. object = S3Object.find(key, TEST_BUCKET)
  297. object.content_type = 'foo/bar'
  298. object.metadata[:foo] = 'bar'
  299. object.update
  300. reloaded_object = S3Object.find(key, TEST_BUCKET)
  301. assert_equal 'foo/bar', reloaded_object.content_type
  302. assert_equal 'bar', reloaded_object.metadata[:foo]
  303. ensure
  304. S3Object.delete(key, TEST_BUCKET)
  305. end
  306. private
  307. def fetch_object_at(url)
  308. Net::HTTP.get_response(URI.parse(url))
  309. end
  310. end