stevequinlan-aws-s3 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,70 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ErrorTest < Test::Unit::TestCase
4
+ def setup
5
+ @container = AWS::S3
6
+ @error = Error.new(Parsing::XmlParser.new(Fixtures::Errors.access_denied))
7
+ @container.send(:remove_const, :NotImplemented) if @container.const_defined?(:NotImplemented)
8
+ end
9
+
10
+ def test_error_class_is_automatically_generated
11
+ assert !@container.const_defined?('NotImplemented')
12
+ error = Error.new(Parsing::XmlParser.new(Fixtures::Errors.not_implemented))
13
+ assert @container.const_defined?('NotImplemented')
14
+ end
15
+
16
+ def test_error_contains_attributes
17
+ assert_equal 'Access Denied', @error.message
18
+ end
19
+
20
+ def test_error_is_raisable_as_exception
21
+ assert_raises(@container::AccessDenied) do
22
+ @error.raise
23
+ end
24
+ end
25
+
26
+ def test_error_message_is_passed_along_to_exception
27
+ @error.raise
28
+ rescue @container::AccessDenied => e
29
+ assert_equal 'Access Denied', e.message
30
+ end
31
+
32
+ def test_response_is_passed_along_to_exception
33
+ response = Error::Response.new(FakeResponse.new(:code => 409, :body => Fixtures::Errors.access_denied))
34
+ response.error.raise
35
+ rescue @container::ResponseError => e
36
+ assert e.response
37
+ assert_kind_of Error::Response, e.response
38
+ assert_equal response.error, e.response.error
39
+ end
40
+
41
+ def test_exception_class_clash
42
+ assert !@container.const_defined?(:NotImplemented)
43
+ # Create a class that does not inherit from exception that has the same name as the class
44
+ # the Error instance is about to attempt to find or create
45
+ @container.const_set(:NotImplemented, Class.new)
46
+ assert @container.const_defined?(:NotImplemented)
47
+
48
+ assert_raises(ExceptionClassClash) do
49
+ Error.new(Parsing::XmlParser.new(Fixtures::Errors.not_implemented))
50
+ end
51
+ end
52
+
53
+ def test_error_response_handles_attributes_with_no_value
54
+ mock_connection_for(Bucket, :returns => {:body => Fixtures::Errors.error_with_no_message, :code => 500})
55
+
56
+ begin
57
+ Bucket.create('foo', 'invalid-argument' => 'bad juju')
58
+ rescue ResponseError => error
59
+ end
60
+
61
+ assert_nothing_raised do
62
+ error.response.error.message
63
+ end
64
+ assert_nil error.response.error.message
65
+
66
+ assert_raises(NoMethodError) do
67
+ error.response.error.non_existant_method
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,341 @@
1
+ # coding: utf-8
2
+ require File.dirname(__FILE__) + '/test_helper'
3
+
4
+ class HashExtensionsTest < Test::Unit::TestCase
5
+ def test_to_query_string
6
+ # Because hashes aren't ordered, I'm mostly testing against hashes with just one key
7
+ symbol_keys = {:one => 1}
8
+ string_keys = {'one' => 1}
9
+ expected = '?one=1'
10
+ [symbol_keys, string_keys].each do |hash|
11
+ assert_equal expected, hash.to_query_string
12
+ end
13
+ end
14
+
15
+ def test_empty_hash_returns_no_query_string
16
+ assert_equal '', {}.to_query_string
17
+ end
18
+
19
+ def test_include_question_mark
20
+ hash = {:one => 1}
21
+ assert_equal '?one=1', hash.to_query_string
22
+ assert_equal 'one=1', hash.to_query_string(false)
23
+ end
24
+
25
+ def test_elements_joined_by_ampersand
26
+ hash = {:one => 1, :two => 2}
27
+ qs = hash.to_query_string
28
+ assert qs['one=1&two=2'] || qs['two=2&one=1']
29
+ end
30
+
31
+ def test_normalized_options
32
+ expectations = [
33
+ [{:foo_bar => 1}, {'foo-bar' => '1'}],
34
+ [{'foo_bar' => 1}, {'foo-bar' => '1'}],
35
+ [{'foo-bar' => 1}, {'foo-bar' => '1'}],
36
+ [{}, {}]
37
+ ]
38
+
39
+ expectations.each do |(before, after)|
40
+ assert_equal after, before.to_normalized_options
41
+ end
42
+ end
43
+ end
44
+
45
+ class StringExtensionsTest < Test::Unit::TestCase
46
+ def test_previous
47
+ expectations = {'abc' => 'abb', '123' => '122', '1' => '0'}
48
+ expectations.each do |before, after|
49
+ assert_equal after, before.previous
50
+ end
51
+ end
52
+
53
+ def test_to_header
54
+ transformations = {
55
+ 'foo' => 'foo',
56
+ :foo => 'foo',
57
+ 'foo-bar' => 'foo-bar',
58
+ 'foo_bar' => 'foo-bar',
59
+ :foo_bar => 'foo-bar',
60
+ 'Foo-Bar' => 'foo-bar',
61
+ 'Foo_Bar' => 'foo-bar'
62
+ }
63
+
64
+ transformations.each do |before, after|
65
+ assert_equal after, before.to_header
66
+ end
67
+ end
68
+
69
+ def test_valid_utf8?
70
+ assert !"318597/620065/GTL_75\24300_A600_A610.zip".valid_utf8?
71
+ assert "318597/620065/GTL_75£00_A600_A610.zip".valid_utf8?
72
+ end
73
+
74
+ def test_remove_extended
75
+ assert "318597/620065/GTL_75\24300_A600_A610.zip".remove_extended.valid_utf8?
76
+ assert "318597/620065/GTL_75£00_A600_A610.zip".remove_extended.valid_utf8?
77
+ end
78
+ end
79
+
80
+ class CoercibleStringTest < Test::Unit::TestCase
81
+
82
+ def test_coerce
83
+ coercions = [
84
+ ['1', 1],
85
+ ['false', false],
86
+ ['true', true],
87
+ ['2006-10-29T23:14:47.000Z', Time.parse('2006-10-29T23:14:47.000Z')],
88
+ ['Hello!', 'Hello!'],
89
+ ['false23', 'false23'],
90
+ ['03 1-2-3-Apple-Tree.mp3', '03 1-2-3-Apple-Tree.mp3'],
91
+ ['0815', '0815'] # This number isn't coerced because the leading zero would be lost
92
+ ]
93
+
94
+ coercions.each do |before, after|
95
+ assert_nothing_raised do
96
+ assert_equal after, CoercibleString.coerce(before)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ class KerneltExtensionsTest < Test::Unit::TestCase
103
+ class Foo
104
+ def foo
105
+ __method__
106
+ end
107
+
108
+ def bar
109
+ foo
110
+ end
111
+
112
+ def baz
113
+ bar
114
+ end
115
+ end
116
+
117
+ class Bar
118
+ def foo
119
+ calling_method
120
+ end
121
+
122
+ def bar
123
+ calling_method
124
+ end
125
+
126
+ def calling_method
127
+ __method__(1)
128
+ end
129
+ end
130
+
131
+ def test___method___works_regardless_of_nesting
132
+ f = Foo.new
133
+ [:foo, :bar, :baz].each do |method|
134
+ assert_equal 'foo', f.send(method)
135
+ end
136
+ end
137
+
138
+ def test___method___depth
139
+ b = Bar.new
140
+ assert_equal 'foo', b.foo
141
+ assert_equal 'bar', b.bar
142
+ end
143
+ end if RUBY_VERSION <= '1.8.7'
144
+
145
+ class ModuleExtensionsTest < Test::Unit::TestCase
146
+ class Foo
147
+ def foo(reload = false)
148
+ expirable_memoize(reload) do
149
+ Time.now
150
+ end
151
+ end
152
+
153
+ def bar(reload = false)
154
+ expirable_memoize(reload, :baz) do
155
+ Time.now
156
+ end
157
+ end
158
+
159
+ def quux
160
+ Time.now
161
+ end
162
+ memoized :quux
163
+ end
164
+
165
+ def setup
166
+ @instance = Foo.new
167
+ end
168
+
169
+ def test_memoize
170
+ assert !instance_variables_of(@instance).include?('@foo')
171
+ cached_result = @instance.foo
172
+ assert_equal cached_result, @instance.foo
173
+ assert instance_variables_of(@instance).include?('@foo')
174
+ assert_equal cached_result, @instance.send(:instance_variable_get, :@foo)
175
+ assert_not_equal cached_result, new_cache = @instance.foo(:reload)
176
+ assert_equal new_cache, @instance.foo
177
+ assert_equal new_cache, @instance.send(:instance_variable_get, :@foo)
178
+ end
179
+
180
+ def test_customizing_memoize_storage
181
+ assert !instance_variables_of(@instance).include?('@bar')
182
+ assert !instance_variables_of(@instance).include?('@baz')
183
+ cached_result = @instance.bar
184
+ assert !instance_variables_of(@instance).include?('@bar')
185
+ assert instance_variables_of(@instance).include?('@baz')
186
+ assert_equal cached_result, @instance.bar
187
+ assert_equal cached_result, @instance.send(:instance_variable_get, :@baz)
188
+ assert_nil @instance.send(:instance_variable_get, :@bar)
189
+ end
190
+
191
+ def test_memoized
192
+ assert !instance_variables_of(@instance).include?('@quux')
193
+ cached_result = @instance.quux
194
+ assert_equal cached_result, @instance.quux
195
+ assert instance_variables_of(@instance).include?('@quux')
196
+ assert_equal cached_result, @instance.send(:instance_variable_get, :@quux)
197
+ assert_not_equal cached_result, new_cache = @instance.quux(:reload)
198
+ assert_equal new_cache, @instance.quux
199
+ assert_equal new_cache, @instance.send(:instance_variable_get, :@quux)
200
+ end
201
+
202
+ def test_constant_setting
203
+ some_module = Module.new
204
+ assert !some_module.const_defined?(:FOO)
205
+ assert_nothing_raised do
206
+ some_module.constant :FOO, 'bar'
207
+ end
208
+
209
+ assert some_module.const_defined?(:FOO)
210
+ assert_nothing_raised do
211
+ some_module::FOO
212
+ some_module.foo
213
+ end
214
+ assert_equal 'bar', some_module::FOO
215
+ assert_equal 'bar', some_module.foo
216
+
217
+ assert_nothing_raised do
218
+ some_module.constant :FOO, 'baz'
219
+ end
220
+
221
+ assert_equal 'bar', some_module::FOO
222
+ assert_equal 'bar', some_module.foo
223
+ end
224
+
225
+ private
226
+ # For 1.9 compatibility
227
+ def instance_variables_of(object)
228
+ object.instance_variables.map do |instance_variable|
229
+ instance_variable.to_s
230
+ end
231
+ end
232
+
233
+ end
234
+
235
+ class AttributeProxyTest < Test::Unit::TestCase
236
+ class BlindProxyUsingDefaultAttributesHash
237
+ include SelectiveAttributeProxy
238
+ proxy_to :exlusively => false
239
+ end
240
+
241
+ class BlindProxyUsingCustomAttributeHash
242
+ include SelectiveAttributeProxy
243
+ proxy_to :settings
244
+ end
245
+
246
+ class ProxyUsingPassedInAttributeHash
247
+ include SelectiveAttributeProxy
248
+
249
+ def initialize(attributes = {})
250
+ @attributes = attributes
251
+ end
252
+ end
253
+
254
+ class RestrictedProxy
255
+ include SelectiveAttributeProxy
256
+
257
+ private
258
+ def proxiable_attribute?(name)
259
+ %w(foo bar baz).include?(name)
260
+ end
261
+ end
262
+
263
+ class NonExclusiveProxy
264
+ include SelectiveAttributeProxy
265
+ proxy_to :settings, :exclusively => false
266
+ end
267
+
268
+ def test_using_all_defaults
269
+ b = BlindProxyUsingDefaultAttributesHash.new
270
+ assert_nothing_raised do
271
+ b.foo = 'bar'
272
+ end
273
+
274
+ assert_nothing_raised do
275
+ b.foo
276
+ end
277
+
278
+ assert_equal 'bar', b.foo
279
+ end
280
+
281
+ def test_storage_is_autovivified
282
+ b = BlindProxyUsingDefaultAttributesHash.new
283
+ assert_nothing_raised do
284
+ b.send(:attributes)['foo'] = 'bar'
285
+ end
286
+
287
+ assert_nothing_raised do
288
+ b.foo
289
+ end
290
+
291
+ assert_equal 'bar', b.foo
292
+ end
293
+
294
+ def test_limiting_which_attributes_are_proxiable
295
+ r = RestrictedProxy.new
296
+ assert_nothing_raised do
297
+ r.foo = 'bar'
298
+ end
299
+
300
+ assert_nothing_raised do
301
+ r.foo
302
+ end
303
+
304
+ assert_equal 'bar', r.foo
305
+
306
+ assert_raises(NoMethodError) do
307
+ r.quux = 'foo'
308
+ end
309
+
310
+ assert_raises(NoMethodError) do
311
+ r.quux
312
+ end
313
+ end
314
+
315
+ def test_proxying_is_exclusive_by_default
316
+ p = ProxyUsingPassedInAttributeHash.new('foo' => 'bar')
317
+ assert_nothing_raised do
318
+ p.foo
319
+ p.foo = 'baz'
320
+ end
321
+
322
+ assert_equal 'baz', p.foo
323
+
324
+ assert_raises(NoMethodError) do
325
+ p.quux
326
+ end
327
+ end
328
+
329
+ def test_setting_the_proxy_as_non_exclusive
330
+ n = NonExclusiveProxy.new
331
+ assert_nothing_raised do
332
+ n.foo = 'baz'
333
+ end
334
+
335
+ assert_nothing_raised do
336
+ n.foo
337
+ end
338
+
339
+ assert_equal 'baz', n.foo
340
+ end
341
+ end
@@ -0,0 +1,89 @@
1
+ require 'yaml'
2
+
3
+ module AWS
4
+ module S3
5
+ # When this file is loaded, for each fixture file, a module is created within the Fixtures module
6
+ # with the same name as the fixture file. For each fixture in that fixture file, a singleton method is
7
+ # added to the module with the name of the given fixture, returning the value of the fixture.
8
+ #
9
+ # For example:
10
+ #
11
+ # A fixture in <tt>buckets.yml</tt> named <tt>empty_bucket_list</tt> with value <tt><foo>hi!</foo></tt>
12
+ # would be made available like so:
13
+ #
14
+ # Fixtures::Buckets.empty_bucket_list
15
+ # => "<foo>hi!</foo>"
16
+ #
17
+ # Alternatively you can treat the fixture module like a hash
18
+ #
19
+ # Fixtures::Buckets[:empty_bucket_list]
20
+ # => "<foo>hi!</foo>"
21
+ #
22
+ # You can find out all available fixtures by calling
23
+ #
24
+ # Fixtures.fixtures
25
+ # => ["Buckets"]
26
+ #
27
+ # And all the fixtures contained in a given fixture by calling
28
+ #
29
+ # Fixtures::Buckets.fixtures
30
+ # => ["bucket_list_with_more_than_one_bucket", "bucket_list_with_one_bucket", "empty_bucket_list"]
31
+ module Fixtures
32
+ class << self
33
+ def create_fixtures
34
+ files.each do |file|
35
+ create_fixture_for(file)
36
+ end
37
+ end
38
+
39
+ def create_fixture_for(file)
40
+ fixtures = YAML.load_file(path(file))
41
+ fixture_module = Module.new
42
+
43
+ fixtures.each do |name, value|
44
+ fixture_module.module_eval(<<-EVAL, __FILE__, __LINE__)
45
+ def #{name}
46
+ #{value.inspect}
47
+ end
48
+ module_function :#{name}
49
+ EVAL
50
+ end
51
+
52
+ fixture_module.module_eval(<<-EVAL, __FILE__, __LINE__)
53
+ module_function
54
+
55
+ def fixtures
56
+ #{fixtures.keys.sort.inspect}
57
+ end
58
+
59
+ def [](name)
60
+ send(name) if fixtures.include?(name.to_s)
61
+ end
62
+ EVAL
63
+
64
+ const_set(module_name(file), fixture_module)
65
+ end
66
+
67
+ def fixtures
68
+ constants.sort
69
+ end
70
+
71
+ private
72
+
73
+ def files
74
+ Dir.glob(File.dirname(__FILE__) + '/fixtures/*.yml').map {|fixture| File.basename(fixture)}
75
+ end
76
+
77
+ def module_name(file_name)
78
+ File.basename(file_name, '.*').capitalize
79
+ end
80
+
81
+ def path(file_name)
82
+ File.join(File.dirname(__FILE__), 'fixtures', file_name)
83
+ end
84
+ end
85
+
86
+ create_fixtures
87
+ end
88
+ end
89
+ end