stevequinlan-aws-s3 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/COPYING +19 -0
  2. data/INSTALL +55 -0
  3. data/README.rdoc +545 -0
  4. data/Rakefile +120 -0
  5. data/bin/s3sh +6 -0
  6. data/bin/setup.rb +10 -0
  7. data/lib/aws/s3.rb +60 -0
  8. data/lib/aws/s3/acl.rb +636 -0
  9. data/lib/aws/s3/authentication.rb +221 -0
  10. data/lib/aws/s3/base.rb +240 -0
  11. data/lib/aws/s3/bittorrent.rb +58 -0
  12. data/lib/aws/s3/bucket.rb +319 -0
  13. data/lib/aws/s3/connection.rb +287 -0
  14. data/lib/aws/s3/error.rb +69 -0
  15. data/lib/aws/s3/exceptions.rb +133 -0
  16. data/lib/aws/s3/extensions.rb +356 -0
  17. data/lib/aws/s3/logging.rb +314 -0
  18. data/lib/aws/s3/object.rb +612 -0
  19. data/lib/aws/s3/owner.rb +44 -0
  20. data/lib/aws/s3/parsing.rb +99 -0
  21. data/lib/aws/s3/response.rb +180 -0
  22. data/lib/aws/s3/service.rb +51 -0
  23. data/lib/aws/s3/version.rb +12 -0
  24. data/support/faster-xml-simple/lib/faster_xml_simple.rb +187 -0
  25. data/support/faster-xml-simple/test/regression_test.rb +47 -0
  26. data/support/faster-xml-simple/test/test_helper.rb +17 -0
  27. data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +46 -0
  28. data/support/rdoc/code_info.rb +211 -0
  29. data/test/acl_test.rb +254 -0
  30. data/test/authentication_test.rb +114 -0
  31. data/test/base_test.rb +136 -0
  32. data/test/bucket_test.rb +74 -0
  33. data/test/connection_test.rb +215 -0
  34. data/test/error_test.rb +70 -0
  35. data/test/extensions_test.rb +341 -0
  36. data/test/fixtures.rb +89 -0
  37. data/test/fixtures/buckets.yml +133 -0
  38. data/test/fixtures/errors.yml +34 -0
  39. data/test/fixtures/headers.yml +3 -0
  40. data/test/fixtures/logging.yml +15 -0
  41. data/test/fixtures/loglines.yml +5 -0
  42. data/test/fixtures/logs.yml +7 -0
  43. data/test/fixtures/policies.yml +16 -0
  44. data/test/logging_test.rb +89 -0
  45. data/test/mocks/fake_response.rb +26 -0
  46. data/test/object_test.rb +205 -0
  47. data/test/parsing_test.rb +66 -0
  48. data/test/remote/acl_test.rb +117 -0
  49. data/test/remote/bittorrent_test.rb +45 -0
  50. data/test/remote/bucket_test.rb +146 -0
  51. data/test/remote/logging_test.rb +82 -0
  52. data/test/remote/object_test.rb +371 -0
  53. data/test/remote/test_file.data +0 -0
  54. data/test/remote/test_helper.rb +33 -0
  55. data/test/response_test.rb +68 -0
  56. data/test/service_test.rb +23 -0
  57. data/test/test_helper.rb +110 -0
  58. metadata +159 -0
