aws-s3 0.1.0

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 (55) hide show
  1. data/COPYING +19 -0
  2. data/INSTALL +35 -0
  3. data/README +529 -0
  4. data/Rakefile +284 -0
  5. data/bin/s3sh +4 -0
  6. data/bin/setup.rb +10 -0
  7. data/lib/aws/s3.rb +64 -0
  8. data/lib/aws/s3/acl.rb +631 -0
  9. data/lib/aws/s3/authentication.rb +218 -0
  10. data/lib/aws/s3/base.rb +232 -0
  11. data/lib/aws/s3/bittorrent.rb +58 -0
  12. data/lib/aws/s3/bucket.rb +323 -0
  13. data/lib/aws/s3/connection.rb +212 -0
  14. data/lib/aws/s3/error.rb +69 -0
  15. data/lib/aws/s3/exceptions.rb +130 -0
  16. data/lib/aws/s3/extensions.rb +186 -0
  17. data/lib/aws/s3/logging.rb +163 -0
  18. data/lib/aws/s3/object.rb +565 -0
  19. data/lib/aws/s3/owner.rb +44 -0
  20. data/lib/aws/s3/parsing.rb +138 -0
  21. data/lib/aws/s3/response.rb +180 -0
  22. data/lib/aws/s3/service.rb +43 -0
  23. data/lib/aws/s3/version.rb +12 -0
  24. data/support/faster-xml-simple/lib/faster_xml_simple.rb +115 -0
  25. data/support/faster-xml-simple/test/regression_test.rb +16 -0
  26. data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +22 -0
  27. data/support/rdoc/code_info.rb +211 -0
  28. data/test/acl_test.rb +243 -0
  29. data/test/authentication_test.rb +96 -0
  30. data/test/base_test.rb +143 -0
  31. data/test/bucket_test.rb +48 -0
  32. data/test/connection_test.rb +120 -0
  33. data/test/error_test.rb +75 -0
  34. data/test/extensions_test.rb +282 -0
  35. data/test/fixtures.rb +89 -0
  36. data/test/fixtures/buckets.yml +102 -0
  37. data/test/fixtures/errors.yml +34 -0
  38. data/test/fixtures/headers.yml +3 -0
  39. data/test/fixtures/logging.yml +15 -0
  40. data/test/fixtures/policies.yml +16 -0
  41. data/test/logging_test.rb +36 -0
  42. data/test/mocks/base.rb +89 -0
  43. data/test/object_test.rb +177 -0
  44. data/test/parsing_test.rb +82 -0
  45. data/test/remote/acl_test.rb +117 -0
  46. data/test/remote/bittorrent_test.rb +45 -0
  47. data/test/remote/bucket_test.rb +127 -0
  48. data/test/remote/logging_test.rb +82 -0
  49. data/test/remote/object_test.rb +267 -0
  50. data/test/remote/test_file.data +0 -0
  51. data/test/remote/test_helper.rb +30 -0
  52. data/test/response_test.rb +70 -0
  53. data/test/service_test.rb +26 -0
  54. data/test/test_helper.rb +82 -0
  55. metadata +125 -0
