happening 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  Changelog
2
2
  =============
3
3
 
4
- 0.2.4
4
+ 0.2.5
5
5
 
6
6
  - fix building
7
7
 
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+ gem "em-http-request"
3
+
4
+ group :development do
5
+ gem "shoulda", ">= 0"
6
+ gem "bundler", "~> 1.0.0"
7
+ gem "jeweler", "~> 1.6.4"
8
+ gem "mocha"
9
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ require File.expand_path("./lib/happening")
16
+ Jeweler::Tasks.new do |gem|
17
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
18
+ gem.name = "happening"
19
+ gem.homepage = "http://github.com/peritor/happening"
20
+ gem.license = "BSD"
21
+ gem.summary = %Q{An EventMachine based S3 client }
22
+ gem.description = %Q{An EventMachine based S3 client }
23
+ gem.email = "jw@innerewut.de"
24
+ gem.authors = ["Jonathan Weiss"]
25
+ gem.version = Happening::VERSION
26
+ # dependencies defined in Gemfile
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rake/testtask'
31
+ Rake::TestTask.new(:test) do |t|
32
+ t.libs << 'test'
33
+ t.pattern = "test/**/*_test.rb"
34
+ t.verbose = true
35
+ end
36
+
37
+ task :default => :test
38
+
39
+ require 'rake/rdoctask'
40
+ Rake::RDocTask.new do |rdoc|
41
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
42
+
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = "hello-gem #{version}"
45
+ rdoc.rdoc_files.include('README*')
46
+ rdoc.rdoc_files.include('lib/**/*.rb')
47
+ end
@@ -0,0 +1,106 @@
1
+ require File.dirname(__FILE__) + '/../happening'
2
+
3
+ require 'benchmark'
4
+ require 'right_aws'
5
+
6
+ AWS_ACCESS_KEY_ID = ENV['AWS_ACCESS_KEY_ID'] or raise "please set AWS_ACCESS_KEY_ID='your-key'"
7
+ AWS_SECRET_ACCESS_KEY = ENV['AWS_SECRET_ACCESS_KEY'] or raise "please set AWS_SECRET_ACCESS_KEY='your-scret'"
8
+
9
+ BUCKET = 'happening-benchmark'
10
+ FILE = 'the_file_name'
11
+ PROTOCOL = 'https'
12
+
13
+ COUNT = 100
14
+ CONTENT = File.read('/tmp/VzLinuxUG.pdf')
15
+
16
+ command = ARGV.first || 'get'
17
+
18
+ puts "running command: #{command}"
19
+
20
+ if command == 'get'
21
+ Benchmark.bm(7) do |x|
22
+ x.report("RightAWS - Get an item") do
23
+ count = COUNT
24
+ s3 = RightAws::S3Interface.new(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, :protocol => PROTOCOL)
25
+ count.times do |i|
26
+ s3.get_object(BUCKET, FILE)
27
+ print '.'; $stdout.flush
28
+ end
29
+ end
30
+
31
+ puts ""
32
+ x.report("Happening - Get an item") do
33
+ puts ""
34
+ count = COUNT
35
+ on_success = Proc.new do |http|
36
+ print '.'; $stdout.flush
37
+ count = count - 1
38
+ EM.stop if count <= 0
39
+ end
40
+
41
+ on_error = Proc.new do |http|
42
+ puts "Status: #{http.response_header.status}"
43
+ puts "Header: #{http.response_header.inspect}"
44
+ puts "Content:"
45
+ puts http.response.inspect + "\n"
46
+ count = count - 1
47
+ EM.stop if count <= 0
48
+ end
49
+
50
+ EM.run do
51
+ count.times do |i|
52
+ item = Happening::S3::Item.new(BUCKET, FILE, :protocol => PROTOCOL, :on_success => on_success, :on_error => on_error)
53
+ item.get
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ elsif command == 'put'
60
+ Benchmark.bm(7) do |x|
61
+ x.report("RightAWS - Put an item") do
62
+ count = COUNT
63
+ s3 = RightAws::S3Interface.new(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, :protocol => PROTOCOL)
64
+ count.times do |i|
65
+ s3.put(BUCKET, "upload_test_right_aws_#{i}", CONTENT)
66
+ print '.'; $stdout.flush
67
+ end
68
+ end
69
+
70
+ puts ""
71
+ x.report("Happening - Put an item") do
72
+ puts ""
73
+ count = COUNT
74
+ on_success = Proc.new do |http|
75
+ #puts "Success"
76
+ puts "Status: #{http.response_header.status}" unless http.response_header.status == 200
77
+ #puts "Header: #{http.response_header.inspect}"
78
+ #puts "Content:"
79
+ #puts http.response.inspect + "\n"
80
+ print '.'; $stdout.flush
81
+ count = count - 1
82
+ EM.stop if count <= 0
83
+ end
84
+
85
+ on_error = Proc.new do |http|
86
+ puts "Error"
87
+ puts "Status: #{http.response_header.status}"
88
+ puts "Header: #{http.response_header.inspect}"
89
+ puts "Content:"
90
+ puts http.response.inspect + "\n"
91
+ count = count - 1
92
+ EM.stop if count <= 0
93
+ end
94
+
95
+ EM.run do
96
+ count.times do |i|
97
+ item = Happening::S3::Item.new(BUCKET, "upload_test_happening_#{i}", :protocol => PROTOCOL, :on_success => on_success, :on_error => on_error, :aws_access_key_id => AWS_ACCESS_KEY_ID, :aws_secret_access_key => AWS_SECRET_ACCESS_KEY)
98
+ item.put(CONTENT)
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ else
105
+ puts "unknown command: #{command}"
106
+ end
@@ -0,0 +1,70 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{happening}
8
+ s.version = "0.2.5"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Jonathan Weiss}]
12
+ s.date = %q{2011-08-23}
13
+ s.description = %q{An EventMachine based S3 client }
14
+ s.email = %q{jw@innerewut.de}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ "CHANGELOG.md",
21
+ "Gemfile",
22
+ "LICENSE.txt",
23
+ "README.md",
24
+ "Rakefile",
25
+ "benchmark/right_aws.rb",
26
+ "happening.gemspec",
27
+ "lib/happening.rb",
28
+ "lib/happening/aws.rb",
29
+ "lib/happening/log.rb",
30
+ "lib/happening/s3.rb",
31
+ "lib/happening/s3/item.rb",
32
+ "lib/happening/s3/request.rb",
33
+ "lib/happening/utils.rb",
34
+ "test/aws_test.rb",
35
+ "test/s3/item_test.rb",
36
+ "test/s3/request_test.rb",
37
+ "test/s3_test.rb",
38
+ "test/test_helper.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/peritor/happening}
41
+ s.licenses = [%q{BSD}]
42
+ s.require_paths = [%q{lib}]
43
+ s.rubygems_version = %q{1.8.7}
44
+ s.summary = %q{An EventMachine based S3 client}
45
+
46
+ if s.respond_to? :specification_version then
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
+ s.add_runtime_dependency(%q<em-http-request>, [">= 0"])
51
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
52
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
53
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
54
+ s.add_development_dependency(%q<mocha>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<em-http-request>, [">= 0"])
57
+ s.add_dependency(%q<shoulda>, [">= 0"])
58
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
60
+ s.add_dependency(%q<mocha>, [">= 0"])
61
+ end
62
+ else
63
+ s.add_dependency(%q<em-http-request>, [">= 0"])
64
+ s.add_dependency(%q<shoulda>, [">= 0"])
65
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
66
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
67
+ s.add_dependency(%q<mocha>, [">= 0"])
68
+ end
69
+ end
70
+
@@ -13,7 +13,11 @@ unless defined?(Happening)
13
13
  require File.expand_path(File.dirname(__FILE__) + '/happening/s3/item')
