jaf-s3 0.6.3.1286550476

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 +545 -0
  4. data/Rakefile +334 -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 +278 -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 +340 -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 +340 -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 +200 -0
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RegressionTest < FasterXSTest
4
+ def test_content_nil_regressions
5
+ expected = {"asdf"=>{"jklsemicolon"=>{}}}
6
+ assert_equal expected, FasterXmlSimple.xml_in("<asdf><jklsemicolon /></asdf>")
7
+ assert_equal expected, FasterXmlSimple.xml_in("<asdf><jklsemicolon /></asdf>", 'forcearray'=>['asdf'])
8
+ end
9
+
10
+ def test_s3_regression
11
+ str = File.read("test/fixtures/test-7.xml")
12
+ assert_nil FasterXmlSimple.xml_in(str)["AccessControlPolicy"]["AccessControlList"]["__content__"]
13
+ end
14
+
15
+ def test_xml_simple_transparency
16
+ assert_equal XmlSimple.xml_in("<asdf />"), FasterXmlSimple.xml_in("<asdf />")
17
+ end
18
+
19
+ def test_suppress_empty_variations
20
+ str = "<asdf><fdsa /></asdf>"
21
+
22
+ assert_equal Hash.new, FasterXmlSimple.xml_in(str)["asdf"]["fdsa"]
23
+ assert_nil FasterXmlSimple.xml_in(str, 'suppressempty'=>nil)["asdf"]["fdsa"]
24
+ assert_equal '', FasterXmlSimple.xml_in(str, 'suppressempty'=>'')["asdf"]["fdsa"]
25
+ assert !FasterXmlSimple.xml_in(str, 'suppressempty'=>true)["asdf"].has_key?("fdsa")
26
+ end
27
+
28
+ def test_empty_string_doesnt_crash
29
+ assert_raise(XML::Parser::ParseError) do
30
+ silence_stderr do
31
+ FasterXmlSimple.xml_in('')
32
+ end
33
+ end
34
+ end
35
+
36
+ def test_keeproot_false
37
+ str = "<asdf><fdsa>1</fdsa></asdf>"
38
+ expected = {"fdsa"=>"1"}
39
+ assert_equal expected, FasterXmlSimple.xml_in(str, 'keeproot'=>false)
40
+ end
41
+
42
+ def test_keeproot_false_with_force_content
43
+ str = "<asdf><fdsa>1</fdsa></asdf>"
44
+ expected = {"fdsa"=>{"__content__"=>"1"}}
45
+ assert_equal expected, FasterXmlSimple.xml_in(str, 'keeproot'=>false, 'forcecontent'=>true)
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+
2
+ require 'test/unit'
3
+ require 'faster_xml_simple'
4
+
5
+ class FasterXSTest < Test::Unit::TestCase
6
+ def default_test
7
+ end
8
+
9
+ def silence_stderr
10
+ str = STDERR.dup
11
+ STDERR.reopen("/dev/null")
12
+ STDERR.sync=true
13
+ yield
14
+ ensure
15
+ STDERR.reopen(str)
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'yaml'
3
+
4
+ class XmlSimpleComparisonTest < FasterXSTest
5
+
6
+ # Define test methods
7
+
8
+ Dir["test/fixtures/test-*.xml"].each do |file_name|
9
+ xml_file_name = file_name
10
+ method_name = File.basename(file_name, ".xml").gsub('-', '_')
11
+ yml_file_name = file_name.gsub('xml', 'yml')
12
+ rails_yml_file_name = file_name.gsub('xml', 'rails.yml')
13
+ class_eval <<-EOV, __FILE__, __LINE__
14
+ def #{method_name}
15
+ assert_equal YAML.load(File.read('#{yml_file_name}')),
16
+ FasterXmlSimple.xml_in(File.read('#{xml_file_name}'), default_options )
17
+ end
18
+
19
+ def #{method_name}_rails
20
+ assert_equal YAML.load(File.read('#{rails_yml_file_name}')),
21
+ FasterXmlSimple.xml_in(File.read('#{xml_file_name}'), rails_options)
22
+ end
23
+ EOV
24
+ end
25
+
26
+ def default_options
27
+ {
28
+ 'keeproot' => true,
29
+ 'contentkey' => '__content__',
30
+ 'forcecontent' => true,
31
+ 'suppressempty' => nil,
32
+ 'forcearray' => ['something-else']
33
+ }
34
+ end
35
+
36
+ def rails_options
37
+ {
38
+ 'forcearray' => false,
39
+ 'forcecontent' => true,
40
+ 'keeproot' => true,
41
+ 'contentkey' => '__content__'
42
+ }
43
+ end
44
+
45
+
46
+ end
@@ -0,0 +1,211 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rdoc/rdoc'
4
+
5
+ module RDoc
6
+ class CodeInfo
7
+ class << self
8
+ def parse(wildcard_pattern = nil)
9
+ @info_for_corpus = parse_files(wildcard_pattern)
10
+ end
11
+
12
+ def for(constant)
13
+ new(constant).info
14
+ end
15
+
16
+ def info_for_corpus
17
+ raise RuntimeError, "You must first generate a corpus to search by using RDoc::CodeInfo.parse" unless @info_for_corpus
18
+ @info_for_corpus
19
+ end
20
+
21
+ def parsed_files
22
+ info_for_corpus.map {|info| info.file_absolute_name}
23
+ end
24
+
25
+ def files_to_parse
26
+ @files_to_parse ||= Rake::FileList.new
27
+ end
28
+
29
+ private
30
+ def parse_files(pattern)
31
+ files = pattern ? Rake::FileList[pattern] : files_to_parse
32
+ options = Options.instance
33
+ options.parse(files << '-q', RDoc::GENERATORS)
34
+ rdoc.send(:parse_files, options)
35
+ end
36
+
37
+ def rdoc
38
+ TopLevel.reset
39
+ rdoc = RDoc.new
40
+ stats = Stats.new
41
+ # We don't want any output so we'll override the print method
42
+ stats.instance_eval { def print; nil end }
43
+ rdoc.instance_variable_set(:@stats, stats)
44
+ rdoc
45
+ end
46
+ end
47
+
48
+ attr_reader :info
49
+ def initialize(location)
50
+ @location = CodeLocation.new(location)
51
+ find_constant
52
+ find_method if @location.has_method?
53
+ end
54
+
55
+ private
56
+ attr_reader :location
57
+ attr_writer :info
58
+ def find_constant
59
+ parts = location.namespace_parts
60
+ self.class.info_for_corpus.each do |file_info|
61
+ @info = parts.inject(file_info) do |result, const_part|
62
+ (result.find_module_named(const_part) || result.find_class_named(const_part)) || break
63
+ end
64
+ return if info
65
+ end
66
+ end
67
+
68
+ def find_method
69
+ return unless info
70
+ self.info = info.method_list.detect do |method_info|
71
+ next unless method_info.name == location.method_name
72
+ if location.class_method?
73
+ method_info.singleton
74
+ elsif location.instance_method?
75
+ !method_info.singleton
76
+ else
77
+ true
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ class CodeLocation
84
+ attr_reader :location
85
+
86
+ def initialize(location)
87
+ @location = location
88
+ end
89
+
90
+ def parts
91
+ location.split(/::|\.|#/)
92
+ end
93
+
94
+ def namespace_parts
95
+ has_method? ? parts[0...-1] : parts
96
+ end
97
+
98
+ def has_method?
99
+ ('a'..'z').include?(parts.last[0, 1])
100
+ end
101
+
102
+ def instance_method?
103
+ !location['#'].nil?
104
+ end
105
+
106
+ def class_method?
107
+ has_method? && !location[/#|\./]
108
+ end
109
+
110
+ def method_name
111
+ parts.last if has_method?
112
+ end
113
+ end
114
+ end
115
+
116
+ if __FILE__ == $0
117
+ require 'test/unit'
118
+ class CodeInfoTest < Test::Unit::TestCase
119
+ def setup
120
+ RDoc::CodeInfo.parse(__FILE__)
121
+ end
122
+
123
+ def test_constant_lookup
124
+ assert RDoc::CodeInfo.for('RDoc')
125
+
126
+ info = RDoc::CodeInfo.for('RDoc::CodeInfo')
127
+ assert_equal 'CodeInfo', info.name
128
+ end
129
+
130
+ def test_method_lookup
131
+ {'RDoc::CodeInfo.parse' => true,
132
+ 'RDoc::CodeInfo::parse' => true,
133
+ 'RDoc::CodeInfo#parse' => false,
134
+ 'RDoc::CodeInfo.find_method' => true,
135
+ 'RDoc::CodeInfo::find_method' => false,
136
+ 'RDoc::CodeInfo#find_method' => true,
137
+ 'RDoc::CodeInfo#no_such_method' => false,
138
+ 'RDoc::NoSuchConst#foo' => false}.each do |location, result_of_lookup|
139
+ assert_equal result_of_lookup, !RDoc::CodeInfo.for(location).nil?
140
+ end
141
+ end
142
+ end
143
+
144
+ class CodeLocationTest < Test::Unit::TestCase
145
+ def test_parts
146
+ {'Foo' => %w(Foo),
147
+ 'Foo::Bar' => %w(Foo Bar),
148
+ 'Foo::Bar#baz' => %w(Foo Bar baz),
149
+ 'Foo::Bar.baz' => %w(Foo Bar baz),
150
+ 'Foo::Bar::baz' => %w(Foo Bar baz),
151
+ 'Foo::Bar::Baz' => %w(Foo Bar Baz)}.each do |location, parts|
152
+ assert_equal parts, RDoc::CodeLocation.new(location).parts
153
+ end
154
+ end
155
+
156
+ def test_namespace_parts
157
+ {'Foo' => %w(Foo),
158
+ 'Foo::Bar' => %w(Foo Bar),
159
+ 'Foo::Bar#baz' => %w(Foo Bar),
160
+ 'Foo::Bar.baz' => %w(Foo Bar),
161
+ 'Foo::Bar::baz' => %w(Foo Bar),
162
+ 'Foo::Bar::Baz' => %w(Foo Bar Baz)}.each do |location, namespace_parts|
163
+ assert_equal namespace_parts, RDoc::CodeLocation.new(location).namespace_parts
164
+ end
165
+ end
166
+
167
+ def test_has_method?
168
+ {'Foo' => false,
169
+ 'Foo::Bar' => false,
170
+ 'Foo::Bar#baz' => true,
171
+ 'Foo::Bar.baz' => true,
172
+ 'Foo::Bar::baz' => true,
173
+ 'Foo::Bar::Baz' => false}.each do |location, has_method_result|
174
+ assert_equal has_method_result, RDoc::CodeLocation.new(location).has_method?
175
+ end
176
+ end
177
+
178
+ def test_instance_method?
179
+ {'Foo' => false,
180
+ 'Foo::Bar' => false,
181
+ 'Foo::Bar#baz' => true,
182
+ 'Foo::Bar.baz' => false,
183
+ 'Foo::Bar::baz' => false,
184
+ 'Foo::Bar::Baz' => false}.each do |location, is_instance_method|
185
+ assert_equal is_instance_method, RDoc::CodeLocation.new(location).instance_method?
186
+ end
187
+ end
188
+
189
+ def test_class_method?
190
+ {'Foo' => false,
191
+ 'Foo::Bar' => false,
192
+ 'Foo::Bar#baz' => false,
193
+ 'Foo::Bar.baz' => false,
194
+ 'Foo::Bar::baz' => true,
195
+ 'Foo::Bar::Baz' => false}.each do |location, is_class_method|
196
+ assert_equal is_class_method, RDoc::CodeLocation.new(location).class_method?
197
+ end
198
+ end
199
+
200
+ def test_method_name
201
+ {'Foo' => nil,
202
+ 'Foo::Bar' => nil,
203
+ 'Foo::Bar#baz' => 'baz',
204
+ 'Foo::Bar.baz' => 'baz',
205
+ 'Foo::Bar::baz' => 'baz',
206
+ 'Foo::Bar::Baz' => nil}.each do |location, method_name|
207
+ assert_equal method_name, RDoc::CodeLocation.new(location).method_name
208
+ end
209
+ end
210
+ end
211
+ end
data/test/acl_test.rb ADDED
@@ -0,0 +1,254 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class PolicyReadingTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @policy = prepare_policy
7
+ end
8
+
9
+ def test_policy_owner
10
+ assert_kind_of Owner, @policy.owner
11
+ assert_equal 'bb2041a25975c3d4ce9775fe9e93e5b77a6a9fad97dc7e00686191f3790b13f1', @policy.owner.id
12
+ assert_equal 'mmolina@onramp.net', @policy.owner.display_name
13
+ end
14
+
15
+ def test_grants
16
+ assert @policy.grants
17
+ assert !@policy.grants.empty?
18
+ grant = @policy.grants.first
19
+ assert_kind_of ACL::Grant, grant
20
+ assert_equal 'FULL_CONTROL', grant.permission
21
+ end
22
+
23
+ def test_grants_have_grantee
24
+ grant = @policy.grants.first
25
+ assert grantee = grant.grantee
26
+ assert_kind_of ACL::Grantee, grantee
27
+ assert_equal 'bb2041a25975c3d4ce9775fe9e93e5b77a6a9fad97dc7e00686191f3790b13f1', grantee.id
28
+ assert_equal 'mmolina@onramp.net', grantee.display_name
29
+ assert_equal 'CanonicalUser', grantee.type
30
+ end
31
+
32
+ def test_grantee_always_responds_to_email_address
33
+ assert_nothing_raised do
34
+ @policy.grants.first.grantee.email_address
35
+ end
36
+ end
37
+
38
+ private
39
+ def prepare_policy
40
+ ACL::Policy.new(parsed_policy)
41
+ end
42
+
43
+ def parsed_policy
44
+ Parsing::XmlParser.new Fixtures::Policies.policy_with_one_grant
45
+ end
46
+ end
47
+
48
+ class PolicyWritingTest < PolicyReadingTest
49
+
50
+ def setup
51
+ policy = prepare_policy
52
+ # Dump the policy to xml and retranslate it back from the xml then run all the tests in the xml reading
53
+ # test. This round tripping indirectly asserts that the original xml document is the same as the to_xml
54
+ # dump.
55
+ @policy = ACL::Policy.new(Parsing::XmlParser.new(policy.to_xml))
56
+ end
57
+
58
+ end
59
+
60
+ class PolicyTest < Test::Unit::TestCase
61
+ def test_building_policy_by_hand
62
+ policy = grant = grantee = nil
63
+ assert_nothing_raised do
64
+ policy = ACL::Policy.new
65
+ grant = ACL::Grant.new
66
+ grantee = ACL::Grantee.new
67
+ grantee.email_address = 'marcel@vernix.org'
68
+ grant.permission = 'READ_ACP'
69
+ grant.grantee = grantee
70
+ policy.grants << grant
71
+ policy.owner = Owner.new('id' => '123456789', 'display_name' => 'noradio')
72
+ end
73
+
74
+ assert_nothing_raised do
75
+ policy.to_xml
76
+ end
77
+
78
+ assert !policy.grants.empty?
79
+ assert_equal 1, policy.grants.size
80
+ assert_equal 'READ_ACP', policy.grants.first.permission
81
+ end
82
+
83
+ def test_include?
84
+ policy = ACL::Policy.new(Parsing::XmlParser.new(Fixtures::Policies.policy_with_one_grant))
85
+ assert !policy.grants.include?(:public_read)
86
+ policy.grants << ACL::Grant.grant(:public_read)
87
+ assert policy.grants.include?(:public_read)
88
+
89
+ assert policy.grants.include?(ACL::Grant.grant(:public_read))
90
+ [false, 1, '1'].each do |non_grant|
91
+ assert !policy.grants.include?(non_grant)
92
+ end
93
+ end
94
+
95
+ def test_delete
96
+ policy = ACL::Policy.new(Parsing::XmlParser.new(Fixtures::Policies.policy_with_one_grant))
97
+ policy.grants << ACL::Grant.grant(:public_read)
98
+ assert policy.grants.include?(:public_read)
99
+ assert policy.grants.delete(:public_read)
100
+ assert !policy.grants.include?(:public_read)
101
+ [false, 1, '1'].each do |non_grant|
102
+ assert_nil policy.grants.delete(non_grant)
103
+ end
104
+ end
105
+
106
+ def test_grant_list_comparison
107
+ policy = ACL::Policy.new
108
+ policy2 = ACL::Policy.new
109
+
110
+ grant_names = [:public_read, :public_read_acp, :authenticated_write]
111
+ grant_names.each {|grant_name| policy.grants << ACL::Grant.grant(grant_name)}
112
+ grant_names.reverse_each {|grant_name| policy2.grants << ACL::Grant.grant(grant_name)}
113
+
114
+ assert_equal policy.grants, policy2.grants
115
+ end
116
+ end
117
+
118
+ class GrantTest < Test::Unit::TestCase
119
+ def test_permission_must_be_valid
120
+ grant = ACL::Grant.new
121
+ assert_nothing_raised do
122
+ grant.permission = 'READ_ACP'
123
+ end
124
+
125
+ assert_raises(InvalidAccessControlLevel) do
126
+ grant.permission = 'not a valid permission'
127
+ end
128
+ end
129
+
130
+ def test_stock_grants
131
+ assert_raises(ArgumentError) do
132
+ ACL::Grant.grant :this_is_not_a_stock_grant
133
+ end
134
+
135
+ grant = nil
136
+ assert_nothing_raised do
137
+ grant = ACL::Grant.grant(:public_read)
138
+ end
139
+
140
+ assert grant
141
+ assert_kind_of ACL::Grant, grant
142
+ assert_equal 'READ', grant.permission
143
+ assert grant.grantee
144
+ assert_kind_of ACL::Grantee, grant.grantee
145
+ assert_equal 'AllUsers', grant.grantee.group
146
+ end
147
+ end
148
+
149
+ class GranteeTest < Test::Unit::TestCase
150
+ def test_type_inference
151
+ grantee = ACL::Grantee.new
152
+
153
+ assert_nothing_raised do
154
+ grantee.type
155
+ end
156
+
157
+ assert_nil grantee.type
158
+ grantee.group = 'AllUsers'
159
+ assert_equal 'AllUsers', grantee.group
160
+ assert_equal 'Group', grantee.type
161
+ grantee.email_address = 'marcel@vernix.org'
162
+ assert_equal 'AmazonCustomerByEmail', grantee.type
163
+ grantee.display_name = 'noradio'
164
+ assert_equal 'AmazonCustomerByEmail', grantee.type
165
+ grantee.id = '123456789'
166
+ assert_equal 'CanonicalUser', grantee.type
167
+ end
168
+
169
+ def test_type_is_extracted_if_present
170
+ grantee = ACL::Grantee.new('xsi:type' => 'CanonicalUser')
171
+ assert_equal 'CanonicalUser', grantee.type
172
+ end
173
+
174
+ def test_type_representation
175
+ grantee = ACL::Grantee.new('uri' => 'http://acs.amazonaws.com/groups/global/AllUsers')
176
+
177
+ assert_equal 'AllUsers Group', grantee.type_representation
178
+ grantee.group = 'AuthenticatedUsers'
179
+ assert_equal 'AuthenticatedUsers Group', grantee.type_representation
180
+ grantee.email_address = 'marcel@vernix.org'
181
+ assert_equal 'marcel@vernix.org', grantee.type_representation
182
+ grantee.display_name = 'noradio'
183
+ grantee.id = '123456789'
184
+ assert_equal 'noradio', grantee.type_representation
185
+ end
186
+ end
187
+
188
+ class ACLOptionProcessorTest < Test::Unit::TestCase
189
+ def test_empty_options
190
+ options = {}
191
+ assert_nothing_raised do
192
+ process! options
193
+ end
194
+ assert_equal({}, options)
195
+ end
196
+
197
+ def test_invalid_access_level
198
+ options = {:access => :foo}
199
+ assert_raises(InvalidAccessControlLevel) do
200
+ process! options
201
+ end
202
+ end
203
+
204
+ def test_valid_access_level_is_normalized
205
+ valid_access_levels = [
206
+ {:access => :private},
207
+ {'access' => 'private'},
208
+ {:access => 'private'},
209
+ {'access' => :private},
210
+ {'x-amz-acl' => 'private'},
211
+ {:x_amz_acl => :private},
212
+ {:x_amz_acl => 'private'},
213
+ {'x_amz_acl' => :private}
214
+ ]
215
+
216
+ valid_access_levels.each do |options|
217
+ assert_nothing_raised do
218
+ process! options
219
+ end
220
+ assert_equal 'private', acl(options)
221
+ end
222
+
223
+ valid_hyphenated_access_levels = [
224
+ {:access => :public_read},
225
+ {'access' => 'public_read'},
226
+ {'access' => 'public-read'},
227
+ {:access => 'public_read'},
228
+ {:access => 'public-read'},
229
+ {'access' => :public_read},
230
+
231
+ {'x-amz-acl' => 'public_read'},
232
+ {:x_amz_acl => :public_read},
233
+ {:x_amz_acl => 'public_read'},
234
+ {:x_amz_acl => 'public-read'},
235
+ {'x_amz_acl' => :public_read}
236
+ ]
237
+
238
+ valid_hyphenated_access_levels.each do |options|
239
+ assert_nothing_raised do
240
+ process! options
241
+ end
242
+ assert_equal 'public-read', acl(options)
243
+ end
244
+ end
245
+
246
+ private
247
+ def process!(options)
248
+ ACL::OptionProcessor.process!(options)
249
+ end
250
+
251
+ def acl(options)
252
+ options['x-amz-acl']
253
+ end
254
+ end