fmalamitsas-aws-s3 0.6.2.1254423625
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.
- data/CHANGELOG +107 -0
- data/COPYING +19 -0
- data/INSTALL +55 -0
- data/README.erb +58 -0
- data/Rakefile +334 -0
- data/TODO +26 -0
- data/aws-s3.gemspec +42 -0
- data/bin/s3sh +6 -0
- data/bin/setup.rb +10 -0
- data/lib/aws/s3.rb +60 -0
- data/lib/aws/s3/acl.rb +636 -0
- data/lib/aws/s3/authentication.rb +222 -0
- data/lib/aws/s3/base.rb +270 -0
- data/lib/aws/s3/bittorrent.rb +58 -0
- data/lib/aws/s3/bucket.rb +372 -0
- data/lib/aws/s3/connection.rb +288 -0
- data/lib/aws/s3/error.rb +69 -0
- data/lib/aws/s3/exceptions.rb +133 -0
- data/lib/aws/s3/extensions.rb +342 -0
- data/lib/aws/s3/logging.rb +317 -0
- data/lib/aws/s3/object.rb +626 -0
- data/lib/aws/s3/owner.rb +46 -0
- data/lib/aws/s3/parsing.rb +99 -0
- data/lib/aws/s3/response.rb +180 -0
- data/lib/aws/s3/service.rb +51 -0
- data/lib/aws/s3/version.rb +12 -0
- data/site/index.erb +41 -0
- data/site/public/images/box-and-gem.gif +0 -0
- data/site/public/images/favicon.ico +0 -0
- data/site/public/ruby.css +18 -0
- data/site/public/screen.css +99 -0
- data/support/faster-xml-simple/COPYING +18 -0
- data/support/faster-xml-simple/README +8 -0
- data/support/faster-xml-simple/Rakefile +54 -0
- data/support/faster-xml-simple/lib/faster_xml_simple.rb +190 -0
- data/support/faster-xml-simple/test/fixtures/test-1.rails.yml +4 -0
- data/support/faster-xml-simple/test/fixtures/test-1.xml +3 -0
- data/support/faster-xml-simple/test/fixtures/test-1.yml +4 -0
- data/support/faster-xml-simple/test/fixtures/test-2.rails.yml +6 -0
- data/support/faster-xml-simple/test/fixtures/test-2.xml +3 -0
- data/support/faster-xml-simple/test/fixtures/test-2.yml +6 -0
- data/support/faster-xml-simple/test/fixtures/test-3.rails.yml +6 -0
- data/support/faster-xml-simple/test/fixtures/test-3.xml +5 -0
- data/support/faster-xml-simple/test/fixtures/test-3.yml +6 -0
- data/support/faster-xml-simple/test/fixtures/test-4.rails.yml +5 -0
- data/support/faster-xml-simple/test/fixtures/test-4.xml +7 -0
- data/support/faster-xml-simple/test/fixtures/test-4.yml +5 -0
- data/support/faster-xml-simple/test/fixtures/test-5.rails.yml +8 -0
- data/support/faster-xml-simple/test/fixtures/test-5.xml +7 -0
- data/support/faster-xml-simple/test/fixtures/test-5.yml +8 -0
- data/support/faster-xml-simple/test/fixtures/test-6.rails.yml +43 -0
- data/support/faster-xml-simple/test/fixtures/test-6.xml +29 -0
- data/support/faster-xml-simple/test/fixtures/test-6.yml +41 -0
- data/support/faster-xml-simple/test/fixtures/test-7.rails.yml +23 -0
- data/support/faster-xml-simple/test/fixtures/test-7.xml +22 -0
- data/support/faster-xml-simple/test/fixtures/test-7.yml +22 -0
- data/support/faster-xml-simple/test/fixtures/test-8.rails.yml +14 -0
- data/support/faster-xml-simple/test/fixtures/test-8.xml +8 -0
- data/support/faster-xml-simple/test/fixtures/test-8.yml +11 -0
- data/support/faster-xml-simple/test/regression_test.rb +47 -0
- data/support/faster-xml-simple/test/test_helper.rb +17 -0
- data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +46 -0
- data/support/rdoc/code_info.rb +211 -0
- data/test/acl_test.rb +254 -0
- data/test/authentication_test.rb +118 -0
- data/test/base_test.rb +136 -0
- data/test/bucket_test.rb +74 -0
- data/test/connection_test.rb +216 -0
- data/test/error_test.rb +70 -0
- data/test/extensions_test.rb +340 -0
- data/test/fixtures.rb +89 -0
- data/test/fixtures/buckets.yml +133 -0
- data/test/fixtures/errors.yml +34 -0
- data/test/fixtures/headers.yml +3 -0
- data/test/fixtures/logging.yml +15 -0
- data/test/fixtures/loglines.yml +5 -0
- data/test/fixtures/logs.yml +7 -0
- data/test/fixtures/policies.yml +16 -0
- data/test/logging_test.rb +89 -0
- data/test/mocks/fake_response.rb +26 -0
- data/test/object_test.rb +205 -0
- data/test/parsing_test.rb +66 -0
- data/test/remote/acl_test.rb +116 -0
- data/test/remote/bittorrent_test.rb +45 -0
- data/test/remote/bucket_test.rb +146 -0
- data/test/remote/logging_test.rb +82 -0
- data/test/remote/object_test.rb +379 -0
- data/test/remote/test_file.data +0 -0
- data/test/remote/test_helper.rb +33 -0
- data/test/response_test.rb +68 -0
- data/test/service_test.rb +23 -0
- data/test/test_helper.rb +118 -0
- metadata +241 -0
data/test/bucket_test.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class BucketTest < Test::Unit::TestCase
|
4
|
+
def test_bucket_name_validation
|
5
|
+
valid_names = %w(123 joe step-one step_two step3 step_4 step-5 step.six)
|
6
|
+
invalid_names = ['12', 'jo', 'kevin spacey', 'larry@wall', '', 'a' * 256]
|
7
|
+
validate_name = Proc.new {|name| Bucket.send(:validate_name!, name)}
|
8
|
+
valid_names.each do |valid_name|
|
9
|
+
assert_nothing_raised { validate_name[valid_name] }
|
10
|
+
end
|
11
|
+
|
12
|
+
invalid_names.each do |invalid_name|
|
13
|
+
assert_raises(InvalidBucketName) { validate_name[invalid_name] }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_empty_bucket
|
18
|
+
mock_connection_for(Bucket, :returns => {:body => Fixtures::Buckets.empty_bucket, :code => 200})
|
19
|
+
bucket = Bucket.find('marcel_molina')
|
20
|
+
assert bucket.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_bucket_with_one_file
|
24
|
+
mock_connection_for(Bucket, :returns => {:body => Fixtures::Buckets.bucket_with_one_key, :code => 200})
|
25
|
+
bucket = Bucket.find('marcel_molina')
|
26
|
+
assert !bucket.empty?
|
27
|
+
assert_equal 1, bucket.size
|
28
|
+
assert_equal %w(tongue_overload.jpg), bucket.objects.map {|object| object.key}
|
29
|
+
assert bucket['tongue_overload.jpg']
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_bucket_with_more_than_one_file
|
33
|
+
mock_connection_for(Bucket, :returns => {:body => Fixtures::Buckets.bucket_with_more_than_one_key, :code => 200})
|
34
|
+
bucket = Bucket.find('marcel_molina')
|
35
|
+
assert !bucket.empty?
|
36
|
+
assert_equal 2, bucket.size
|
37
|
+
assert_equal %w(beluga_baby.jpg tongue_overload.jpg), bucket.objects.map {|object| object.key}.sort
|
38
|
+
assert bucket['tongue_overload.jpg']
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_bucket_path
|
42
|
+
assert_equal '/?max-keys=2', Bucket.send(:path, 'bucket_name', :max_keys => 2)
|
43
|
+
assert_equal '/', Bucket.send(:path, 'bucket_name', {})
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_should_not_be_truncated
|
47
|
+
mock_connection_for(Bucket, :returns => {:body => Fixtures::Buckets.bucket_with_more_than_one_key, :code => 200})
|
48
|
+
bucket = Bucket.find('marcel_molina')
|
49
|
+
assert !bucket.is_truncated
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_should_be_truncated
|
53
|
+
mock_connection_for(Bucket, :returns => {:body => Fixtures::Buckets.truncated_bucket_with_more_than_one_key, :code => 200})
|
54
|
+
bucket = Bucket.find('marcel_molina')
|
55
|
+
assert bucket.is_truncated
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_bucket_name_should_have_leading_slash_prepended_only_once_when_forcing_a_delete
|
59
|
+
# References bug: http://rubyforge.org/tracker/index.php?func=detail&aid=19158&group_id=2409&atid=9356
|
60
|
+
bucket_name = 'foo'
|
61
|
+
expected_bucket_path = %r{/[^/]*[a-zA-Z.0-9]*}
|
62
|
+
|
63
|
+
mock_bucket = flexmock('Mock bucket') do |mock|
|
64
|
+
mock.should_receive(:delete_all).once
|
65
|
+
end
|
66
|
+
mock_response = flexmock('Mock delete response') do |mock|
|
67
|
+
mock.should_receive(:success?).once
|
68
|
+
end
|
69
|
+
|
70
|
+
flexmock(Bucket).should_receive(:find).with(bucket_name).once.and_return(mock_bucket)
|
71
|
+
flexmock(Base).should_receive(:delete).with(expected_bucket_path).once.and_return(mock_response)
|
72
|
+
Bucket.delete(bucket_name, :force => true)
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class ConnectionTest < Test::Unit::TestCase
|
4
|
+
attr_reader :keys
|
5
|
+
def setup
|
6
|
+
@keys = {:access_key_id => '123', :secret_access_key => 'abc'}.freeze
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_creating_a_connection
|
10
|
+
connection = Connection.new(keys)
|
11
|
+
assert_kind_of Net::HTTP, connection.http
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_use_ssl_option_is_set_in_connection
|
15
|
+
connection = Connection.new(keys.merge(:use_ssl => true))
|
16
|
+
assert connection.http.use_ssl?
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_setting_port_to_443_implies_use_ssl
|
20
|
+
connection = Connection.new(keys.merge(:port => 443))
|
21
|
+
assert connection.http.use_ssl?
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_protocol
|
25
|
+
connection = Connection.new(keys)
|
26
|
+
assert_equal 'http://', connection.protocol
|
27
|
+
connection = Connection.new(keys.merge(:use_ssl => true))
|
28
|
+
assert_equal 'https://', connection.protocol
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_url_for_honors_use_ssl_option_if_it_is_false_even_if_connection_has_use_ssl_option_set
|
32
|
+
# References bug: http://rubyforge.org/tracker/index.php?func=detail&aid=17628&group_id=2409&atid=9356
|
33
|
+
connection = Connection.new(keys.merge(:use_ssl => true))
|
34
|
+
# assert_match %r(^http://), connection.url_for('/pathdoesnotmatter', :authenticated => false, :use_ssl => false)
|
35
|
+
assert_match %r{^http://}, connection.url_for('/pathdoesnotmatter', 'hostdoesnt.matter', :authenticated => false, :use_ssl => false)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_connection_is_not_persistent_by_default
|
39
|
+
connection = Connection.new(keys)
|
40
|
+
assert !connection.persistent?
|
41
|
+
|
42
|
+
connection = Connection.new(keys.merge(:persistent => true))
|
43
|
+
assert connection.persistent?
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_server_and_port_are_passed_onto_connection
|
47
|
+
connection = Connection.new(keys)
|
48
|
+
options = connection.instance_variable_get('@options')
|
49
|
+
assert_equal connection.http.address, options[:server]
|
50
|
+
assert_equal connection.http.port, options[:port]
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_not_including_required_access_keys_raises
|
54
|
+
assert_raises(MissingAccessKey) do
|
55
|
+
Connection.new
|
56
|
+
end
|
57
|
+
|
58
|
+
assert_raises(MissingAccessKey) do
|
59
|
+
Connection.new(:access_key_id => '123')
|
60
|
+
end
|
61
|
+
|
62
|
+
assert_nothing_raised do
|
63
|
+
Connection.new(keys)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_access_keys_extracted
|
68
|
+
connection = Connection.new(keys)
|
69
|
+
assert_equal '123', connection.access_key_id
|
70
|
+
assert_equal 'abc', connection.secret_access_key
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_request_method_class_lookup
|
74
|
+
connection = Connection.new(keys)
|
75
|
+
expectations = {
|
76
|
+
:get => Net::HTTP::Get, :post => Net::HTTP::Post,
|
77
|
+
:put => Net::HTTP::Put, :delete => Net::HTTP::Delete,
|
78
|
+
:head => Net::HTTP::Head
|
79
|
+
}
|
80
|
+
|
81
|
+
expectations.each do |verb, klass|
|
82
|
+
assert_equal klass, connection.send(:request_method, verb)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_url_for_uses_default_protocol_server_and_port
|
87
|
+
connection = Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :port => 80)
|
88
|
+
assert_match %r(^http://mybucket\.s3\.amazonaws\.com/foo\?), connection.url_for('/foo', 'mybucket')
|
89
|
+
|
90
|
+
connection = Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :use_ssl => true, :port => 443)
|
91
|
+
assert_match %r(^https://mybucket\.s3\.amazonaws\.com/foo\?), connection.url_for('/foo', 'mybucket')
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_url_for_remembers_custom_protocol_server_and_port
|
95
|
+
connection = Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :server => 'example.org', :port => 555, :use_ssl => true)
|
96
|
+
assert_match %r(^https://mybucket\.example\.org:555/foo\?), connection.url_for('/foo', 'mybucket')
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_url_for_with_and_without_authenticated_urls
|
100
|
+
connection = Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :server => 'example.org')
|
101
|
+
authenticated = lambda {|url| url['?AWSAccessKeyId']}
|
102
|
+
assert authenticated[connection.url_for('/foo', 'mybucket')]
|
103
|
+
assert authenticated[connection.url_for('/foo', 'mybucket', :authenticated => true)]
|
104
|
+
assert !authenticated[connection.url_for('/foo', 'mybucket', :authenticated => false)]
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_connecting_through_a_proxy
|
108
|
+
connection = nil
|
109
|
+
assert_nothing_raised do
|
110
|
+
connection = Connection.new(keys.merge(:proxy => sample_proxy_settings))
|
111
|
+
end
|
112
|
+
assert connection.http.proxy?
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_request_only_escapes_the_path_the_first_time_it_runs_and_not_subsequent_times
|
116
|
+
connection = Connection.new(@keys)
|
117
|
+
unescaped_path = 'path with spaces'
|
118
|
+
escaped_path = 'path%20with%20spaces'
|
119
|
+
|
120
|
+
flexmock(Connection).should_receive(:prepare_path).with(unescaped_path).once.and_return(escaped_path).ordered
|
121
|
+
flexmock(connection.http).should_receive(:request).and_raise(Errno::EPIPE).ordered
|
122
|
+
flexmock(connection.http).should_receive(:request).ordered
|
123
|
+
connection.request :put, unescaped_path
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_if_request_has_no_body_then_the_content_length_is_set_to_zero
|
127
|
+
# References bug: http://rubyforge.org/tracker/index.php?func=detail&aid=13052&group_id=2409&atid=9356
|
128
|
+
connection = Connection.new(@keys)
|
129
|
+
flexmock(Net::HTTP::Put).new_instances.should_receive(:content_length=).once.with(0).ordered
|
130
|
+
flexmock(connection.http).should_receive(:request).once.ordered
|
131
|
+
connection.request :put, 'path does not matter'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class ConnectionOptionsTest < Test::Unit::TestCase
|
136
|
+
|
137
|
+
def setup
|
138
|
+
@options = generate_options(:server => 'example.org', :port => 555)
|
139
|
+
@default_options = generate_options
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_server_extracted
|
143
|
+
assert_key_transfered(:server, 'example.org', @options)
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_port_extracted
|
147
|
+
assert_key_transfered(:port, 555, @options)
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_server_defaults_to_default_host
|
151
|
+
assert_equal DEFAULT_HOST, @default_options[:server]
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_port_defaults_to_80_if_use_ssl_is_false
|
155
|
+
assert_equal 80, @default_options[:port]
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_port_is_set_to_443_if_use_ssl_is_true
|
159
|
+
options = generate_options(:use_ssl => true)
|
160
|
+
assert_equal 443, options[:port]
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_explicit_port_trumps_use_ssl
|
164
|
+
options = generate_options(:port => 555, :use_ssl => true)
|
165
|
+
assert_equal 555, options[:port]
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_invalid_options_raise
|
169
|
+
assert_raises(InvalidConnectionOption) do
|
170
|
+
generate_options(:host => 'campfire.s3.amazonaws.com')
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_not_specifying_all_required_proxy_settings_raises
|
175
|
+
assert_raises(ArgumentError) do
|
176
|
+
generate_options(:proxy => {})
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_not_specifying_proxy_option_at_all_does_not_raise
|
181
|
+
assert_nothing_raised do
|
182
|
+
generate_options
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_specifying_all_required_proxy_settings
|
187
|
+
assert_nothing_raised do
|
188
|
+
generate_options(:proxy => sample_proxy_settings)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_only_host_setting_is_required
|
193
|
+
assert_nothing_raised do
|
194
|
+
generate_options(:proxy => {:host => 'http://google.com'})
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_proxy_settings_are_extracted
|
199
|
+
options = generate_options(:proxy => sample_proxy_settings)
|
200
|
+
assert_equal sample_proxy_settings.values.map {|value| value.to_s}.sort, options.proxy_settings.map {|value| value.to_s}.sort
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_recognizing_that_the_settings_want_to_connect_through_a_proxy
|
204
|
+
options = generate_options(:proxy => sample_proxy_settings)
|
205
|
+
assert options.connecting_through_proxy?
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
def assert_key_transfered(key, value, options)
|
210
|
+
assert_equal value, options[key]
|
211
|
+
end
|
212
|
+
|
213
|
+
def generate_options(options = {})
|
214
|
+
Connection::Options.new(options)
|
215
|
+
end
|
216
|
+
end
|
data/test/error_test.rb
ADDED
@@ -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,340 @@
|
|
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_normalized_options
|
31
|
+
expectations = [
|
32
|
+
[{:foo_bar => 1}, {'foo-bar' => '1'}],
|
33
|
+
[{'foo_bar' => 1}, {'foo-bar' => '1'}],
|
34
|
+
[{'foo-bar' => 1}, {'foo-bar' => '1'}],
|
35
|
+
[{}, {}]
|
36
|
+
]
|
37
|
+
|
38
|
+
expectations.each do |(before, after)|
|
39
|
+
assert_equal after, before.to_normalized_options
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class StringExtensionsTest < Test::Unit::TestCase
|
45
|
+
def test_previous
|
46
|
+
expectations = {'abc' => 'abb', '123' => '122', '1' => '0'}
|
47
|
+
expectations.each do |before, after|
|
48
|
+
assert_equal after, before.previous
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_to_header
|
53
|
+
transformations = {
|
54
|
+
'foo' => 'foo',
|
55
|
+
:foo => 'foo',
|
56
|
+
'foo-bar' => 'foo-bar',
|
57
|
+
'foo_bar' => 'foo-bar',
|
58
|
+
:foo_bar => 'foo-bar',
|
59
|
+
'Foo-Bar' => 'foo-bar',
|
60
|
+
'Foo_Bar' => 'foo-bar'
|
61
|
+
}
|
62
|
+
|
63
|
+
transformations.each do |before, after|
|
64
|
+
assert_equal after, before.to_header
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_valid_utf8?
|
69
|
+
assert !"318597/620065/GTL_75\24300_A600_A610.zip".valid_utf8?
|
70
|
+
assert "318597/620065/GTL_75£00_A600_A610.zip".valid_utf8?
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_remove_extended
|
74
|
+
assert "318597/620065/GTL_75\24300_A600_A610.zip".remove_extended.valid_utf8?
|
75
|
+
assert "318597/620065/GTL_75£00_A600_A610.zip".remove_extended.valid_utf8?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class CoercibleStringTest < Test::Unit::TestCase
|
80
|
+
|
81
|
+
def test_coerce
|
82
|
+
coercions = [
|
83
|
+
['1', 1],
|
84
|
+
['false', false],
|
85
|
+
['true', true],
|
86
|
+
['2006-10-29T23:14:47.000Z', Time.parse('2006-10-29T23:14:47.000Z')],
|
87
|
+
['Hello!', 'Hello!'],
|
88
|
+
['false23', 'false23'],
|
89
|
+
['03 1-2-3-Apple-Tree.mp3', '03 1-2-3-Apple-Tree.mp3'],
|
90
|
+
['0815', '0815'] # This number isn't coerced because the leading zero would be lost
|
91
|
+
]
|
92
|
+
|
93
|
+
coercions.each do |before, after|
|
94
|
+
assert_nothing_raised do
|
95
|
+
assert_equal after, CoercibleString.coerce(before)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class KerneltExtensionsTest < Test::Unit::TestCase
|
102
|
+
class Foo
|
103
|
+
def foo
|
104
|
+
__method__
|
105
|
+
end
|
106
|
+
|
107
|
+
def bar
|
108
|
+
foo
|
109
|
+
end
|
110
|
+
|
111
|
+
def baz
|
112
|
+
bar
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Bar
|
117
|
+
def foo
|
118
|
+
calling_method
|
119
|
+
end
|
120
|
+
|
121
|
+
def bar
|
122
|
+
calling_method
|
123
|
+
end
|
124
|
+
|
125
|
+
def calling_method
|
126
|
+
__method__(1)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def test___method___works_regardless_of_nesting
|
131
|
+
f = Foo.new
|
132
|
+
[:foo, :bar, :baz].each do |method|
|
133
|
+
assert_equal 'foo', f.send(method)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def test___method___depth
|
138
|
+
b = Bar.new
|
139
|
+
assert_equal 'foo', b.foo
|
140
|
+
assert_equal 'bar', b.bar
|
141
|
+
end
|
142
|
+
end if RUBY_VERSION <= '1.8.7'
|
143
|
+
|
144
|
+
class ModuleExtensionsTest < Test::Unit::TestCase
|
145
|
+
class Foo
|
146
|
+
def foo(reload = false)
|
147
|
+
expirable_memoize(reload) do
|
148
|
+
Time.now
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def bar(reload = false)
|
153
|
+
expirable_memoize(reload, :baz) do
|
154
|
+
Time.now
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def quux
|
159
|
+
Time.now
|
160
|
+
end
|
161
|
+
memoized :quux
|
162
|
+
end
|
163
|
+
|
164
|
+
def setup
|
165
|
+
@instance = Foo.new
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_memoize
|
169
|
+
assert !instance_variables_of(@instance).include?('@foo')
|
170
|
+
cached_result = @instance.foo
|
171
|
+
assert_equal cached_result, @instance.foo
|
172
|
+
assert instance_variables_of(@instance).include?('@foo')
|
173
|
+
assert_equal cached_result, @instance.send(:instance_variable_get, :@foo)
|
174
|
+
assert_not_equal cached_result, new_cache = @instance.foo(:reload)
|
175
|
+
assert_equal new_cache, @instance.foo
|
176
|
+
assert_equal new_cache, @instance.send(:instance_variable_get, :@foo)
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_customizing_memoize_storage
|
180
|
+
assert !instance_variables_of(@instance).include?('@bar')
|
181
|
+
assert !instance_variables_of(@instance).include?('@baz')
|
182
|
+
cached_result = @instance.bar
|
183
|
+
assert !instance_variables_of(@instance).include?('@bar')
|
184
|
+
assert instance_variables_of(@instance).include?('@baz')
|
185
|
+
assert_equal cached_result, @instance.bar
|
186
|
+
assert_equal cached_result, @instance.send(:instance_variable_get, :@baz)
|
187
|
+
assert_nil @instance.send(:instance_variable_get, :@bar)
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_memoized
|
191
|
+
assert !instance_variables_of(@instance).include?('@quux')
|
192
|
+
cached_result = @instance.quux
|
193
|
+
assert_equal cached_result, @instance.quux
|
194
|
+
assert instance_variables_of(@instance).include?('@quux')
|
195
|
+
assert_equal cached_result, @instance.send(:instance_variable_get, :@quux)
|
196
|
+
assert_not_equal cached_result, new_cache = @instance.quux(:reload)
|
197
|
+
assert_equal new_cache, @instance.quux
|
198
|
+
assert_equal new_cache, @instance.send(:instance_variable_get, :@quux)
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_constant_setting
|
202
|
+
some_module = Module.new
|
203
|
+
assert !some_module.const_defined?(:FOO)
|
204
|
+
assert_nothing_raised do
|
205
|
+
some_module.constant :FOO, 'bar'
|
206
|
+
end
|
207
|
+
|
208
|
+
assert some_module.const_defined?(:FOO)
|
209
|
+
assert_nothing_raised do
|
210
|
+
some_module::FOO
|
211
|
+
some_module.foo
|
212
|
+
end
|
213
|
+
assert_equal 'bar', some_module::FOO
|
214
|
+
assert_equal 'bar', some_module.foo
|
215
|
+
|
216
|
+
assert_nothing_raised do
|
217
|
+
some_module.constant :FOO, 'baz'
|
218
|
+
end
|
219
|
+
|
220
|
+
assert_equal 'bar', some_module::FOO
|
221
|
+
assert_equal 'bar', some_module.foo
|
222
|
+
end
|
223
|
+
|
224
|
+
private
|
225
|
+
# For 1.9 compatibility
|
226
|
+
def instance_variables_of(object)
|
227
|
+
object.instance_variables.map do |instance_variable|
|
228
|
+
instance_variable.to_s
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
class AttributeProxyTest < Test::Unit::TestCase
|
235
|
+
class BlindProxyUsingDefaultAttributesHash
|
236
|
+
include SelectiveAttributeProxy
|
237
|
+
proxy_to :exlusively => false
|
238
|
+
end
|
239
|
+
|
240
|
+
class BlindProxyUsingCustomAttributeHash
|
241
|
+
include SelectiveAttributeProxy
|
242
|
+
proxy_to :settings
|
243
|
+
end
|
244
|
+
|
245
|
+
class ProxyUsingPassedInAttributeHash
|
246
|
+
include SelectiveAttributeProxy
|
247
|
+
|
248
|
+
def initialize(attributes = {})
|
249
|
+
@attributes = attributes
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
class RestrictedProxy
|
254
|
+
include SelectiveAttributeProxy
|
255
|
+
|
256
|
+
private
|
257
|
+
def proxiable_attribute?(name)
|
258
|
+
%w(foo bar baz).include?(name)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
class NonExclusiveProxy
|
263
|
+
include SelectiveAttributeProxy
|
264
|
+
proxy_to :settings, :exclusively => false
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_using_all_defaults
|
268
|
+
b = BlindProxyUsingDefaultAttributesHash.new
|
269
|
+
assert_nothing_raised do
|
270
|
+
b.foo = 'bar'
|
271
|
+
end
|
272
|
+
|
273
|
+
assert_nothing_raised do
|
274
|
+
b.foo
|
275
|
+
end
|
276
|
+
|
277
|
+
assert_equal 'bar', b.foo
|
278
|
+
end
|
279
|
+
|
280
|
+
def test_storage_is_autovivified
|
281
|
+
b = BlindProxyUsingDefaultAttributesHash.new
|
282
|
+
assert_nothing_raised do
|
283
|
+
b.send(:attributes)['foo'] = 'bar'
|
284
|
+
end
|
285
|
+
|
286
|
+
assert_nothing_raised do
|
287
|
+
b.foo
|
288
|
+
end
|
289
|
+
|
290
|
+
assert_equal 'bar', b.foo
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_limiting_which_attributes_are_proxiable
|
294
|
+
r = RestrictedProxy.new
|
295
|
+
assert_nothing_raised do
|
296
|
+
r.foo = 'bar'
|
297
|
+
end
|
298
|
+
|
299
|
+
assert_nothing_raised do
|
300
|
+
r.foo
|
301
|
+
end
|
302
|
+
|
303
|
+
assert_equal 'bar', r.foo
|
304
|
+
|
305
|
+
assert_raises(NoMethodError) do
|
306
|
+
r.quux = 'foo'
|
307
|
+
end
|
308
|
+
|
309
|
+
assert_raises(NoMethodError) do
|
310
|
+
r.quux
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_proxying_is_exclusive_by_default
|
315
|
+
p = ProxyUsingPassedInAttributeHash.new('foo' => 'bar')
|
316
|
+
assert_nothing_raised do
|
317
|
+
p.foo
|
318
|
+
p.foo = 'baz'
|
319
|
+
end
|
320
|
+
|
321
|
+
assert_equal 'baz', p.foo
|
322
|
+
|
323
|
+
assert_raises(NoMethodError) do
|
324
|
+
p.quux
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def test_setting_the_proxy_as_non_exclusive
|
329
|
+
n = NonExclusiveProxy.new
|
330
|
+
assert_nothing_raised do
|
331
|
+
n.foo = 'baz'
|
332
|
+
end
|
333
|
+
|
334
|
+
assert_nothing_raised do
|
335
|
+
n.foo
|
336
|
+
end
|
337
|
+
|
338
|
+
assert_equal 'baz', n.foo
|
339
|
+
end
|
340
|
+
end
|