14
14
 
15
15
  module Happening
16
- VERSION = '0.2.4'
16
+ MAJOR = 0
17
+ MINOR = 2
18
+ PATCH = 5
19
+
20
+ VERSION = [MAJOR, MINOR, PATCH].compact.join('.')
17
21
  class Error < RuntimeError; end
18
22
  end
19
23
  end
@@ -0,0 +1,41 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class ItemTest < Test::Unit::TestCase
4
+ context "An Happening::AWS instance" do
5
+
6
+ setup do
7
+ @aws = Happening::AWS.new('the-aws-access-key', 'the-aws-secret-key')
8
+ end
9
+
10
+ context "when constructing" do
11
+ should "require Access Key and Secret Key" do
12
+ assert_raise(ArgumentError) do
13
+ Happening::AWS.new(nil, nil)
14
+ end
15
+
16
+ assert_raise(ArgumentError) do
17
+ Happening::AWS.new('', '')
18
+ end
19
+
20
+ assert_nothing_raised do
21
+ Happening::AWS.new('abc', 'abc')
22
+ end
23
+ end
24
+ end
25
+
26
+ context "when signing parameters" do
27
+ should "return a header hash" do
28
+ assert_not_nil @aws.sign("GET", '/')['Authorization']
29
+ end
30
+
31
+ should "include the current date" do
32
+ assert_not_nil @aws.sign("GET", '/')['date']
33
+ end
34
+
35
+ should "keep given headers" do
36
+ assert_equal 'bar', @aws.sign("GET", '/', {'foo' => 'bar'})['foo']
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,531 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class ItemTest < Test::Unit::TestCase
4
+ context "An Happening::S3::Item instance" do
5
+
6
+ setup do
7
+ Happening::Log.level = Logger::ERROR
8
+ @item = Happening::S3::Item.new('the-bucket', 'the-key', :aws_access_key_id => '123', :aws_secret_access_key => 'secret', :server => '127.0.0.1')
9
+
10
+ @time = "Thu, 25 Feb 2010 10:00:00 GMT"
11
+ Time.stubs(:now).returns(Time.parse(@time))
12
+ #stub(:utc_httpdate => @time, :to_i => 99, :usec => 88))
13
+ end
14
+
15
+ context "validation" do
16
+ should "require a bucket and a key" do
17
+ assert_raise(ArgumentError) do
18
+ item = Happening::S3::Item.new()
19
+ end
20
+
21
+ assert_raise(ArgumentError) do
22
+ item = Happening::S3::Item.new('the-key')
23
+ end
24
+
25
+ assert_nothing_raised(ArgumentError) do
26
+ item = Happening::S3::Item.new('the-bucket', 'the-key')
27
+ end
28
+
29
+ end
30
+
31
+ should "not allow unknown options" do
32
+ assert_raise(ArgumentError) do
33
+ item = Happening::S3::Item.new('the-bucket', 'the-key', :aws_access_key_id => '123', :aws_secret_access_key => 'secret', :lala => 'lulul')
34
+ end
35
+ end
36
+
37
+ should "check valid protocol" do
38
+ assert_raise(ArgumentError) do
39
+ item = Happening::S3::Item.new('the-bucket', 'the-key', :aws_access_key_id => '123', :aws_secret_access_key => 'secret', :protocol => 'lulul')
40
+ end
41
+
42
+ assert_nothing_raised do
43
+ item = Happening::S3::Item.new('the-bucket', 'the-key', :aws_access_key_id => '123', :aws_secret_access_key => 'secret', :protocol => 'http')
44
+ end
45
+
46
+ assert_nothing_raised do
47
+ item = Happening::S3::Item.new('the-bucket', 'the-key', :aws_access_key_id => '123', :aws_secret_access_key => 'secret', :protocol => 'https')
48
+ end
49
+ end
50
+ end
51
+
52
+ context "when building the item url" do
53
+ should "build the full path out of the server, bucket, and key" do
54
+ @item = Happening::S3::Item.new('the-bucketissoooooooooooooooooooooooooooooooooooooolonggggggggggggggggggggggggggggggggggg', 'the-key', :aws_access_key_id => '123', :aws_secret_access_key => 'secret', :server => '127.0.0.1')
55
+ assert_equal "https://127.0.0.1:443/the-bucketissoooooooooooooooooooooooooooooooooooooolonggggggggggggggggggggggggggggggggggg/the-key", @item.url
56
+ end
57
+
58
+ should "use the DNS bucket name where possible" do
59
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => '123', :aws_secret_access_key => 'secret')
60
+ assert_equal "https://bucket.s3.amazonaws.com:443/the-key", @item.url
61
+ end
62
+ end
63
+
64
+ context "when getting an item" do
65
+
66
+ should "call the on success callback" do
67
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :get, {}, fake_response("data-here"))
68
+
69
+ called = false
70
+ data = nil
71
+ on_success = Proc.new {|http| called = true, data = http.response}
72
+ @item = Happening::S3::Item.new('bucket', 'the-key')
73
+ run_in_em_loop do
74
+ @item.get(:on_success => on_success)
75
+
76
+ EM.add_timer(1) {
77
+ assert called
78
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :get, {})
79
+ assert_equal "data-here\n", data
80
+ EM.stop_event_loop
81
+ }
82
+
83
+ end
84
+ end
85
+
86
+ should "support direct blocks" do
87
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :get, {}, fake_response("data-here"))
88
+
89
+ called = false
90
+ data = nil
91
+ @item = Happening::S3::Item.new('bucket', 'the-key')
92
+ run_in_em_loop do
93
+ @item.get do |http|
94
+ called = true
95
+ data = http.response
96
+ end
97
+
98
+ EM.add_timer(1) {
99
+ assert called
100
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :get, {})
101
+ assert_equal "data-here\n", data
102
+ EM.stop_event_loop
103
+ }
104
+
105
+ end
106
+ end
107
+
108
+ should "support stream blocks" do
109
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :get, {}, fake_response(""))
110
+
111
+ called = false
112
+ data = ""
113
+ @item = Happening::S3::Item.new('bucket', 'the-key')
114
+ run_in_em_loop do
115
+ response = @item.get
116
+ response.stream do |chunk|
117
+ called = true
118
+ data << chunk
119
+ end
120
+ response.on_body_data "data-here"
121
+
122
+ EM.add_timer(1) {
123
+ assert called
124
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :get, {})
125
+ assert_equal "data-here", data
126
+ EM.stop_event_loop
127
+ }
128
+
129
+ end
130
+ end
131
+
132
+ should "sign requests if AWS credentials are passend" do
133
+ time = "Thu, 25 Feb 2010 12:06:33 GMT"
134
+ Time.stubs(:now).returns(Time.parse(time))
135
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :get, {"Authorization"=>"AWS abc:3OEcVbE//maUUmqh3A5ETEcr9TE=", 'date' => time}, fake_response("data-here"))
136
+
137
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
138
+ run_in_em_loop do
139
+ @item.get
140
+
141
+ EM.add_timer(1) {
142
+ EM.stop_event_loop
143
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :get, {"Authorization"=>"AWS abc:3OEcVbE//maUUmqh3A5ETEcr9TE=", 'date' => time})
144
+ }
145
+
146
+ end
147
+ end
148
+
149
+ should "retry on error" do
150
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :get, {}, error_response(400))
151
+
152
+ @item = Happening::S3::Item.new('bucket', 'the-key')
153
+ run_in_em_loop do
154
+ @item.get(:on_error => Proc.new{} ) #ignore error
155
+
156
+ EM.add_timer(1) {
157
+ EM.stop_event_loop
158
+ assert_equal 5, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :get, {})
159
+ }
160
+
161
+ end
162
+ end
163
+
164
+ should "handle re-direct" do
165
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :get, {}, redirect_response('https://bucket.s3-external-3.amazonaws.com/the-key'))
166
+ EventMachine::MockHttpRequest.register('https://bucket.s3-external-3.amazonaws.com:443/the-key', :get, {}, fake_response('hy there'))
167
+
168
+ @item = Happening::S3::Item.new('bucket', 'the-key')
169
+ run_in_em_loop do
170
+ @item.get
171
+
172
+ EM.add_timer(1) {
173
+ EM.stop_event_loop
174
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :get, {})
175
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3-external-3.amazonaws.com:443/the-key', :get, {})
176
+ }
177
+
178
+ end
179
+ end
180
+ end
181
+
182
+ context "when deleting an item" do
183
+ should "send a DELETE to the items location" do
184
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :delete, {
185
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
186
+ 'date' => @time,
187
+ 'url' => "/bucket/the-key"}, fake_response("data-here"))
188
+
189
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
190
+ run_in_em_loop do
191
+ @item.delete
192
+
193
+ EM.add_timer(1) {
194
+ EM.stop_event_loop
195
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :delete, {
196
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
197
+ 'date' => @time,
198
+ 'url' => "/bucket/the-key"})
199
+ }
200
+
201
+ end
202
+ end
203
+
204
+ should "support direct blocks" do
205
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :delete, {
206
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
207
+ 'date' => @time,
208
+ 'url' => "/bucket/the-key"}, fake_response("data-here"))
209
+
210
+ called = false
211
+ data = nil
212
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
213
+ run_in_em_loop do
214
+ @item.delete do |http|
215
+ called = true
216
+ data = http.response
217
+ end
218
+
219
+ EM.add_timer(1) {
220
+ assert called
221
+ assert_equal "data-here\n", data
222
+ EM.stop_event_loop
223
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :delete, {
224
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
225
+ 'date' => @time,
226
+ 'url' => "/bucket/the-key"})
227
+ }
228
+
229
+ end
230
+ end
231
+
232
+ should "handle re-direct" do
233
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :delete, {
234
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
235
+ 'date' => @time,
236
+ 'url' => "/bucket/the-key"}, redirect_response('https://bucket.s3-external-3.amazonaws.com/the-key'))
237
+ EventMachine::MockHttpRequest.register('https://bucket.s3-external-3.amazonaws.com:443/the-key', :delete, {
238
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
239
+ 'date' => @time,
240
+ 'url' => "/bucket/the-key"}, fake_response("success!"))
241
+
242
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
243
+ run_in_em_loop do
244
+ @item.delete
245
+
246
+ EM.add_timer(1) {
247
+ EM.stop_event_loop
248
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :delete, {
249
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
250
+ 'date' => @time,
251
+ 'url' => "/bucket/the-key"})
252
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3-external-3.amazonaws.com:443/the-key', :delete, {
253
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
254
+ 'date' => @time,
255
+ 'url' => "/bucket/the-key"})
256
+ }
257
+
258
+ end
259
+ end
260
+
261
+ should "handle retry" do
262
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :delete, {
263
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
264
+ 'date' => @time,
265
+ 'url' => "/bucket/the-key"}, error_response(400))
266
+
267
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
268
+ run_in_em_loop do
269
+ @item.delete(:on_error => Proc.new{} ) #ignore error
270
+
271
+ EM.add_timer(1) {
272
+ EM.stop_event_loop
273
+ assert_equal 5, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :delete, {
274
+ "Authorization"=>"AWS abc:nvkrlq4wor1qbFXZh6rHnAbiRjk=",
275
+ 'date' => @time,
276
+ 'url' => "/bucket/the-key"})
277
+ }
278
+
279
+ end
280
+ end
281
+ end
282
+
283
+ context "when loading the headers" do
284
+ should "request via HEAD" do
285
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :head, {}, fake_response('hy there'))
286
+
287
+ @item = Happening::S3::Item.new('bucket', 'the-key')
288
+ run_in_em_loop do
289
+ @item.head
290
+
291
+ EM.add_timer(1) {
292
+ EM.stop_event_loop
293
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :head, {})
294
+ }
295
+
296
+ end
297
+ end
298
+ end
299
+
300
+ context "when saving an item" do
301
+
302
+ should "post to the desired location" do
303
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :put, {
304
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
305
+ 'date' => @time,
306
+ 'url' => "/bucket/the-key"}, fake_response("data-here"))
307
+
308
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
309
+ run_in_em_loop do
310
+ @item.put('content')
311
+
312
+ EM.add_timer(1) {
313
+ EM.stop_event_loop
314
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :put, {
315
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
316
+ 'date' => @time,
317
+ 'url' => "/bucket/the-key"})
318
+ }
319
+
320
+ end
321
+ end
322
+
323
+ should "support direct blocks" do
324
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :put, {
325
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
326
+ 'date' => @time,
327
+ 'url' => "/bucket/the-key"}, fake_response("data-here"))
328
+
329
+ called = false
330
+ data = nil
331
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
332
+ run_in_em_loop do
333
+ @item.put('upload me') do |http|
334
+ called = true
335
+ data = http.response
336
+ end
337
+
338
+ EM.add_timer(1) {
339
+ assert called
340
+ assert_equal "data-here\n", data
341
+ EM.stop_event_loop
342
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :put, {
343
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
344
+ 'date' => @time,
345
+ 'url' => "/bucket/the-key"})
346
+ }
347
+
348
+ end
349
+ end
350
+
351
+ should "set the desired permissions" do
352
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :put, {
353
+ "Authorization"=>"AWS abc:cqkfX+nC7WIkYD+yWaUFuoRuePA=",
354
+ 'date' => @time,
355
+ 'url' => "/bucket/the-key",
356
+ "x-amz-acl" => 'public-read'}, fake_response("data-here"))
357
+
358
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123' , :permissions => 'public-read')
359
+ run_in_em_loop do
360
+ @item.put('content')
361
+
362
+ EM.add_timer(1) {
363
+ EM.stop_event_loop
364
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :put, {
365
+ "Authorization"=>"AWS abc:cqkfX+nC7WIkYD+yWaUFuoRuePA=",
366
+ 'date' => @time,
367
+ 'url' => "/bucket/the-key",
368
+ 'x-amz-acl' => 'public-read'})
369
+ }
370
+
371
+ end
372
+ end
373
+
374
+ should "allow to set custom headers" do
375
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :put, {
376
+ "Authorization"=>"AWS abc:wrPkGKrlwH2AtNzBVS80vU73TDc=",
377
+ 'date' => @time,
378
+ 'url' => "/bucket/the-key",
379
+ "x-amz-acl" => 'public-read',
380
+ 'Cache-Control' => "max-age=252460800",
381
+ 'Expires' => 'Fri, 16 Nov 2018 22:09:29 GMT',
382
+ 'x-amz-meta-abc' => 'ABC'}, fake_response("data-here"))
383
+
384
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc',
385
+ :aws_secret_access_key => '123' ,
386
+ :permissions => 'public-read')
387
+ run_in_em_loop do
388
+ @item.put('content', :headers => {
389
+ 'Expires' => 'Fri, 16 Nov 2018 22:09:29 GMT',
390
+ 'Cache-Control' => "max-age=252460800",
391
+ 'x-amz-meta-abc' => 'ABC'})
392
+
393
+ EM.add_timer(1) {
394
+ EM.stop_event_loop
395
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :put, {
396
+ "Authorization"=>"AWS abc:wrPkGKrlwH2AtNzBVS80vU73TDc=",
397
+ 'date' => @time,
398
+ 'url' => "/bucket/the-key",
399
+ 'x-amz-acl' => 'public-read',
400
+ 'Cache-Control' => "max-age=252460800",
401
+ 'Expires' => 'Fri, 16 Nov 2018 22:09:29 GMT',
402
+ 'x-amz-meta-abc' => 'ABC'})
403
+ }
404
+
405
+ end
406
+ end
407
+
408
+ should "validate the headers" do
409
+
410
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc',
411
+ :aws_secret_access_key => '123' ,
412
+ :permissions => 'public-read')
413
+
414
+ assert_raise(ArgumentError) do
415
+ @item.put('content', :headers => {
416
+ 'expires' => 'Fri, 16 Nov 2018 22:09:29 GMT',
417
+ 'cache_control' => "max-age=252460800"})
418
+ end
419
+ end
420
+
421
+ should "re-post to a new location" do
422
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :put, {
423
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
424
+ 'date' => @time,
425
+ 'url' => "/bucket/the-key"}, redirect_response('https://bucket.s3-external-3.amazonaws.com/the-key'))
426
+ EventMachine::MockHttpRequest.register('https://bucket.s3-external-3.amazonaws.com:443/the-key', :put, {
427
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
428
+ 'date' => @time,
429
+ 'url' => "/bucket/the-key"}, fake_response('Thanks!'))
430
+
431
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
432
+ run_in_em_loop do
433
+ @item.put('content')
434
+
435
+ EM.add_timer(1) {
436
+ EM.stop_event_loop
437
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :put, {
438
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
439
+ 'date' => @time,
440
+ 'url' => "/bucket/the-key"})
441
+
442
+ assert_equal 1, EventMachine::MockHttpRequest.count('https://bucket.s3-external-3.amazonaws.com:443/the-key', :put, {
443
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
444
+ 'date' => @time,
445
+ 'url' => "/bucket/the-key"})
446
+ }
447
+
448
+ end
449
+ end
450
+
451
+ should "retry on error" do
452
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :put, {
453
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
454
+ 'date' => @time,
455
+ 'url' => "/bucket/the-key"}, error_response(400))
456
+
457
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
458
+ run_in_em_loop do
459
+ @item.put('content', :on_error => Proc.new{} )
460
+
461
+ EM.add_timer(1) {
462
+ EM.stop_event_loop
463
+ assert_equal 5, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :put, {
464
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
465
+ 'date' => @time,
466
+ 'url' => "/bucket/the-key"})
467
+ }
468
+
469
+ end
470
+ end
471
+
472
+ should "call error handler after retry reached" do
473
+ EventMachine::MockHttpRequest.register('https://bucket.s3.amazonaws.com:443/the-key', :put, {
474
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
475
+ 'date' => @time,
476
+ 'url' => "/bucket/the-key"}, error_response(400))
477
+
478
+ called = false
479
+ on_error = Proc.new {|http| called = true}
480
+
481
+ @item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
482
+ run_in_em_loop do
483
+ @item.put('content', :on_error => on_error, :retry_count => 1)
484
+
485
+ EM.add_timer(1) {
486
+ EM.stop_event_loop
487
+ assert called
488
+ assert_equal 2, EventMachine::MockHttpRequest.count('https://bucket.s3.amazonaws.com:443/the-key', :put, {
489
+ "Authorization"=>"AWS abc:lZMKxGDKcQ1PH8yjbpyN7o2sPWg=",
490
+ 'date' => @time,
491
+ 'url' => "/bucket/the-key"})
492
+ }
493
+
494
+ end
495
+ end
496
+
497
+ end
498
+
499
+ context "SSL options" do
500
+ setup do
501
+ Happening::S3.ssl_options[:verify_peer] = true
502
+ Happening::S3.ssl_options[:cert_chain_file] = '/etc/foo.ca'
503
+ end
504
+
505
+ should "re-use the global options" do
506
+ item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
507
+ assert item.options[:ssl][:verify_peer]
508
+ assert_equal '/etc/foo.ca', item.options[:ssl][:cert_chain_file]
509
+ end
510
+
511
+ should "allow to override global options" do
512
+ item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123', :ssl => {:cert_chain_file => nil, :verify_peer => false})
513
+ assert !item.options[:ssl][:verify_peer]
514
+ assert_nil item.options[:ssl][:cert_chain_file]
515
+ end
516
+
517
+ should "pass the options to the Request" do
518
+ item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
519
+ Happening::S3::Request.expects(:new).with(:get, anything, {:ssl => {:cert_chain_file => '/etc/foo.ca', :verify_peer => true}, :headers => {'Authorization' => 'AWS abc:LGLdCdGTuLAHs+InbMWEnQR6djc=', 'date' => 'Thu, 25 Feb 2010 10:00:00 GMT'}}).returns(stub(:execute => nil))
520
+ item.get
521
+ end
522
+
523
+ should "allow to override the options per request" do
524
+ item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
525
+ Happening::S3::Request.expects(:new).with(:get, anything, {:ssl => {:foo => :bar}, :headers => {'Authorization' => 'AWS abc:LGLdCdGTuLAHs+InbMWEnQR6djc=', 'date' => 'Thu, 25 Feb 2010 10:00:00 GMT'}}).returns(stub(:execute => nil))
526
+ item.get(:ssl => {:foo => :bar})
527
+ end
528
+ end
529
+
530
+ end
531
+ end
@@ -0,0 +1,109 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class ItemTest < Test::Unit::TestCase
4
+ context "An Happening::S3::Request instance" do
5
+
6
+ setup do
7
+ Happening::Log.level = Logger::ERROR
8
+ @response_stub = stub()
9
+ @response_stub.stubs(:errback)
10
+ @response_stub.stubs(:callback)
11
+ end
12
+
13
+ context "validation" do
14
+ should "check HTTP method" do
15
+ assert_raise(ArgumentError) do
16
+ Happening::S3::Request.new(:foo, 'https://www.example.com')
17
+ end
18
+
19
+ assert_nothing_raised do
20
+ Happening::S3::Request.new(:get, 'https://www.example.com')
21
+ end
22
+ end
23
+
24
+ should "check the options" do
25
+ assert_raise(ArgumentError) do
26
+ Happening::S3::Request.new(:get, 'https://www.example.com', {:foo => :bar})
27
+ end
28
+
29
+ assert_nothing_raised do
30
+ Happening::S3::Request.new(:get, 'https://www.example.com', {:timeout => 4})
31
+ end
32
+ end
33
+ end
34
+
35
+ context "when executing" do
36
+ should "have no response before executing" do
37
+ assert_nil Happening::S3::Request.new(:get, 'https://www.example.com').response
38
+ end
39
+
40
+ should "call em-http-request" do
41
+ request = mock(:get => @response_stub)
42
+ EventMachine::MockHttpRequest.expects(:new).with('https://www.example.com').returns(request)
43
+ Happening::S3::Request.new(:get, 'https://www.example.com').execute
44
+ end
45
+
46
+ should "return the response" do
47
+ request = mock(:get => @response_stub)
48
+ EventMachine::MockHttpRequest.expects(:new).with('https://www.example.com').returns(request)
49
+ resp = Happening::S3::Request.new(:get, 'https://www.example.com').execute
50
+ assert_equal resp, @response_stub
51
+ end
52
+
53
+ should "pass the given headers and options" do
54
+ request = mock('em-http-request')
55
+ request.expects(:get).with(:timeout => 10, :head => {'a' => 'b'}, :body => nil, :ssl => {:verify_peer => false, :cert_chain_file => nil}).returns(@response_stub)
56
+ EventMachine::MockHttpRequest.expects(:new).with('https://www.example.com').returns(request)
57
+ Happening::S3::Request.new(:get, 'https://www.example.com', :headers => {'a' => 'b'}).execute
58
+ end
59
+
60
+ should "post any given data" do
61
+ request = mock('em-http-request')
62
+ request.expects(:put).with(:timeout => 10, :body => 'the-data', :head => {}, :ssl => {:verify_peer => false, :cert_chain_file => nil}).returns(@response_stub)
63
+ EventMachine::MockHttpRequest.expects(:new).with('https://www.example.com').returns(request)
64
+ Happening::S3::Request.new(:put, 'https://www.example.com', :data => 'the-data').execute
65
+ end
66
+
67
+ should "pass SSL options to em-http-request" do
68
+ request = mock('em-http-request')
69
+ request.expects(:put).with(:timeout => 10, :body => 'the-data', :head => {}, :ssl => {:verfiy_peer => true, :cert_chain_file => '/tmp/server.crt'}).returns(@response_stub)
70
+ EventMachine::MockHttpRequest.expects(:new).with('https://www.example.com').returns(request)
71
+ Happening::S3::Request.new(:put, 'https://www.example.com', :data => 'the-data', :ssl => {:verfiy_peer => true, :cert_chain_file => '/tmp/server.crt'}).execute
72
+ end
73
+
74
+ context "when handling errors" do
75
+ should "call the user error handler" do
76
+ EventMachine::MockHttpRequest.register('http://www.example.com:80/', :get, {}, error_response(400))
77
+
78
+ called = false
79
+ on_error = Proc.new {|http| called = true}
80
+
81
+ run_in_em_loop do
82
+ Happening::S3::Request.new(:get, 'http://www.example.com/', :on_error => on_error).execute
83
+
84
+ EM.add_timer(1) {
85
+ EM.stop_event_loop
86
+ assert called
87
+ assert_equal 5, EventMachine::MockHttpRequest.count('http://www.example.com:80/', :get, {})
88
+ }
89
+
90
+ end
91
+ end
92
+
93
+ should "use a default error handler if there is no user handler" do
94
+ EventMachine::MockHttpRequest.register('http://www.example.com:80/', :get, {}, error_response(400))
95
+
96
+ assert_raise(Happening::Error) do
97
+ run_in_em_loop do
98
+ Happening::S3::Request.new(:get, 'http://www.example.com/').execute
99
+ end
100
+ end
101
+ EM.stop_event_loop if EM.reactor_running?
102
+ end
103
+
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class S3Test < Test::Unit::TestCase
4
+ context "The Happening::S3 module" do
5
+
6
+ should "allow to set global SSL options" do
7
+ assert Happening::S3.respond_to?(:ssl_options)
8
+ assert Happening::S3.respond_to?(:ssl_options=)
9
+ end
10
+
11
+ should "set and get verify_peer" do
12
+ Happening::S3.ssl_options[:verify_peer] = true
13
+ assert Happening::S3.ssl_options[:verify_peer]
14
+ Happening::S3.ssl_options[:verify_peer] = false
15
+ assert !Happening::S3.ssl_options[:verify_peer]
16
+ end
17
+
18
+ should "set and get cert_chain_file" do
19
+ Happening::S3.ssl_options[:cert_chain_file] = '/etc/cacert'
20
+ assert_equal '/etc/cacert', Happening::S3.ssl_options[:cert_chain_file]
21
+ Happening::S3.ssl_options[:cert_chain_file] = nil
22
+ assert_nil Happening::S3.ssl_options[:cert_chain_file]
23
+ end
24
+
25
+ should "default to no certificate file and no verification" do
26
+ Happening::S3.instance_variable_set("@_ssl_options", nil)
27
+ assert !Happening::S3.ssl_options[:verify_peer]
28
+ assert_nil Happening::S3.ssl_options[:cert_chain_file]
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,94 @@
1
+ require 'rubygems'
2
+
3
+ require 'test/unit'
4
+ require 'shoulda'
5
+ require 'mocha'
6
+
7
+ $:.unshift(File.dirname(__FILE__) + "/../")
8
+
9
+ require 'happening'
10
+
11
+ require 'em-http/mock'
12
+
13
+ EventMachine.instance_eval do
14
+ # Switching out EM's defer since it makes tests just a tad more unreliable
15
+ alias :defer_original :defer
16
+ def defer
17
+ yield
18
+ end
19
+ end unless EM.respond_to?(:defer_original)
20
+
21
+ class Test::Unit::TestCase
22
+ def setup
23
+ EventMachine::MockHttpRequest.reset_counts!
24
+ EventMachine::MockHttpRequest.reset_registry!
25
+ end
26
+
27
+ def run_in_em_loop
28
+ EM.run {
29
+ yield
30
+ }
31
+ end
32
+ end
33
+
34
+ module Happening
35
+ module S3
36
+ class Request
37
+ def http_class
38
+ EventMachine::MockHttpRequest
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def fake_response(data)
45
+ <<-HEREDOC
46
+ HTTP/1.0 200 OK
47
+ Date: Mon, 16 Nov 2009 20:39:15 GMT
48
+ Expires: -1
49
+ Cache-Control: private, max-age=0
50
+ Content-Type: text/html; charset=ISO-8859-1
51
+ Set-Cookie: PREF=ID=9454187d21c4a6a6:TM=1258403955:LM=1258403955:S=2-mf1n5oV5yAeT9-; expires=Wed, 16-Nov-2011 20:39:15 GMT; path=/; domain=.google.ca
52
+ Set-Cookie: NID=28=lvxxVdiBQkCetu_WFaUxLyB7qPlHXS5OdAGYTqge_laVlCKVN8VYYeVBh4bNZiK_Oan2gm8oP9GA-FrZfMPC3ZMHeNq37MG2JH8AIW9LYucU8brOeuggMEbLNNXuiWg4; expires=Tue, 18-May-2010 20:39:15 GMT; path=/; domain=.google.ca; HttpOnly
53
+ Server: gws
54
+ X-XSS-Protection: 0
55
+ X-Cache: MISS from .
56
+ Via: 1.0 .:80 (squid)
57
+ Connection: close
58
+
59
+ #{data}
60
+ HEREDOC
61
+ end
62
+
63
+ # amazon tells us to upload to another location, e.g. happening-benchmark.s3-external-3.amazonaws.com instead of happening-benchmark.s3.amazonaws.com
64
+ def redirect_response(location)
65
+ <<-HEREDOC
66
+ HTTP/1.0 301 Moved Permanently
67
+ Date: Mon, 16 Nov 2009 20:39:15 GMT
68
+ Expires: -1
69
+ Cache-Control: private, max-age=0
70
+ Content-Type: text/html; charset=ISO-8859-1
71
+ Via: 1.0 .:80 (squid)
72
+ Connection: close
73
+ Location: #{location}
74
+
75
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>TemporaryRedirect</Code><Message>Please re-send this request to the specified temporary endpoint. Continue to use the original request endpoint for future requests.</Message><RequestId>137D5486D66095AE</RequestId><Bucket>happening-benchmark</Bucket><HostId>Nyk+Zq9GbtxcspdbKDWyGhsZhyUZquZP55tteYef4QVodsn73HUUad0xrIeD09lF</HostId><Endpoint>#{location}</Endpoint></Error>
76
+ HEREDOC
77
+ end
78
+
79
+ def error_response(error_code)
80
+ <<-HEREDOC
81
+ HTTP/1.0 #{error_code} OK
82
+ Date: Mon, 16 Nov 2009 20:39:15 GMT
83
+ Content-Type: text/html; charset=ISO-8859-1
84
+ Connection: close
85
+
86
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>TemporaryRedirect</Code><Message>Please re-send this request to the specified temporary endpoint. Continue to use the original request endpoint for future requests.</Message><RequestId>137D5486D66095AE</RequestId><Bucket>happening-benchmark</Bucket><HostId>Nyk+Zq9GbtxcspdbKDWyGhsZhyUZquZP55tteYef4QVodsn73HUUad0xrIeD09lF</HostId><Endpoint>https://s3.amazonaws.com</Endpoint></Error>
87
+ HEREDOC
88
+ end
89
+
90
+ module EventMachine
91
+ class MockHttpRequest
92
+ @@pass_through_requests = false
93
+ end
94
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: happening
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 29
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 4
10
- version: 0.2.4
9
+ - 5
10
+ version: 0.2.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jonathan Weiss
@@ -27,7 +27,7 @@ dependencies:
27
27
  segments:
