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.
Files changed (93) hide show
  1. data/CHANGELOG +107 -0
  2. data/COPYING +19 -0
  3. data/INSTALL +55 -0
  4. data/README.erb +58 -0
  5. data/Rakefile +334 -0
  6. data/TODO +26 -0
  7. data/aws-s3.gemspec +42 -0
  8. data/bin/s3sh +6 -0
  9. data/bin/setup.rb +10 -0
  10. data/lib/aws/s3.rb +60 -0
  11. data/lib/aws/s3/acl.rb +636 -0
  12. data/lib/aws/s3/authentication.rb +222 -0
  13. data/lib/aws/s3/base.rb +270 -0
  14. data/lib/aws/s3/bittorrent.rb +58 -0
  15. data/lib/aws/s3/bucket.rb +372 -0
  16. data/lib/aws/s3/connection.rb +288 -0
  17. data/lib/aws/s3/error.rb +69 -0
  18. data/lib/aws/s3/exceptions.rb +133 -0
  19. data/lib/aws/s3/extensions.rb +342 -0
  20. data/lib/aws/s3/logging.rb +317 -0
  21. data/lib/aws/s3/object.rb +626 -0
  22. data/lib/aws/s3/owner.rb +46 -0
  23. data/lib/aws/s3/parsing.rb +99 -0
  24. data/lib/aws/s3/response.rb +180 -0
  25. data/lib/aws/s3/service.rb +51 -0
  26. data/lib/aws/s3/version.rb +12 -0
  27. data/site/index.erb +41 -0
  28. data/site/public/images/box-and-gem.gif +0 -0
  29. data/site/public/images/favicon.ico +0 -0
  30. data/site/public/ruby.css +18 -0
  31. data/site/public/screen.css +99 -0
  32. data/support/faster-xml-simple/COPYING +18 -0
  33. data/support/faster-xml-simple/README +8 -0
  34. data/support/faster-xml-simple/Rakefile +54 -0
  35. data/support/faster-xml-simple/lib/faster_xml_simple.rb +190 -0
  36. data/support/faster-xml-simple/test/fixtures/test-1.rails.yml +4 -0
  37. data/support/faster-xml-simple/test/fixtures/test-1.xml +3 -0
  38. data/support/faster-xml-simple/test/fixtures/test-1.yml +4 -0
  39. data/support/faster-xml-simple/test/fixtures/test-2.rails.yml +6 -0
  40. data/support/faster-xml-simple/test/fixtures/test-2.xml +3 -0
  41. data/support/faster-xml-simple/test/fixtures/test-2.yml +6 -0
  42. data/support/faster-xml-simple/test/fixtures/test-3.rails.yml +6 -0
  43. data/support/faster-xml-simple/test/fixtures/test-3.xml +5 -0
  44. data/support/faster-xml-simple/test/fixtures/test-3.yml +6 -0
  45. data/support/faster-xml-simple/test/fixtures/test-4.rails.yml +5 -0
  46. data/support/faster-xml-simple/test/fixtures/test-4.xml +7 -0
  47. data/support/faster-xml-simple/test/fixtures/test-4.yml +5 -0
  48. data/support/faster-xml-simple/test/fixtures/test-5.rails.yml +8 -0
  49. data/support/faster-xml-simple/test/fixtures/test-5.xml +7 -0
  50. data/support/faster-xml-simple/test/fixtures/test-5.yml +8 -0
  51. data/support/faster-xml-simple/test/fixtures/test-6.rails.yml +43 -0
  52. data/support/faster-xml-simple/test/fixtures/test-6.xml +29 -0
  53. data/support/faster-xml-simple/test/fixtures/test-6.yml +41 -0
  54. data/support/faster-xml-simple/test/fixtures/test-7.rails.yml +23 -0
  55. data/support/faster-xml-simple/test/fixtures/test-7.xml +22 -0
  56. data/support/faster-xml-simple/test/fixtures/test-7.yml +22 -0
  57. data/support/faster-xml-simple/test/fixtures/test-8.rails.yml +14 -0
  58. data/support/faster-xml-simple/test/fixtures/test-8.xml +8 -0
  59. data/support/faster-xml-simple/test/fixtures/test-8.yml +11 -0
  60. data/support/faster-xml-simple/test/regression_test.rb +47 -0
  61. data/support/faster-xml-simple/test/test_helper.rb +17 -0
  62. data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +46 -0
  63. data/support/rdoc/code_info.rb +211 -0
  64. data/test/acl_test.rb +254 -0
  65. data/test/authentication_test.rb +118 -0
  66. data/test/base_test.rb +136 -0
  67. data/test/bucket_test.rb +74 -0
  68. data/test/connection_test.rb +216 -0
  69. data/test/error_test.rb +70 -0
  70. data/test/extensions_test.rb +340 -0
  71. data/test/fixtures.rb +89 -0
  72. data/test/fixtures/buckets.yml +133 -0
  73. data/test/fixtures/errors.yml +34 -0
  74. data/test/fixtures/headers.yml +3 -0
  75. data/test/fixtures/logging.yml +15 -0
  76. data/test/fixtures/loglines.yml +5 -0
  77. data/test/fixtures/logs.yml +7 -0
  78. data/test/fixtures/policies.yml +16 -0
  79. data/test/logging_test.rb +89 -0
  80. data/test/mocks/fake_response.rb +26 -0
  81. data/test/object_test.rb +205 -0
  82. data/test/parsing_test.rb +66 -0
  83. data/test/remote/acl_test.rb +116 -0
  84. data/test/remote/bittorrent_test.rb +45 -0
  85. data/test/remote/bucket_test.rb +146 -0
  86. data/test/remote/logging_test.rb +82 -0
  87. data/test/remote/object_test.rb +379 -0
  88. data/test/remote/test_file.data +0 -0
  89. data/test/remote/test_helper.rb +33 -0
  90. data/test/response_test.rb +68 -0
  91. data/test/service_test.rb +23 -0
  92. data/test/test_helper.rb +118 -0
  93. metadata +241 -0
@@ -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
@@ -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