alancse-aws-s3 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,99 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class HeaderAuthenticationTest < Test::Unit::TestCase
4
+ def test_encoded_canonical
5
+ signature = Authentication::Signature.new(request, key_id, secret, current_host)
6
+ assert_equal AmazonDocExampleData::Example1.canonical_string, signature.send(:canonical_string)
7
+ assert_equal AmazonDocExampleData::Example1.signature, signature.send(:encoded_canonical)
8
+ end
9
+
10
+ def test_authorization_header
11
+ header = Authentication::Header.new(request, key_id, secret, current_host)
12
+ assert_equal AmazonDocExampleData::Example1.canonical_string, header.send(:canonical_string)
13
+ assert_equal AmazonDocExampleData::Example1.authorization_header, header
14
+ end
15
+
16
+ private
17
+ def request ; AmazonDocExampleData::Example1.request end
18
+ def key_id ; AmazonDocExampleData::Example1.access_key_id end
19
+ def secret ; AmazonDocExampleData::Example1.secret_access_key end
20
+ def current_host; AmazonDocExampleData::Example1.current_host end
21
+ end
22
+
23
+ class QueryStringAuthenticationTest < Test::Unit::TestCase
24
+ def test_query_string
25
+ query_string = Authentication::QueryString.new(request, key_id, secret, current_host, :expires_in => 60)
26
+ assert_equal AmazonDocExampleData::Example3.canonical_string, query_string.send(:canonical_string)
27
+ assert_equal AmazonDocExampleData::Example3.query_string, query_string
28
+ end
29
+
30
+ def test_query_string_with_explicit_expiry
31
+ query_string = Authentication::QueryString.new(request, key_id, secret, current_host, :expires => expires)
32
+ assert_equal expires, query_string.send(:canonical_string).instance_variable_get(:@options)[:expires]
33
+ assert_equal AmazonDocExampleData::Example3.query_string, query_string
34
+ end
35
+
36
+ private
37
+ def request ; AmazonDocExampleData::Example3.request end
38
+ def key_id ; AmazonDocExampleData::Example3.access_key_id end
39
+ def secret ; AmazonDocExampleData::Example3.secret_access_key end
40
+ def expires ; AmazonDocExampleData::Example3.expires end
41
+ def current_host; AmazonDocExampleData::Example3.current_host end
42
+ end
43
+
44
+ class CanonicalStringTest < Test::Unit::TestCase
45
+ def setup
46
+ @request = Net::HTTP::Post.new('/test')
47
+ @current_host = 'quotes'
48
+ @canonical_string = Authentication::CanonicalString.new(@request, @current_host)
49
+ end
50
+
51
+ def test_path_does_not_include_query_string
52
+ request = Net::HTTP::Get.new('/test/query/string?foo=bar&baz=quux')
53
+ assert_equal '/quotes/test/query/string', Authentication::CanonicalString.new(request, @current_host).send(:path)
54
+
55
+ # Make sure things still work when there is *no* query string
56
+ request = Net::HTTP::Get.new('/')
57
+ assert_equal '/quotes/', Authentication::CanonicalString.new(request, @current_host).send(:path)
58
+ request = Net::HTTP::Get.new('/foo/bar')
59
+ assert_equal '/quotes/foo/bar', Authentication::CanonicalString.new(request, @current_host).send(:path)
60
+ end
61
+
62
+ def test_path_includes_significant_query_strings
63
+ significant_query_strings = [
64
+ ['/test/query/string?acl', '/quotes/test/query/string?acl'],
65
+ ['/test/query/string?acl&foo=bar', '/quotes/test/query/string?acl'],
66
+ ['/test/query/string?foo=bar&acl', '/quotes/test/query/string?acl'],
67
+ ['/test/query/string?acl=foo', '/quotes/test/query/string?acl'],
68
+ ['/test/query/string?torrent=foo', '/quotes/test/query/string?torrent'],
69
+ ['/test/query/string?logging=foo', '/quotes/test/query/string?logging'],
70
+ ['/test/query/string?bar=baz&acl=foo', '/quotes/test/query/string?acl']
71
+ ]
72
+
73
+ significant_query_strings.each do |uncleaned_path, expected_cleaned_path|
74
+ assert_equal expected_cleaned_path, Authentication::CanonicalString.new(Net::HTTP::Get.new(uncleaned_path), @current_host).send(:path)
75
+ end
76
+ end
77
+
78
+ def test_default_headers_set
79
+ Authentication::CanonicalString.default_headers.each do |header|
80
+ assert @canonical_string.headers.include?(header)
81
+ end
82
+ end
83
+
84
+ def test_interesting_headers_are_copied_over
85
+ an_interesting_header = 'content-md5'
86
+ string_without_interesting_header = Authentication::CanonicalString.new(@request, @current_host)
87
+ assert string_without_interesting_header.headers[an_interesting_header].empty?
88
+
89
+ # Add an interesting header
90
+ @request[an_interesting_header] = 'foo'
91
+ string_with_interesting_header = Authentication::CanonicalString.new(@request, @current_host)
92
+ assert_equal 'foo', string_with_interesting_header.headers[an_interesting_header]
93
+ end
94
+
95
+ def test_canonical_string
96
+ request = AmazonDocExampleData::Example1.request
97
+ assert_equal AmazonDocExampleData::Example1.canonical_string, Authentication::CanonicalString.new(request, @current_host)
98
+ end
99
+ end
@@ -0,0 +1,143 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class BaseTest < Test::Unit::TestCase
4
+ def test_connection_established
5
+ assert_raises(NoConnectionEstablished) do
6
+ Base.connection
7
+ end
8
+
9
+ Base.establish_connection!(:access_key_id => '123', :secret_access_key => 'abc')
10
+ assert_kind_of Connection, Base.connection
11
+
12
+ instance = Base.new
13
+ assert_equal instance.send(:connection), Base.connection
14
+ assert_equal instance.send(:http), Base.connection.http
15
+ end
16
+
17
+ def test_respond_with
18
+ assert_equal Base::Response, Base.send(:response_class)
19
+ Base.send(:respond_with, Bucket::Response) do
20
+ assert_equal Bucket::Response, Base.send(:response_class)
21
+ end
22
+ assert_equal Base::Response, Base.send(:response_class)
23
+ end
24
+
25
+ def test_request_tries_again_when_encountering_an_internal_error
26
+ Bucket.in_test_mode do
27
+ Bucket.request_returns [
28
+ # First request is an internal error
29
+ {:body => Fixtures::Errors.internal_error, :code => 500, :error => true},
30
+ # Second request is a success
31
+ {:body => Fixtures::Buckets.empty_bucket, :code => 200}
32
+ ]
33
+ bucket = nil # Block scope hack
34
+ assert_nothing_raised do
35
+ bucket = Bucket.find('marcel')
36
+ end
37
+ # Don't call objects 'cause we don't want to make another request
38
+ assert bucket.object_cache.empty?
39
+ end
40
+ end
41
+
42
+ def test_request_tries_up_to_three_times
43
+ Bucket.in_test_mode do
44
+ Bucket.request_returns [
45
+ # First request is an internal error
46
+ {:body => Fixtures::Errors.internal_error, :code => 500, :error => true},
47
+ # Second request is also an internal error
48
+ {:body => Fixtures::Errors.internal_error, :code => 500, :error => true},
49
+ # Ditto third
50
+ {:body => Fixtures::Errors.internal_error, :code => 500, :error => true},
51
+ # Fourth works
52
+ {:body => Fixtures::Buckets.empty_bucket, :code => 200}
53
+ ]
54
+ bucket = nil # Block scope hack
55
+ assert_nothing_raised do
56
+ bucket = Bucket.find('marcel')
57
+ end
58
+ # Don't call objects 'cause we don't want to make another request
59
+ assert bucket.object_cache.empty?
60
+ end
61
+ end
62
+
63
+ def test_request_tries_again_three_times_and_gives_up
64
+ Bucket.in_test_mode do
65
+ Bucket.request_returns [
66
+ # First request is an internal error
67
+ {:body => Fixtures::Errors.internal_error, :code => 500, :error => true},
68
+ # Second request is also an internal error
69
+ {:body => Fixtures::Errors.internal_error, :code => 500, :error => true},
70
+ # Ditto third
71
+ {:body => Fixtures::Errors.internal_error, :code => 500, :error => true},
72
+ # Ditto fourth
73
+ {:body => Fixtures::Errors.internal_error, :code => 500, :error => true},
74
+ ]
75
+ assert_raises(InternalError) do
76
+ Bucket.find('marcel')
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ class MultiConnectionsTest < Test::Unit::TestCase
83
+ class ClassToTestSettingCurrentBucket < Base
84
+ set_current_bucket_to 'foo'
85
+ end
86
+
87
+ def setup
88
+ Base.send(:connections).clear
89
+ end
90
+ alias_method :teardown, :setup
91
+
92
+ def test_default_connection_options_are_used_for_subsequent_connections
93
+ assert !Base.connected?
94
+
95
+ assert_raises(MissingAccessKey) do
96
+ Base.establish_connection!
97
+ end
98
+
99
+ assert !Base.connected?
100
+
101
+ assert_raises(NoConnectionEstablished) do
102
+ Base.connection
103
+ end
104
+
105
+ assert_nothing_raised do
106
+ Base.establish_connection!(:access_key_id => '123', :secret_access_key => 'abc')
107
+ end
108
+
109
+ assert Base.connected?
110
+
111
+ assert_nothing_raised do
112
+ Base.connection
113
+ end
114
+
115
+ # All subclasses are currently using the default connection
116
+ assert Base.connection == Bucket.connection
117
+
118
+ # No need to pass in the required options. The default connection will supply them
119
+ assert_nothing_raised do
120
+ Bucket.establish_connection!(:server => 'foo.s3.amazonaws.com')
121
+ end
122
+
123
+ assert Base.connection != Bucket.connection
124
+ assert_equal '123', Bucket.connection.access_key_id
125
+ assert_equal 'foo', Bucket.connection.subdomain
126
+ end
127
+
128
+ def test_current_bucket
129
+ Base.establish_connection!(:access_key_id => '123', :secret_access_key => 'abc')
130
+ assert_raises(CurrentBucketNotSpecified) do
131
+ Base.current_bucket
132
+ end
133
+
134
+ S3Object.establish_connection!(:server => 'foo-bucket.s3.amazonaws.com')
135
+ assert_nothing_raised do
136
+ assert_equal 'foo-bucket', S3Object.current_bucket
137
+ end
138
+ end
139
+
140
+ def test_setting_the_current_bucket
141
+ assert_equal 'foo', ClassToTestSettingCurrentBucket.current_bucket
142
+ end
143
+ end
@@ -0,0 +1,48 @@
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
+ Bucket.request_always_returns :body => Fixtures::Buckets.empty_bucket, :code => 200 do
19
+ bucket = Bucket.find('marcel_molina')
20
+ assert bucket.empty?
21
+ end
22
+ end
23
+
24
+ def test_bucket_with_one_file
25
+ Bucket.request_always_returns :body => Fixtures::Buckets.bucket_with_one_key, :code => 200 do
26
+ bucket = Bucket.find('marcel_molina')
27
+ assert !bucket.empty?
28
+ assert_equal 1, bucket.size
29
+ assert_equal %w(tongue_overload.jpg), bucket.objects.map {|object| object.key}
30
+ assert bucket['tongue_overload.jpg']
31
+ end
32
+ end
33
+
34
+ def test_bucket_with_more_than_one_file
35
+ Bucket.request_always_returns :body => Fixtures::Buckets.bucket_with_more_than_one_key, :code => 200 do
36
+ bucket = Bucket.find('marcel_molina')
37
+ assert !bucket.empty?
38
+ assert_equal 2, bucket.size
39
+ assert_equal %w(beluga_baby.jpg tongue_overload.jpg), bucket.objects.map {|object| object.key}.sort
40
+ assert bucket['tongue_overload.jpg']
41
+ end
42
+ end
43
+
44
+ def test_bucket_path
45
+ assert_equal '/?max-keys=2', Bucket.send(:path, 'bucket_name', :max_keys => 2)
46
+ assert_equal '/', Bucket.send(:path, 'bucket_name', {})
47
+ end
48
+ end
@@ -0,0 +1,190 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ConnectionTest < Test::Unit::TestCase
4
+ def setup
5
+ @keys = {:access_key_id => '123', :secret_access_key => 'abc'}
6
+ end
7
+
8
+ def test_creating_a_connection
9
+ connection = Connection.new(@keys)
10
+ assert_kind_of Net::HTTP, connection.http
11
+ end
12
+
13
+ def test_use_ssl_option_is_set_in_connection
14
+ connection = Connection.new(@keys.merge(:use_ssl => true))
15
+ assert connection.http.use_ssl?
16
+ end
17
+
18
+ def test_setting_port_to_443_implies_use_ssl
19
+ connection = Connection.new(@keys.merge(:port => 443))
20
+ assert connection.http.use_ssl?
21
+ end
22
+
23
+ def test_protocol
24
+ connection = Connection.new(@keys)
25
+ assert_equal 'http://', connection.protocol
26
+ connection = Connection.new(@keys.merge(:use_ssl => true))
27
+ assert_equal 'https://', connection.protocol
28
+ end
29
+
30
+ def test_connection_is_persistent_by_default
31
+ connection = Connection.new(@keys)
32
+ assert connection.persistent?
33
+
34
+ connection = Connection.new(@keys.merge(:persistent => false))
35
+ assert !connection.persistent?
36
+ end
37
+
38
+ def test_server_and_port_are_passed_onto_connection
39
+ connection = Connection.new(@keys)
40
+ options = connection.instance_variable_get('@options')
41
+ assert_equal connection.http.address, options[:server]
42
+ assert_equal connection.http.port, options[:port]
43
+ end
44
+
45
+ def test_not_including_required_access_keys_raises
46
+ assert_raises(MissingAccessKey) do
47
+ Connection.new
48
+ end
49
+
50
+ assert_raises(MissingAccessKey) do
51
+ Connection.new(:access_key_id => '123')
52
+ end
53
+
54
+ assert_nothing_raised do
55
+ Connection.new(@keys)
56
+ end
57
+ end
58
+
59
+ def test_access_keys_extracted
60
+ connection = Connection.new(@keys)
61
+ assert_equal '123', connection.access_key_id
62
+ assert_equal 'abc', connection.secret_access_key
63
+ end
64
+
65
+ def test_request_method_class_lookup
66
+ c = Connection.new(@keys)
67
+ expectations = {
68
+ :get => Net::HTTP::Get, :post => Net::HTTP::Post,
69
+ :put => Net::HTTP::Put, :delete => Net::HTTP::Delete,
70
+ :head => Net::HTTP::Head
71
+ }
72
+
73
+ expectations.each do |verb, klass|
74
+ assert_equal klass, c.send(:request_method, verb)
75
+ end
76
+ end
77
+
78
+ def test_url_for_uses_default_protocol_server_and_port
79
+ connection = Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :port => 80)
80
+ assert_match %r(^http://mybucket\.s3\.amazonaws\.com/foo\?), connection.url_for('/foo', 'mybucket')
81
+
82
+ connection = Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :use_ssl => true, :port => 443)
83
+ assert_match %r(^https://mybucket\.s3\.amazonaws\.com/foo\?), connection.url_for('/foo', 'mybucket')
84
+ end
85
+
86
+ def test_url_for_remembers_custom_protocol_server_and_port
87
+ connection = Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :server => 'example.org', :port => 555, :use_ssl => true)
88
+ assert_match %r(^https://mybucket\.example\.org:555/foo\?), connection.url_for('/foo', 'mybucket')
89
+ end
90
+
91
+ def test_url_for_with_and_without_authenticated_urls
92
+ connection = Connection.new(:access_key_id => '123', :secret_access_key => 'abc', :server => 'example.org')
93
+ authenticated = lambda {|url| url['?AWSAccessKeyId']}
94
+ assert authenticated[connection.url_for('/foo', 'mybucket')]
95
+ assert authenticated[connection.url_for('/foo', 'mybucket', :authenticated => true)]
96
+ assert !authenticated[connection.url_for('/foo', 'mybucket', :authenticated => false)]
97
+ end
98
+
99
+ def test_connecting_through_a_proxy
100
+ connection = nil
101
+ assert_nothing_raised do
102
+ connection = Connection.new(@keys.merge(:proxy => sample_proxy_settings))
103
+ end
104
+ assert connection.http.proxy?
105
+ end
106
+ end
107
+
108
+ class ConnectionOptionsTest < Test::Unit::TestCase
109
+
110
+ def setup
111
+ @options = generate_options(:server => 'example.org', :port => 555)
112
+ @default_options = generate_options
113
+ end
114
+
115
+ def test_server_extracted
116
+ assert_key_transfered(:server, 'example.org', @options)
117
+ end
118
+
119
+ def test_port_extracted
120
+ assert_key_transfered(:port, 555, @options)
121
+ end
122
+
123
+ def test_server_defaults_to_default_host
124
+ assert_equal DEFAULT_HOST, @default_options[:server]
125
+ end
126
+
127
+ def test_port_defaults_to_80_if_use_ssl_is_false
128
+ assert_equal 80, @default_options[:port]
129
+ end
130
+
131
+ def test_port_is_set_to_443_if_use_ssl_is_true
132
+ options = generate_options(:use_ssl => true)
133
+ assert_equal 443, options[:port]
134
+ end
135
+
136
+ def test_explicit_port_trumps_use_ssl
137
+ options = generate_options(:port => 555, :use_ssl => true)
138
+ assert_equal 555, options[:port]
139
+ end
140
+
141
+ def test_invalid_options_raise
142
+ assert_raises(InvalidConnectionOption) do
143
+ generate_options(:host => 'campfire.s3.amazonaws.com')
144
+ end
145
+ end
146
+
147
+ def test_not_specifying_all_required_proxy_settings_raises
148
+ assert_raises(ArgumentError) do
149
+ generate_options(:proxy => {})
150
+ end
151
+ end
152
+
153
+ def test_not_specifying_proxy_option_at_all_does_not_raise
154
+ assert_nothing_raised do
155
+ generate_options
156
+ end
157
+ end
158
+
159
+ def test_specifying_all_required_proxy_settings
160
+ assert_nothing_raised do
161
+ generate_options(:proxy => sample_proxy_settings)
162
+ end
163
+ end
164
+
165
+ def test_only_host_setting_is_required
166
+ assert_nothing_raised do
167
+ generate_options(:proxy => {:host => 'http://google.com'})
168
+ end
169
+ end
170
+
171
+ def test_proxy_settings_are_extracted
172
+ options = generate_options(:proxy => sample_proxy_settings)
173
+ assert_equal sample_proxy_settings.values.map {|value| value.to_s}.sort, options.proxy_settings.map {|value| value.to_s}.sort
174
+ end
175
+
176
+ def test_recognizing_that_the_settings_want_to_connect_through_a_proxy
177
+ options = generate_options(:proxy => sample_proxy_settings)
178
+ assert options.connecting_through_proxy?
179
+ end
180
+
181
+ private
182
+ def assert_key_transfered(key, value, options)
183
+ assert_equal value, options[key]
184
+ assert !options.instance_variable_get('@options').has_key?(key)
185
+ end
186
+
187
+ def generate_options(options = {})
188
+ Connection::Options.new(options)
189
+ end
190
+ end