28
28
  - 0
29
29
  version: "0"
30
- name: happening
30
+ name: em-http-request
31
31
  prerelease: false
32
32
  type: :runtime
33
33
  requirement: *id001
@@ -41,7 +41,7 @@ dependencies:
41
41
  segments:
42
42
  - 0
43
43
  version: "0"
44
- name: jeweler
44
+ name: shoulda
45
45
  prerelease: false
46
46
  type: :development
47
47
  requirement: *id002
@@ -49,13 +49,15 @@ dependencies:
49
49
  version_requirements: &id003 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
- - - ">="
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
- hash: 3
54
+ hash: 23
55
55
  segments:
56
+ - 1
56
57
  - 0
57
- version: "0"
58
- name: shoulda
58
+ - 0
59
+ version: 1.0.0
60
+ name: bundler
59
61
  prerelease: false
60
62
  type: :development
61
63
  requirement: *id003
@@ -63,13 +65,15 @@ dependencies:
63
65
  version_requirements: &id004 !ruby/object:Gem::Requirement
64
66
  none: false
65
67
  requirements:
66
- - - ">="
68
+ - - ~>
67
69
  - !ruby/object:Gem::Version
68
- hash: 3
70
+ hash: 7
69
71
  segments:
70
- - 0
71
- version: "0"
72
- name: mocha
72
+ - 1
73
+ - 6
74
+ - 4
75
+ version: 1.6.4
76
+ name: jeweler
73
77
  prerelease: false