@@ -0,0 +1,371 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RemoteS3ObjectTest < Test::Unit::TestCase
4
+ def setup
5
+ establish_real_connection
6
+ end
7
+
8
+ def teardown
9
+ disconnect!
10
+ end
11
+
12
+ def test_object
13
+ key = 'testing_s3objects'
14
+ value = 'testing'
15
+ content_type = 'text/plain'
16
+ unauthenticated_url = ['http:/', Base.connection.http.address, TEST_BUCKET, key].join('/')
17
+
18
+ # Create an object
19
+
20
+ response = nil
21
+ assert_nothing_raised do
22
+ response = S3Object.create(key, value, TEST_BUCKET, :access => :public_read, :content_type => content_type)
23
+ end
24
+
25
+ # Check response
26
+
27
+ assert response.success?
28
+
29
+ # Extract the object's etag
30
+
31
+ etag = nil
32
+ assert_nothing_raised do
33
+ etag = response.etag
34
+ end
35
+
36
+ assert etag
37
+
38
+ # Confirm we can't create an object unless the bucket is set
39
+
40
+ assert_raises(NoBucketSpecified) do
41
+ object = S3Object.new
42
+ object.key = 'hello'
43
+ object.store
44
+ end
45
+
46
+ # Fetch newly created object to show it was actually created
47
+
48
+ object = nil
49
+ assert_nothing_raised do
50
+ object = S3Object.find(key, TEST_BUCKET)
51
+ end
52
+
53
+ assert object
54
+
55
+ # Confirm it has the right etag
56
+
57
+ assert_equal etag, object.etag
58
+
59
+ # Check if its owner is properly set
60
+
61
+ assert_nothing_raised do
62
+ object.owner.display_name
63
+ end
64
+
65
+ # Confirm we can get the object's key
66
+
67
+ assert_equal key, object.key
68
+
69
+ # Confirm its value was properly set
70
+
71
+ assert_equal value, object.value
72
+ assert_equal value, S3Object.value(key, TEST_BUCKET)
73
+ streamed_value = ''
74
+ assert_nothing_raised do
75
+ S3Object.stream(key, TEST_BUCKET) do |segment|
76
+ streamed_value << segment
77
+ end
78
+ end
79
+
80
+ assert_equal value, streamed_value
81
+
82
+ # Change its value
83
+
84
+ new_value = "<script>alert('foo');</script>"
85
+ assert_nothing_raised do
86
+ object.value = new_value
87
+ end
88
+ assert_equal new_value, object.value
89
+
90
+ # Confirm content type was properly set
91
+
92
+ assert_equal content_type, object.content_type
93
+
94
+ # Change its content type
95
+
96
+ new_content_type = 'text/javascript'
97
+ assert_nothing_raised do
98
+ object.content_type = new_content_type
99
+ end
100
+
101
+ assert_equal new_content_type, object.content_type
102
+
103
+ # Test that it is publicly readable
104
+
105
+ response = fetch_object_at(unauthenticated_url)
106
+ assert (200..299).include?(response.code.to_i)
107
+
108
+ # Confirm that it has no meta data
109
+
110
+ assert object.metadata.empty?
111
+
112
+ # Set some meta data
113
+
114
+ metadata_key = :secret_sauce
115
+ metadata_value = "it's a secret"
116
+ object.metadata[metadata_key] = metadata_value
117
+
118
+ # Persist all changes
119
+
120
+ assert_nothing_raised do
121
+ object.store
122
+ end
123
+
124
+ # Refetch the object
125
+
126
+ key = object.key
127
+ object = nil
128
+ assert_nothing_raised do
129
+ object = S3Object.find(key, TEST_BUCKET)
130
+ end
131
+
132
+ # Confirm all changes were persisted
133
+
134
+ assert object
135
+ assert_equal key, object.key
136
+
137
+ assert_equal new_content_type, object.content_type
138
+
139
+ assert_equal new_value, object.value
140
+ assert_equal new_value, object.value(:reload)
141
+
142
+ assert !object.metadata.empty?
143
+ assert_equal metadata_value, object.metadata[metadata_key]
144
+
145
+ # Change acl
146
+
147
+ assert_nothing_raised do
148
+ S3Object.create(object.key, object.value, TEST_BUCKET, :access => :private, :content_type => object.content_type)
149
+ end
150
+
151
+ # Confirm object is no longer publicly readable
152
+
153
+ response = fetch_object_at(unauthenticated_url)
154
+ assert (400..499).include?(response.code.to_i)
155
+
156
+ # Confirm object is accessible from its authenticated url
157
+
158
+ response = fetch_object_at(object.url)
159
+ assert (200..299).include?(response.code.to_i)
160
+
161
+ # Copy the object
162
+
163
+ assert_nothing_raised do
164
+ object.copy('testing_s3objects-copy')
165
+ end
166
+
167
+ # Confirm the object is identical
168
+
169
+ copy = nil
170
+ assert_nothing_raised do
171
+ copy = S3Object.find('testing_s3objects-copy', TEST_BUCKET)
172
+ end
173
+
174
+ assert copy
175
+
176
+ assert_equal object.value, copy.value
177
+ assert_equal object.content_type, copy.content_type
178
+
179
+ # Delete object
180
+
181
+ assert_nothing_raised do
182
+ object.delete
183
+ end
184
+
185
+ # Confirm we can rename objects
186
+
187
+ renamed_to = copy.key + '-renamed'
188
+ renamed_value = copy.value
189
+ assert_nothing_raised do
190
+ S3Object.rename(copy.key, renamed_to, TEST_BUCKET)
191
+ end
192
+
193
+ # Confirm renamed copy exists
194
+
195
+ renamed = nil
196
+ assert_nothing_raised do
197
+ renamed = S3Object.find(renamed_to, TEST_BUCKET)
198
+ end
199
+
200
+ assert renamed
201
+ assert_equal renamed_value, renamed.value
202
+
203
+ # Confirm copy is deleted
204
+
205
+ assert_raises(NoSuchKey) do
206
+ S3Object.find(copy.key, TEST_BUCKET)
207
+ end
208
+
209
+ # Confirm that you can not store an object once it is deleted
210
+
211
+ assert_raises(DeletedObject) do
212
+ object.store
213
+ end
214
+
215
+ assert_raises(NoSuchKey) do
216
+ S3Object.find(key, TEST_BUCKET)
217
+ end
218
+
219
+ # Confirm we can pass in an IO stream and have the uploading sent in chunks
220
+
221
+ response = nil
222
+ test_file_key = File.basename(TEST_FILE)
223
+ assert_nothing_raised do
224
+ response = S3Object.store(test_file_key, open(TEST_FILE), TEST_BUCKET)
225
+ end
226
+ assert response.success?
227
+
228
+ assert_equal File.size(TEST_FILE), Integer(S3Object.about(test_file_key, TEST_BUCKET)['content-length'])
229
+
230
+ result = nil
231
+ assert_nothing_raised do
232
+ result = S3Object.delete(test_file_key, TEST_BUCKET)
233
+ end
234
+
235
+ assert result
236
+ end
237
+
238
+ def test_content_type_inference
239
+ # Confirm appropriate content type is inferred when not specified
240
+
241
+ content_type_objects = {'foo.jpg' => 'image/jpeg', 'no-extension-specified' => 'binary/octet-stream', 'foo.txt' => 'text/plain'}
242
+ content_type_objects.each_key do |key|
243
+ S3Object.store(key, 'fake data', TEST_BUCKET) # No content type explicitly set
244
+ end
245
+
246
+ content_type_objects.each do |key, content_type|
247
+ assert_equal content_type, S3Object.about(key, TEST_BUCKET)['content-type']
248
+ end
249
+
250
+ # Confirm we can update the content type
251
+
252
+ assert_nothing_raised do
253
+ object = S3Object.find('no-extension-specified', TEST_BUCKET)
254
+ object.content_type = 'application/pdf'
255
+ object.store
256
+ end
257
+
258
+ assert_equal 'application/pdf', S3Object.about('no-extension-specified', TEST_BUCKET)['content-type']
259
+
260
+ ensure
261
+ # Get rid of objects we just created
262
+ content_type_objects.each_key {|key| S3Object.delete(key, TEST_BUCKET) }
263
+ end
264
+
265
+ def test_body_can_be_more_than_just_string_or_io
266
+ require 'stringio'
267
+ key = 'testing-body-as-string-io'
268
+ io = StringIO.new('hello there')
269
+ S3Object.store(key, io, TEST_BUCKET)
270
+ assert_equal 'hello there', S3Object.value(key, TEST_BUCKET)
271
+ ensure
272
+ S3Object.delete(key, TEST_BUCKET)
273
+ end
274
+
275
+ def test_fetching_information_about_an_object_that_does_not_exist_raises_no_such_key
276
+ assert_raises(NoSuchKey) do
277
+ S3Object.about('asdfasdfasdfas-this-does-not-exist', TEST_BUCKET)
278
+ end
279
+ end
280
+
281
+ # Regression test for http://developer.amazonwebservices.com/connect/thread.jspa?messageID=49152&tstart=0#49152
282
+ def test_finding_an_object_with_slashes_in_its_name_does_not_escape_the_slash
283
+ S3Object.store('rails/1', 'value does not matter', TEST_BUCKET)
284
+ S3Object.store('rails/1.html', 'value does not matter', TEST_BUCKET)
285
+
286
+ object = nil
287
+ assert_nothing_raised do
288
+ object = S3Object.find('rails/1.html', TEST_BUCKET)
289
+ end
290
+
291
+ assert_equal 'rails/1.html', object.key
292
+ ensure
293
+ %w(rails/1 rails/1.html).each {|key| S3Object.delete(key, TEST_BUCKET)}
294
+ end
295
+
296
+ def test_finding_an_object_with_spaces_in_its_name
297
+ assert_nothing_raised do
298
+ S3Object.store('name with spaces', 'value does not matter', TEST_BUCKET)
299
+ end
300
+
301
+ object = nil
302
+ assert_nothing_raised do
303
+ object = S3Object.find('name with spaces', TEST_BUCKET)
304
+ end
305
+
306
+ assert object
307
+ assert_equal 'name with spaces', object.key
308
+
309
+ # Confirm authenticated url is generated correctly despite space in file name
310
+
311
+ response = fetch_object_at(object.url)
312
+ assert (200..299).include?(response.code.to_i)
313
+
314
+ ensure
315
+ S3Object.delete('name with spaces', TEST_BUCKET)
316
+ end
317
+
318
+ def test_copying_an_object_should_copy_over_its_acl_also_if_requested
319
+ key = 'copied-objects-inherit-acl'
320
+ copy_key = key + '2'
321
+ S3Object.store(key, 'value does not matter', TEST_BUCKET)
322
+ original_object = S3Object.find(key, TEST_BUCKET)
323
+ original_object.acl.grants << ACL::Grant.grant(:public_read)
324
+ original_object.acl.grants << ACL::Grant.grant(:public_read_acp)
325
+
326
+ S3Object.acl(key, TEST_BUCKET, original_object.acl)
327
+
328
+ acl = S3Object.acl(key, TEST_BUCKET)
329
+ assert_equal 3, acl.grants.size
330
+
331
+ S3Object.copy(key, copy_key, TEST_BUCKET, :copy_acl => true)
332
+ copied_object = S3Object.find(copy_key, TEST_BUCKET)
333
+ assert_equal acl.grants, copied_object.acl.grants
334
+ ensure
335
+ S3Object.delete(key, TEST_BUCKET)
336
+ S3Object.delete(copy_key, TEST_BUCKET)
337
+ end
338
+
339
+ def test_handling_a_path_that_is_not_valid_utf8
340
+ key = "318597/620065/GTL_75\24300_A600_A610.zip"
341
+ assert_nothing_raised do
342
+ S3Object.store(key, 'value does not matter', TEST_BUCKET)
343
+ end
344
+
345
+ object = nil
346
+ assert_nothing_raised do
347
+ object = S3Object.find(key, TEST_BUCKET)
348
+ end
349
+
350
+ assert object
351
+
352
+ url = nil
353
+ assert_nothing_raised do
354
+ url = S3Object.url_for(key, TEST_BUCKET)
355
+ end
356
+
357
+ assert url
358
+
359
+ assert_equal object.value, fetch_object_at(url).body
360
+ ensure
361
+ assert_nothing_raised do
362
+ S3Object.delete(key, TEST_BUCKET)
363
+ end
364
+ end
365
+
366
+ private
367
+ def fetch_object_at(url)
368
+ Net::HTTP.get_response(URI.parse(url))
369
+ end
370
+
371
+ end
@@ -0,0 +1,33 @@
1
+ require 'test/unit'
2
+ require 'uri'
3
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
4
+ require 'aws/s3'
5
+ begin
6
+ require_library_or_gem 'breakpoint'
7
+ rescue LoadError
8
+ end
9
+
10
+ TEST_BUCKET = 'aws-s3-tests'
11
+ TEST_FILE = File.dirname(__FILE__) + '/test_file.data'
12
+
13
+ class Test::Unit::TestCase
14
+ include AWS::S3
15
+ def establish_real_connection
16
+ Base.establish_connection!(
17
+ :access_key_id => ENV['AMAZON_ACCESS_KEY_ID'],
18
+ :secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY']
19
+ )
20
+ end
21
+
22
+ def disconnect!
23
+ Base.disconnect
24
+ end
25
+
26
+ class TestBucket < Bucket
27
+ set_current_bucket_to TEST_BUCKET
28
+ end
29
+
30
+ class TestS3Object < S3Object
31
+ set_current_bucket_to TEST_BUCKET
32
+ end
33
+ end
@@ -0,0 +1,68 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ class BaseResponseTest < Test::Unit::TestCase
3
+ def setup
4
+ @headers = {'content-type' => 'text/plain', 'date' => Time.now}
5
+ @response = FakeResponse.new()
6
+ @base_response = Base::Response.new(@response)
7
+ end
8
+
9
+ def test_status_predicates
10
+ response = Proc.new {|code| Base::Response.new(FakeResponse.new(:code => code))}
11
+ assert response[200].success?
12
+ assert response[300].redirect?
13
+ assert response[400].client_error?
14
+ assert response[500].server_error?
15
+ end
16
+
17
+ def test_headers_passed_along_from_original_response
18
+ assert_equal @response.headers, @base_response.headers
19
+ assert_equal @response['date'], @base_response['date']
20
+ original_headers, new_headers = {}, {}
21
+ @response.headers.each {|k,v| original_headers[k] = v}
22
+ @base_response.each {|k,v| new_headers[k] = v}
23
+ assert_equal original_headers, new_headers
24
+ end
25
+ end
26
+
27
+ class ErrorResponseTest < Test::Unit::TestCase
28
+ def test_error_responses_are_always_in_error
29
+ assert Error::Response.new(FakeResponse.new).error?
30
+ assert Error::Response.new(FakeResponse.new(:code => 200)).error?
31
+ assert Error::Response.new(FakeResponse.new(:headers => {'content-type' => 'text/plain'})).error?
32
+ end
33
+ end
34
+
35
+ class S3ObjectResponseTest < Test::Unit::TestCase
36
+ def test_etag_extracted
37
+ mock_connection_for(S3Object, :returns => {:headers => {"etag" => %("acbd18db4cc2f85cedef654fccc4a4d8")}}).once
38
+ object_response = S3Object.create('name_does_not_matter', 'data does not matter', 'bucket does not matter')
39
+ assert_equal "acbd18db4cc2f85cedef654fccc4a4d8", object_response.etag
40
+ end
41
+ end
42
+
43
+ class ResponseClassFinderTest < Test::Unit::TestCase
44
+ class CampfireBucket < Bucket
45
+ end
46
+
47
+ class BabyBase < Base
48
+ end
49
+
50
+ def test_on_base
51
+ assert_equal Base::Response, FindResponseClass.for(Base)
52
+ assert_equal Base::Response, FindResponseClass.for(AWS::S3::Base)
53
+
54
+ end
55
+
56
+ def test_on_subclass_with_corresponding_response_class
57
+ assert_equal Bucket::Response, FindResponseClass.for(Bucket)
58
+ assert_equal Bucket::Response, FindResponseClass.for(AWS::S3::Bucket)
59
+ end
60
+
61
+ def test_on_subclass_with_intermediary_parent_that_has_corresponding_response_class
62
+ assert_equal Bucket::Response, FindResponseClass.for(CampfireBucket)
63
+ end
64
+
65
+ def test_on_subclass_with_no_corresponding_response_class_and_no_intermediary_parent
66
+ assert_equal Base::Response, FindResponseClass.for(BabyBase)
67
+ end
68
+ end