@@ -0,0 +1,282 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class HashExtensionsTest < Test::Unit::TestCase
4
+ def test_to_query_string
5
+ # Because hashes aren't ordered, I'm mostly testing against hashes with just one key
6
+ symbol_keys = {:one => 1}
7
+ string_keys = {'one' => 1}
8
+ expected = '?one=1'
9
+ [symbol_keys, string_keys].each do |hash|
10
+ assert_equal expected, hash.to_query_string
11
+ end
12
+ end
13
+
14
+ def test_empty_hash_returns_no_query_string
15
+ assert_equal '', {}.to_query_string
16
+ end
17
+
18
+ def test_include_question_mark
19
+ hash = {:one => 1}
20
+ assert_equal '?one=1', hash.to_query_string
21
+ assert_equal 'one=1', hash.to_query_string(false)
22
+ end
23
+
24
+ def test_elements_joined_by_ampersand
25
+ hash = {:one => 1, :two => 2}
26
+ qs = hash.to_query_string
27
+ assert qs['one=1&two=2'] || qs['two=2&one=1']
28
+ end
29
+
30
+ def test_keys_and_values_are_url_encoded
31
+ hash = {'key with spaces' => 'value with spaces'}
32
+ assert_equal '?key+with+spaces=value+with+spaces', hash.to_query_string
33
+ end
34
+
35
+ def test_normalized_options
36
+ expectations = [
37
+ [{:foo_bar => 1}, {'foo-bar' => '1'}],
38
+ [{'foo_bar' => 1}, {'foo-bar' => '1'}],
39
+ [{'foo-bar' => 1}, {'foo-bar' => '1'}],
40
+ [{}, {}]
41
+ ]
42
+
43
+ expectations.each do |(before, after)|
44
+ assert_equal after, before.to_normalized_options
45
+ end
46
+ end
47
+ end
48
+
49
+ class StringExtensionsTest < Test::Unit::TestCase
50
+ def test_previous
51
+ expectations = {'abc' => 'abb', '123' => '122', '1' => '0'}
52
+ expectations.each do |before, after|
53
+ assert_equal after, before.previous
54
+ end
55
+ end
56
+
57
+ def test_to_header
58
+ transformations = {
59
+ 'foo' => 'foo',
60
+ :foo => 'foo',
61
+ 'foo-bar' => 'foo-bar',
62
+ 'foo_bar' => 'foo-bar',
63
+ :foo_bar => 'foo-bar',
64
+ 'Foo-Bar' => 'foo-bar',
65
+ 'Foo_Bar' => 'foo-bar'
66
+ }
67
+
68
+ transformations.each do |before, after|
69
+ assert_equal after, before.to_header
70
+ end
71
+ end
72
+ end
73
+
74
+ class KerneltExtensionsTest < Test::Unit::TestCase
75
+ class Foo
76
+ def foo
77
+ __method__
78
+ end
79
+
80
+ def bar
81
+ foo
82
+ end
83
+
84
+ def baz
85
+ bar
86
+ end
87
+ end
88
+
89
+ class Bar
90
+ def foo
91
+ calling_method
92
+ end
93
+
94
+ def bar
95
+ calling_method
96
+ end
97
+
98
+ def calling_method
99
+ __method__(1)
100
+ end
101
+ end
102
+
103
+ def test___method___works_regardless_of_nesting
104
+ f = Foo.new
105
+ [:foo, :bar, :baz].each do |method|
106
+ assert_equal 'foo', f.send(method)
107
+ end
108
+ end
109
+
110
+ def test___method___depth
111
+ b = Bar.new
112
+ assert_equal 'foo', b.foo
113
+ assert_equal 'bar', b.bar
114
+ end
115
+ end
116
+
117
+ class ModuleExtensionsTest < Test::Unit::TestCase
118
+ class Foo
119
+ def foo(reload = false)
120
+ memoize(reload) do
121
+ Time.now
122
+ end
123
+ end
124
+
125
+ def bar(reload = false)
126
+ memoize(reload, :baz) do
127
+ Time.now
128
+ end
129
+ end
130
+ end
131
+
132
+ def setup
133
+ @instance = Foo.new
134
+ end
135
+
136
+ def test_memoize
137
+ cached_result = @instance.foo
138
+ assert_equal cached_result, @instance.foo
139
+ assert_equal cached_result, @instance.send(:instance_variable_get, :@foo)
140
+ assert_not_equal cached_result, @instance.foo(:reload)
141
+ end
142
+
143
+ def test_customizing_storage
144
+ cached_result = @instance.bar
145
+ assert_equal cached_result, @instance.bar
146
+ assert_equal cached_result, @instance.send(:instance_variable_get, :@baz)
147
+ assert_nil @instance.send(:instance_variable_get, :@bar)
148
+ end
149
+
150
+ def test_constant_setting
151
+ some_module = Module.new
152
+ assert !some_module.const_defined?(:FOO)
153
+ assert_nothing_raised do
154
+ some_module.constant :FOO, 'bar'
155
+ end
156
+
157
+ assert some_module.const_defined?(:FOO)
158
+ assert_nothing_raised do
159
+ some_module::FOO
160
+ some_module.foo
161
+ end
162
+ assert_equal 'bar', some_module::FOO
163
+ assert_equal 'bar', some_module.foo
164
+
165
+ assert_nothing_raised do
166
+ some_module.constant :FOO, 'baz'
167
+ end
168
+
169
+ assert_equal 'bar', some_module::FOO
170
+ assert_equal 'bar', some_module.foo
171
+ end
172
+
173
+
174
+ end
175
+
176
+ class AttributeProxyTest < Test::Unit::TestCase
177
+ class BlindProxyUsingDefaultAttributesHash
178
+ include SelectiveAttributeProxy
179
+ proxy_to :exlusively => false
180
+ end
181
+
182
+ class BlindProxyUsingCustomAttributeHash
183
+ include SelectiveAttributeProxy
184
+ proxy_to :settings
185
+ end
186
+
187
+ class ProxyUsingPassedInAttributeHash
188
+ include SelectiveAttributeProxy
189
+
190
+ def initialize(attributes = {})
191
+ @attributes = attributes
192
+ end
193
+ end
194
+
195
+ class RestrictedProxy
196
+ include SelectiveAttributeProxy
197
+
198
+ private
199
+ def proxiable_attribute?(name)
200
+ %w(foo bar baz).include?(name)
201
+ end
202
+ end
203
+
204
+ class NonExclusiveProxy
205
+ include SelectiveAttributeProxy
206
+ proxy_to :settings, :exclusively => false
207
+ end
208
+
209
+ def test_using_all_defaults
210
+ b = BlindProxyUsingDefaultAttributesHash.new
211
+ assert_nothing_raised do
212
+ b.foo = 'bar'
213
+ end
214
+
215
+ assert_nothing_raised do
216
+ b.foo
217
+ end
218
+
219
+ assert_equal 'bar', b.foo
220
+ end
221
+
222
+ def test_storage_is_autovivified
223
+ b = BlindProxyUsingDefaultAttributesHash.new
224
+ assert_nothing_raised do
225
+ b.send(:attributes)['foo'] = 'bar'
226
+ end
227
+
228
+ assert_nothing_raised do
229
+ b.foo
230
+ end
231
+
232
+ assert_equal 'bar', b.foo
233
+ end
234
+
235
+ def test_limiting_which_attributes_are_proxiable
236
+ r = RestrictedProxy.new
237
+ assert_nothing_raised do
238
+ r.foo = 'bar'
239
+ end
240
+
241
+ assert_nothing_raised do
242
+ r.foo
243
+ end
244
+
245
+ assert_equal 'bar', r.foo
246
+
247
+ assert_raises(NoMethodError) do
248
+ r.quux = 'foo'
249
+ end
250
+
251
+ assert_raises(NoMethodError) do
252
+ r.quux
253
+ end
254
+ end
255
+
256
+ def test_proxying_is_exclusive_by_default
257
+ p = ProxyUsingPassedInAttributeHash.new('foo' => 'bar')
258
+ assert_nothing_raised do
259
+ p.foo
260
+ p.foo = 'baz'
261
+ end
262
+
263
+ assert_equal 'baz', p.foo
264
+
265
+ assert_raises(NoMethodError) do
266
+ p.quux
267
+ end
268
+ end
269
+
270
+ def test_setting_the_proxy_as_non_exclusive
271
+ n = NonExclusiveProxy.new
272
+ assert_nothing_raised do
273
+ n.foo = 'baz'
274
+ end
275
+
276
+ assert_nothing_raised do
277
+ n.foo
278
+ end
279
+
280
+ assert_equal 'baz', n.foo
281
+ end
282
+ 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
@@ -0,0 +1,102 @@
1
+ empty_bucket_list: >
2
+ <ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
3
+ <Owner>
4
+ <ID>ab00c3106e091f8fe23154c85678cda66628adb330bc00f02cf4a1c36d76bc48</ID>
5
+ <DisplayName>amazon</DisplayName>
6
+ </Owner>
7
+ <Buckets/>
8
+ </ListAllMyBucketsResult>
9
+
10
+
11
+ bucket_list_with_one_bucket: >
12
+ <ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
13
+ <Owner>
14
+ <ID>ab00c3106e091f8fe23154c85678cda66628adb330bc00f02cf4a1c36d76bc48</ID>
15
+ <DisplayName>amazon</DisplayName>
16
+ </Owner>
17
+ <Buckets>
18
+ <Bucket>
19
+ <Name>marcel_molina</Name>
20
+ <CreationDate>2006-10-04T15:58:38.000Z</CreationDate>
21
+ </Bucket>
22
+ </Buckets>
23
+ </ListAllMyBucketsResult>
24
+
25
+
26
+ bucket_list_with_more_than_one_bucket: >
27
+ <ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
28
+ <Owner>
29
+ <ID>ab00c3106e091f8fe23154c85678cda66628adb330bc00f02cf4a1c36d76bc48</ID>
30
+ <DisplayName>amazon</DisplayName>
31
+ </Owner>
32
+ <Buckets>
33
+ <Bucket>
34
+ <Name>marcel_molina</Name>
35
+ <CreationDate>2006-10-04T15:58:38.000Z</CreationDate>
36
+ </Bucket>
37
+ <Bucket>
38
+ <Name>marcel_molina_jr</Name>
39
+ <CreationDate>2006-10-04T16:01:30.000Z</CreationDate>
40
+ </Bucket>
41
+ </Buckets>
42
+ </ListAllMyBucketsResult>
43
+
44
+ empty_bucket: >
45
+ <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
46
+ <Name>marcel_molina</Name>
47
+ <Prefix></Prefix>
48
+ <Marker></Marker>
49
+ <MaxKeys>1000</MaxKeys>
50
+ <IsTruncated>false</IsTruncated>
51
+ </ListBucketResult>
52
+
53
+ bucket_with_one_key: >
54
+ <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
55
+ <Name>marcel_molina</Name>
56
+ <Prefix></Prefix>
57
+ <Marker></Marker>
58
+ <MaxKeys>1000</MaxKeys>
59
+ <IsTruncated>false</IsTruncated>
60
+ <Contents>
61
+ <Key>tongue_overload.jpg</Key>
62
+ <LastModified>2006-10-05T02:42:22.000Z</LastModified>
63
+ <ETag>&quot;f21f7c4e8ea6e34b268887b07d6da745&quot;</ETag>
64
+ <Size>60673</Size>
65
+ <Owner>
66
+ <ID>bb2041a25975c3d4ce9775fe9e93e5b77a6a9fad97dc7e00686191f3790b13f1</ID>
67
+ <DisplayName>mmolina@onramp.net</DisplayName>
68
+ </Owner>
69
+ <StorageClass>STANDARD</StorageClass>
70
+ </Contents>
71
+ </ListBucketResult>
72
+
73
+ bucket_with_more_than_one_key: >
74
+ <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
75
+ <Name>marcel_molina</Name>
76
+ <Prefix></Prefix>
77
+ <Marker></Marker>
78
+ <MaxKeys>1000</MaxKeys>
79
+ <IsTruncated>false</IsTruncated>
80
+ <Contents>
81
+ <Key>beluga_baby.jpg</Key>
82
+ <LastModified>2006-10-05T02:55:10.000Z</LastModified>
83
+ <ETag>&quot;b2453d4a39a7387674a8c505112a2f0b&quot;</ETag>
84
+ <Size>35807</Size>
85
+ <Owner>
86
+ <ID>bb2041a25975c3d4ce9775fe9e93e5b77a6a9fad97dc7e00686191f3790b13f1</ID>
87
+ <DisplayName>mmolina@onramp.net</DisplayName>
88
+ </Owner>
89
+ <StorageClass>STANDARD</StorageClass>
90
+ </Contents>
91
+ <Contents>
92
+ <Key>tongue_overload.jpg</Key>
93
+ <LastModified>2006-10-05T02:42:22.000Z</LastModified>
94
+ <ETag>&quot;f21f7c4e8ea6e34b268887b07d6da745&quot;</ETag>
95
+ <Size>60673</Size>
96
+ <Owner>
97
+ <ID>bb2041a25975c3d4ce9775fe9e93e5b77a6a9fad97dc7e00686191f3790b13f1</ID>
98
+ <DisplayName>mmolina@onramp.net</DisplayName>
99
+ </Owner>
100
+ <StorageClass>STANDARD</StorageClass>
101
+ </Contents>
102
+ </ListBucketResult>