happening 0.2.4 → 0.2.5

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.
@@ -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