74
78
  type: :development
75
79
  requirement: *id004
@@ -83,54 +87,12 @@ dependencies:
83
87
  segments:
84
88
  - 0
85
89
  version: "0"
86
- name: em-http-request
87
- prerelease: false
88
- type: :runtime
89
- requirement: *id005
90
- - !ruby/object:Gem::Dependency
91
- version_requirements: &id006 !ruby/object:Gem::Requirement
92
- none: false
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- hash: 3
97
- segments:
98
- - 0
99
- version: "0"
100
- name: jeweler
101
- prerelease: false
102
- type: :development
103
- requirement: *id006
104
- - !ruby/object:Gem::Dependency
105
- version_requirements: &id007 !ruby/object:Gem::Requirement
106
- none: false
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- hash: 3
111
- segments:
112
- - 0
113
- version: "0"
114
- name: shoulda
115
- prerelease: false
116
- type: :development
117
- requirement: *id007
118
- - !ruby/object:Gem::Dependency
119
- version_requirements: &id008 !ruby/object:Gem::Requirement
120
- none: false
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- hash: 3
125
- segments:
126
- - 0
127
- version: "0"
128
90
  name: mocha
129
91
  prerelease: false
130
92
  type: :development
131
- requirement: *id008
132
- description: An EventMachine based S3 client - using em-http-request
133
- email: info@peritor.com
93
+ requirement: *id005
94
+ description: "An EventMachine based S3 client "
95
+ email: jw@innerewut.de
134
96
  executables: []
135
97
 
136
98
  extensions: []
@@ -140,8 +102,12 @@ extra_rdoc_files:
140
102
  - README.md
141
103
  files:
142
104
  - CHANGELOG.md
105
+ - Gemfile
143
106
  - LICENSE.txt
144
107
  - README.md
108
+ - Rakefile
109
+ - benchmark/right_aws.rb
110
+ - happening.gemspec
145
111
  - lib/happening.rb
146
112
  - lib/happening/aws.rb
147
113
  - lib/happening/log.rb
@@ -149,9 +115,14 @@ files:
149
115
  - lib/happening/s3/item.rb
150
116
  - lib/happening/s3/request.rb
151
117
  - lib/happening/utils.rb
118
+ - test/aws_test.rb
119
+ - test/s3/item_test.rb
120
+ - test/s3/request_test.rb
121
+ - test/s3_test.rb
122
+ - test/test_helper.rb
152
123
  homepage: http://github.com/peritor/happening
153
- licenses: []
154
-
124
+ licenses:
125
+ - BSD
155
126
  post_install_message:
156
127
  rdoc_options: []
157
128