arachni-typhoeus 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG.markdown +43 -0
  3. data/Gemfile +9 -0
  4. data/Gemfile.lock +30 -0
  5. data/README.textile +6 -0
  6. data/Rakefile +40 -0
  7. data/VERSION +1 -0
  8. data/benchmarks/profile.rb +25 -0
  9. data/benchmarks/vs_nethttp.rb +35 -0
  10. data/examples/twitter.rb +21 -0
  11. data/ext/typhoeus/.gitignore +7 -0
  12. data/ext/typhoeus/extconf.rb +65 -0
  13. data/ext/typhoeus/native.c +11 -0
  14. data/ext/typhoeus/native.h +21 -0
  15. data/ext/typhoeus/typhoeus_easy.c +220 -0
  16. data/ext/typhoeus/typhoeus_easy.h +19 -0
  17. data/ext/typhoeus/typhoeus_multi.c +211 -0
  18. data/ext/typhoeus/typhoeus_multi.h +16 -0
  19. data/lib/typhoeus.rb +58 -0
  20. data/lib/typhoeus/.gitignore +1 -0
  21. data/lib/typhoeus/easy.rb +366 -0
  22. data/lib/typhoeus/filter.rb +28 -0
  23. data/lib/typhoeus/hydra.rb +245 -0
  24. data/lib/typhoeus/hydra/callbacks.rb +24 -0
  25. data/lib/typhoeus/hydra/connect_options.rb +61 -0
  26. data/lib/typhoeus/hydra/stubbing.rb +52 -0
  27. data/lib/typhoeus/hydra_mock.rb +131 -0
  28. data/lib/typhoeus/multi.rb +37 -0
  29. data/lib/typhoeus/normalized_header_hash.rb +58 -0
  30. data/lib/typhoeus/remote.rb +306 -0
  31. data/lib/typhoeus/remote_method.rb +108 -0
  32. data/lib/typhoeus/remote_proxy_object.rb +50 -0
  33. data/lib/typhoeus/request.rb +210 -0
  34. data/lib/typhoeus/response.rb +91 -0
  35. data/lib/typhoeus/service.rb +20 -0
  36. data/lib/typhoeus/utils.rb +24 -0
  37. data/profilers/valgrind.rb +24 -0
  38. data/spec/fixtures/result_set.xml +60 -0
  39. data/spec/servers/app.rb +84 -0
  40. data/spec/spec.opts +2 -0
  41. data/spec/spec_helper.rb +11 -0
  42. data/spec/typhoeus/easy_spec.rb +284 -0
  43. data/spec/typhoeus/filter_spec.rb +35 -0
  44. data/spec/typhoeus/hydra_mock_spec.rb +300 -0
  45. data/spec/typhoeus/hydra_spec.rb +526 -0
  46. data/spec/typhoeus/multi_spec.rb +74 -0
  47. data/spec/typhoeus/normalized_header_hash_spec.rb +41 -0
  48. data/spec/typhoeus/remote_method_spec.rb +141 -0
  49. data/spec/typhoeus/remote_proxy_object_spec.rb +65 -0
  50. data/spec/typhoeus/remote_spec.rb +695 -0
  51. data/spec/typhoeus/request_spec.rb +276 -0
  52. data/spec/typhoeus/response_spec.rb +151 -0
  53. data/spec/typhoeus/utils_spec.rb +22 -0
  54. data/typhoeus.gemspec +123 -0
  55. metadata +196 -0
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Typhoeus::Easy do
4
+ it "should save easy handles that get added" do
5
+ multi = Typhoeus::Multi.new
6
+ easy = Typhoeus::Easy.new
7
+ easy.url = "http://localhost:3002"
8
+ easy.method = :get
9
+
10
+ multi.add(easy)
11
+ multi.easy_handles.should == [easy]
12
+ multi.perform
13
+ multi.easy_handles.should == []
14
+ end
15
+
16
+ it "should be reusable" do
17
+ easy = Typhoeus::Easy.new
18
+ easy.url = "http://localhost:3002"
19
+ easy.method = :get
20
+
21
+ multi = Typhoeus::Multi.new
22
+ multi.add(easy)
23
+ multi.perform
24
+ easy.response_code.should == 200
25
+ JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "GET"
26
+
27
+ e2 = Typhoeus::Easy.new
28
+ e2.url = "http://localhost:3002"
29
+ e2.method = :post
30
+ multi.add(e2)
31
+ multi.perform
32
+
33
+ e2.response_code.should == 200
34
+ JSON.parse(e2.response_body)["REQUEST_METHOD"].should == "POST"
35
+ end
36
+
37
+ it "should perform easy handles added after the first one runs" do
38
+ easy = Typhoeus::Easy.new
39
+ easy.url = "http://localhost:3002"
40
+ easy.method = :get
41
+ multi = Typhoeus::Multi.new
42
+ multi.add(easy)
43
+
44
+ e2 = Typhoeus::Easy.new
45
+ e2.url = "http://localhost:3002"
46
+ e2.method = :post
47
+ easy.on_success do |e|
48
+ multi.add(e2)
49
+ end
50
+
51
+ multi.perform
52
+ easy.response_code.should == 200
53
+ JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "GET"
54
+ e2.response_code.should == 200
55
+ JSON.parse(e2.response_body)["REQUEST_METHOD"].should == "POST"
56
+ end
57
+
58
+ # it "should do multiple gets" do
59
+ # multi = Typhoeus::Multi.new
60
+ #
61
+ # handles = []
62
+ # 5.times do |i|
63
+ # easy = Typhoeus::Easy.new
64
+ # easy.url = "http://localhost:3002"
65
+ # easy.method = :get
66
+ # easy.on_success {|e| puts "get #{i} succeeded"}
67
+ # easy.on_failure {|e| puts "get #{i} failed with #{e.response_code}"}
68
+ # handles << easy
69
+ # multi.add(easy)
70
+ # end
71
+ #
72
+ # multi.perform
73
+ # end
74
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Typhoeus::NormalizedHeaderHash do
4
+ before(:all) do
5
+ @klass = Typhoeus::NormalizedHeaderHash
6
+ end
7
+
8
+ it "should normalize keys on assignment" do
9
+ hash = @klass.new
10
+ hash['Content-Type'] = 'text/html'
11
+ hash['content-type'].should == 'text/html'
12
+ hash[:content_type].should == 'text/html'
13
+ hash['Accepts'] = 'text/javascript'
14
+ hash['accepts'].should == 'text/javascript'
15
+ end
16
+
17
+ it "should normalize the keys on instantiation" do
18
+ hash = @klass.new('Content-Type' => 'text/html', :x_http_header => 'foo', 'X-HTTP-USER' => 'bar')
19
+ hash.keys.should =~ ['Content-Type', 'X-Http-Header', 'X-Http-User']
20
+ end
21
+
22
+ it "should merge keys correctly" do
23
+ hash = @klass.new
24
+ hash.merge!('Content-Type' => 'fdsa')
25
+ hash['content-type'].should == 'fdsa'
26
+ end
27
+
28
+ it "should allow any casing of keys" do
29
+ hash = @klass.new
30
+ hash['Content-Type'] = 'fdsa'
31
+ hash['content-type'].should == 'fdsa'
32
+ hash['cOnTent-TYPE'].should == 'fdsa'
33
+ hash['Content-Type'].should == 'fdsa'
34
+ end
35
+
36
+ it "should support has_key?" do
37
+ hash = @klass.new
38
+ hash['Content-Type'] = 'fdsa'
39
+ hash.has_key?('cOntent-Type').should be_true
40
+ end
41
+ end
@@ -0,0 +1,141 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Typhoeus::RemoteMethod do
4
+ it "should take options" do
5
+ Typhoeus::RemoteMethod.new(:body => "foo")
6
+ end
7
+
8
+ describe "http_method" do
9
+ it "should return the http method" do
10
+ m = Typhoeus::RemoteMethod.new(:method => :put)
11
+ m.http_method.should == :put
12
+ end
13
+
14
+ it "should default to :get" do
15
+ m = Typhoeus::RemoteMethod.new
16
+ m.http_method.should == :get
17
+ end
18
+ end
19
+
20
+ it "should return the options" do
21
+ m = Typhoeus::RemoteMethod.new(:body => "foo")
22
+ m.options.should == {:body => "foo"}
23
+ end
24
+
25
+ it "should pull uri out of the options hash" do
26
+ m = Typhoeus::RemoteMethod.new(:base_uri => "http://pauldix.net")
27
+ m.base_uri.should == "http://pauldix.net"
28
+ m.options.should_not have_key(:base_uri)
29
+ end
30
+
31
+ describe "on_success" do
32
+ it "should return the block" do
33
+ m = Typhoeus::RemoteMethod.new(:on_success => lambda {:foo})
34
+ m.on_success.call.should == :foo
35
+ end
36
+ end
37
+
38
+ describe "on_failure" do
39
+ it "should return method name" do
40
+ m = Typhoeus::RemoteMethod.new(:on_failure => lambda {:bar})
41
+ m.on_failure.call.should == :bar
42
+ end
43
+ end
44
+
45
+ describe "path" do
46
+ it "should pull path out of the options hash" do
47
+ m = Typhoeus::RemoteMethod.new(:path => "foo")
48
+ m.path.should == "foo"
49
+ m.options.should_not have_key(:path)
50
+ end
51
+
52
+ it "should output argument names from the symbols in the path" do
53
+ m = Typhoeus::RemoteMethod.new(:path => "/posts/:post_id/comments/:comment_id")
54
+ m.argument_names.should == [:post_id, :comment_id]
55
+ end
56
+
57
+ it "should output an empty string when there are no arguments in path" do
58
+ m = Typhoeus::RemoteMethod.new(:path => "/default.html")
59
+ m.argument_names.should == []
60
+ end
61
+
62
+ it "should output and empty string when there is no path specified" do
63
+ m = Typhoeus::RemoteMethod.new
64
+ m.argument_names.should == []
65
+ end
66
+
67
+ it "should interpolate a path with arguments" do
68
+ m = Typhoeus::RemoteMethod.new(:path => "/posts/:post_id/comments/:comment_id")
69
+ m.interpolate_path_with_arguments(:post_id => 1, :comment_id => "asdf").should == "/posts/1/comments/asdf"
70
+ end
71
+
72
+ it "should provide the path when interpolated called and there is nothing to interpolate" do
73
+ m = Typhoeus::RemoteMethod.new(:path => "/posts/123")
74
+ m.interpolate_path_with_arguments(:foo => :bar).should == "/posts/123"
75
+ end
76
+ end
77
+
78
+ describe "#merge_options" do
79
+ it "should keep the passed in options first" do
80
+ m = Typhoeus::RemoteMethod.new("User-Agent" => "whatev", :foo => :bar)
81
+ m.merge_options({"User-Agent" => "http-machine"}).should == {"User-Agent" => "http-machine", :foo => :bar}
82
+ end
83
+
84
+ it "should combine the params" do
85
+ m = Typhoeus::RemoteMethod.new(:foo => :bar, :params => {:id => :asdf})
86
+ m.merge_options({:params => {:desc => :jkl}}).should == {:foo => :bar, :params => {:id => :asdf, :desc => :jkl}}
87
+ end
88
+ end
89
+
90
+ describe "memoize_reponses" do
91
+ before(:each) do
92
+ @m = Typhoeus::RemoteMethod.new(:memoize_responses => true)
93
+ @args = ["foo", "bar"]
94
+ @options = {:asdf => {:jkl => :bar}}
95
+ end
96
+
97
+ it "should store if responses should be memoized" do
98
+ @m.memoize_responses?.should be_true
99
+ @m.options.should == {}
100
+ end
101
+
102
+ it "should tell when a method is already called" do
103
+ @m.already_called?(@args, @options).should be_false
104
+ @m.calling(@args, @options)
105
+ @m.already_called?(@args, @options).should be_true
106
+ @m.already_called?([], {}).should be_false
107
+ end
108
+
109
+ it "should call response blocks and clear the methods that have been called" do
110
+ response_block_called = mock('response_block')
111
+ response_block_called.should_receive(:call).exactly(1).times
112
+
113
+ @m.add_response_block(lambda {|res| res.should == :foo; response_block_called.call}, @args, @options)
114
+ @m.calling(@args, @options)
115
+ @m.call_response_blocks(:foo, @args, @options)
116
+ @m.already_called?(@args, @options).should be_false
117
+ @m.call_response_blocks(:asdf, @args, @options) #just to make sure it doesn't actually call that block again
118
+ end
119
+ end
120
+
121
+ describe "cache_reponses" do
122
+ before(:each) do
123
+ @m = Typhoeus::RemoteMethod.new(:cache_responses => true)
124
+ @args = ["foo", "bar"]
125
+ @options = {:asdf => {:jkl => :bar}}
126
+ end
127
+
128
+ it "should store if responses should be cached" do
129
+ @m.cache_responses?.should be_true
130
+ @m.options.should == {}
131
+ end
132
+
133
+ it "should force memoization if caching is enabled" do
134
+ @m.memoize_responses?.should be_true
135
+ end
136
+
137
+ it "should store cache ttl" do
138
+ Typhoeus::RemoteMethod.new(:cache_responses => 30).cache_ttl.should == 30
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Typhoeus::RemoteProxyObject do
4
+ before(:each) do
5
+ @easy = Typhoeus::Easy.new
6
+ @easy.method = :get
7
+ @easy.url = "http://localhost:3001"
8
+ end
9
+
10
+ it "should take a caller and call the clear_memoized_proxy_objects" do
11
+ clear_proxy = lambda {}
12
+ clear_proxy.should_receive(:call)
13
+ response = Typhoeus::RemoteProxyObject.new(clear_proxy, @easy)
14
+ response.code.should == 200
15
+ end
16
+
17
+ it "should take an easy object and return the body when requested" do
18
+ response = Typhoeus::RemoteProxyObject.new(lambda {}, @easy)
19
+ @easy.response_code.should == 0
20
+ response.code.should == 200
21
+ end
22
+
23
+ it "should perform requests only on the first access" do
24
+ response = Typhoeus::RemoteProxyObject.new(lambda {}, @easy)
25
+ response.code.should == 200
26
+ Typhoeus.should_receive(:perform_easy_requests).exactly(0).times
27
+ response.code.should == 200
28
+ end
29
+
30
+ it "should set the requested_url and requested_http_method on the response" do
31
+ response = Typhoeus::RemoteProxyObject.new(lambda {}, @easy)
32
+ response.requested_url.should == "http://localhost:3001"
33
+ response.requested_http_method.should == :get
34
+ end
35
+
36
+ it "should call the on_success method with an easy object and proxy to the result of on_success" do
37
+ klass = Class.new do
38
+ def initialize(r)
39
+ @response = r
40
+ end
41
+
42
+ def blah
43
+ @response.code
44
+ end
45
+ end
46
+
47
+ k = Typhoeus::RemoteProxyObject.new(lambda {}, @easy, :on_success => lambda {|e| klass.new(e)})
48
+ k.blah.should == 200
49
+ end
50
+
51
+ it "should call the on_failure method with an easy object and proxy to the result of on_failure" do
52
+ klass = Class.new do
53
+ def initialize(r)
54
+ @response = r
55
+ end
56
+
57
+ def blah
58
+ @response.code
59
+ end
60
+ end
61
+ @easy.url = "http://localhost:3005" #bad port
62
+ k = Typhoeus::RemoteProxyObject.new(lambda {}, @easy, :on_failure => lambda {|e| klass.new(e)})
63
+ k.blah.should == 0
64
+ end
65
+ end
@@ -0,0 +1,695 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Typhoeus do
4
+ it "should be deprecated" do
5
+ pending "This entire interface is deprecated!"
6
+ end
7
+
8
+ # before(:each) do
9
+ # @klass = Class.new do
10
+ # include Typhoeus
11
+ # end
12
+ # end
13
+ #
14
+ # describe "entirely disallowing HTTP connections in specs" do
15
+ # describe "allow_net_connect" do
16
+ # it "should default to true" do
17
+ # @klass.allow_net_connect.should be_true
18
+ # end
19
+ #
20
+ # it "should be settable" do
21
+ # @klass.allow_net_connect.should be_true
22
+ # @klass.allow_net_connect = false
23
+ # @klass.allow_net_connect.should be_false
24
+ # end
25
+ # end
26
+ #
27
+ # describe "and hitting a URL that hasn't been mocked" do
28
+ # it "should raise an error for any HTTP verbs" do
29
+ # @klass.allow_net_connect = false
30
+ #
31
+ # [:get, :put, :post, :delete].each do |method|
32
+ # lambda {
33
+ # @klass.send(method, "http://crazy_url_that_isnt_mocked.com")
34
+ # }.should raise_error(Typhoeus::MockExpectedError)
35
+ # end
36
+ # end
37
+ # end
38
+ #
39
+ # describe "hitting a mocked URL that returns false" do
40
+ # it "should not raise a MockExpectedError" do
41
+ # @klass.allow_net_connect = false
42
+ # @klass.mock(:delete,
43
+ # :url => "http://test.com",
44
+ # :code => 500,
45
+ # :body => 'ok')
46
+ #
47
+ # lambda {
48
+ # @klass.delete("http://test.com",
49
+ # :on_failure => lambda { |response| false })
50
+ # }.should_not raise_error
51
+ # end
52
+ # end
53
+ #
54
+ # describe "handlers" do
55
+ # it "should be able to return nil as part of their block" do
56
+ # @klass.allow_net_connect = false
57
+ # url = 'http://api.mysite.com/v1/stuff.json'
58
+ # @klass.mock(:get,
59
+ # :url => url,
60
+ # :body => '',
61
+ # :code => 500)
62
+ # result = @klass.get(url,
63
+ # :on_failure => lambda { |response| nil })
64
+ # result.should be_nil
65
+ # end
66
+ # end
67
+ # end
68
+ #
69
+ # describe "mocking" do
70
+ # it "should mock out GET" do
71
+ # @klass.mock(:get)
72
+ # response = @klass.get("http://mock_url")
73
+ # response.code.should == 200
74
+ # response.body.should == ""
75
+ # response.headers.should == ""
76
+ # response.time.should == 0
77
+ # end
78
+ #
79
+ # it "should mock out PUT" do
80
+ # @klass.mock(:put)
81
+ # response = @klass.put("http://mock_url")
82
+ # response.code.should == 200
83
+ # response.body.should == ""
84
+ # response.headers.should == ""
85
+ # response.time.should == 0
86
+ # end
87
+ #
88
+ # it "should mock out POST" do
89
+ # @klass.mock(:post)
90
+ # response = @klass.post("http://mock_url")
91
+ # response.code.should == 200
92
+ # response.body.should == ""
93
+ # response.headers.should == ""
94
+ # response.time.should == 0
95
+ # end
96
+ #
97
+ # it "should mock out DELETE" do
98
+ # @klass.mock(:delete)
99
+ # response = @klass.delete("http://mock_url")
100
+ # response.code.should == 200
101
+ # response.body.should == ""
102
+ # response.headers.should == ""
103
+ # response.time.should == 0
104
+ # end
105
+ #
106
+ # it "should take an optional url" do
107
+ # @klass.mock(:get, :url => "http://stuff")
108
+ # response = @klass.get("http://stuff")
109
+ # response.code.should == 200
110
+ # response.body.should == ""
111
+ # response.headers.should == ""
112
+ # response.time.should == 0
113
+ #
114
+ # @klass.get("http://localhost:234234234").code.should == 0
115
+ # end
116
+ #
117
+ # it "should be able to mock using specific params as well" do
118
+ # @klass.allow_net_connect = false
119
+ # @klass.mock(:get, :url => "http://stuff")
120
+ #
121
+ # lambda {
122
+ # @klass.get("http://stuff", :params => { :a => 'test' })
123
+ # }.should raise_error(Typhoeus::MockExpectedError)
124
+ #
125
+ # @klass.mock(:get,
126
+ # :url => "http://stuff",
127
+ # :params => { :a => 'test' })
128
+ # lambda {
129
+ # @klass.get("http://stuff", :params => { :a => 'test' })
130
+ # }.should_not raise_error(Typhoeus::MockExpectedError)
131
+ # end
132
+ #
133
+ # describe "request body expectations" do
134
+ # before(:all) do
135
+ # @body_klass = Class.new do
136
+ # include Typhoeus
137
+ # end
138
+ # @body_klass.mock(:put, :url => "http://whatev", :expected_body => "hi")
139
+ # end
140
+ #
141
+ # it "should take an expected request body" do
142
+ # @body_klass.put("http://whatev", :body => "hi").code.should == 200
143
+ # end
144
+ #
145
+ # it "should raise if the expected request body doesn't match" do
146
+ # lambda {
147
+ # @body_klass.put("http://whatev", :body => "not what we expect")
148
+ # }.should raise_error
149
+ # end
150
+ # end
151
+ #
152
+ # describe "check_expected_headers!" do
153
+ # before(:each) do
154
+ # @header_klass = Class.new do
155
+ # include Typhoeus
156
+ # end
157
+ # end
158
+ #
159
+ # it "should match a header with :anything" do
160
+ # lambda {
161
+ # @header_klass.check_expected_headers!(
162
+ # { :expected_headers => { 'Content-Type' => :anything } },
163
+ # { :headers => { 'Content-Type' => 'text/xml' } }
164
+ # )
165
+ # }.should_not raise_error
166
+ # end
167
+ #
168
+ # it "should enforce exact matching" do
169
+ # lambda {
170
+ # @header_klass.check_expected_headers!(
171
+ # { :expected_headers => { 'Content-Type' => 'text/html' } },
172
+ # { :headers => { 'Content-Type' => 'text/xml' } }
173
+ # )
174
+ # }.should raise_error
175
+ # end
176
+ # end
177
+ #
178
+ # describe "check_unexpected_headers!" do
179
+ # before(:each) do
180
+ # @header_klass = Class.new do
181
+ # include Typhoeus
182
+ # end
183
+ # end
184
+ #
185
+ # it "should match a header with :anything" do
186
+ # lambda {
187
+ # @header_klass.check_unexpected_headers!(
188
+ # { :unexpected_headers => { 'Content-Type' => :anything } },
189
+ # { :headers => { "Content-Type" => "text/xml" } }
190
+ # )
191
+ # }.should raise_error
192
+ # end
193
+ #
194
+ # it "should not match if a header is different from the expected value" do
195
+ # lambda {
196
+ # @header_klass.check_unexpected_headers!(
197
+ # { :unexpected_headers => { 'Content-Type' => 'text/html' } },
198
+ # { :headers => { "Content-Type" => "text/xml" } }
199
+ # )
200
+ # }.should_not raise_error
201
+ # end
202
+ # end
203
+ #
204
+ # describe "request header expectations" do
205
+ # before(:all) do
206
+ # @header_klass = Class.new do
207
+ # include Typhoeus
208
+ # end
209
+ # @header_klass.mock(:get,
210
+ # :url => "http://asdf",
211
+ # :expected_headers => {"If-None-Match" => "\"lkjsd90823\""},
212
+ # :unexpected_headers => { 'Content-Type' => "text/xml" })
213
+ # end
214
+ #
215
+ # it "should take expected request headers" do
216
+ # @header_klass.get("http://asdf", :headers => {"If-None-Match" => "\"lkjsd90823\""})
217
+ # end
218
+ #
219
+ # it "should raise if the expected request headers don't match" do
220
+ # lambda {
221
+ # @header_klass.get("http://asdf")
222
+ # }.should raise_error
223
+ # end
224
+ #
225
+ # it "should raise if an unexpected header shows up" do
226
+ # lambda {
227
+ # @header_klass.get("http://asdf",
228
+ # :headers => { "Content-Type" => "text/xml" })
229
+ # }.should raise_error
230
+ # end
231
+ # end
232
+ #
233
+ # describe "remote methods" do
234
+ # it "should work for defined remote methods" do
235
+ # @klass.instance_eval do
236
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|r| r.body.should == "hi"; :great_success}
237
+ # end
238
+ # @klass.mock(:get, :url => "http://localhost:3001", :body => "hi")
239
+ # @klass.do_stuff.should == :great_success
240
+ # end
241
+ #
242
+ # it "should call the on failure handler for remote methods" do
243
+ # @klass.instance_eval do
244
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_failure => lambda {|r| r.body.should == "hi"; :fail}
245
+ # end
246
+ # @klass.mock(:get, :url => "http://localhost:3001", :body => "hi", :code => 500)
247
+ # @klass.do_stuff.should == :fail
248
+ # end
249
+ #
250
+ # it "should allow for subclassing a class that includes Typhoeus, and merging defaults" do
251
+ # class TestA
252
+ # include Typhoeus
253
+ # remote_defaults :on_failure => lambda { |response|
254
+ # :fail
255
+ # }
256
+ # end
257
+ #
258
+ # class TestB < TestA
259
+ # remote_defaults :base_uri => "http://localhost"
260
+ # define_remote_method :do_stuff
261
+ # end
262
+ #
263
+ # TestB.mock(:get, :url => "http://localhost", :body => "hi", :code => 500)
264
+ # TestB.do_stuff.should == :fail
265
+ # end
266
+ # end
267
+ #
268
+ # describe "response hash" do
269
+ # it "should use provided code" do
270
+ # @klass.mock(:get, :url => "http://localhost/whatever", :code => 301)
271
+ # response = @klass.get("http://localhost/whatever")
272
+ # response.code.should == 301
273
+ # response.body.should == ""
274
+ # response.headers.should == ""
275
+ # response.time.should == 0
276
+ # end
277
+ #
278
+ # it "should use provided body" do
279
+ # @klass.mock(:get, :url => "http://localhost/whatever", :body => "hey paul")
280
+ # response = @klass.get("http://localhost/whatever")
281
+ # response.code.should == 200
282
+ # response.body.should == "hey paul"
283
+ # response.headers.should == ""
284
+ # response.time.should == 0
285
+ # end
286
+ #
287
+ # it "should use provided headers" do
288
+ # @klass.mock(:get, :url => "http://localhost/whatever", :headers => "whooo, headers!")
289
+ # response = @klass.get("http://localhost/whatever")
290
+ # response.code.should == 200
291
+ # response.body.should == ""
292
+ # response.headers.should == "whooo, headers!"
293
+ # response.time.should == 0
294
+ # end
295
+ #
296
+ # it "should use provided time" do
297
+ # @klass.mock(:get, :url => "http://localhost/whatever", :time => 123)
298
+ # response = @klass.get("http://localhost/whatever")
299
+ # response.code.should == 200
300
+ # response.body.should == ""
301
+ # response.headers.should == ""
302
+ # response.time.should == 123
303
+ # end
304
+ # end
305
+ # end
306
+ #
307
+ # describe "get" do
308
+ # it "should add a get method" do
309
+ # easy = @klass.get("http://localhost:3001/posts.xml")
310
+ # easy.code.should == 200
311
+ # easy.body.should include("REQUEST_METHOD=GET")
312
+ # easy.body.should include("REQUEST_URI=/posts.xml")
313
+ # end
314
+ #
315
+ # it "should take passed in params and add them to the query string" do
316
+ # easy = @klass.get("http://localhost:3001", {:params => {:foo => :bar}})
317
+ # easy.body.should include("QUERY_STRING=foo=bar")
318
+ # end
319
+ # end # get
320
+ #
321
+ # describe "post" do
322
+ # it "should add a post method" do
323
+ # easy = @klass.post("http://localhost:3001/posts.xml", {:params => {:post => {:author => "paul", :title => "a title", :body => "a body"}}})
324
+ # easy.code.should == 200
325
+ # easy.body.should include("post%5Bbody%5D=a+body")
326
+ # easy.body.should include("post%5Bauthor%5D=paul")
327
+ # easy.body.should include("post%5Btitle%5D=a+title")
328
+ # easy.body.should include("REQUEST_METHOD=POST")
329
+ # end
330
+ #
331
+ # it "should add a body" do
332
+ # easy = @klass.post("http://localhost:3001/posts.xml", {:body => "this is a request body"})
333
+ # easy.code.should == 200
334
+ # easy.body.should include("this is a request body")
335
+ # easy.body.should include("REQUEST_METHOD=POST")
336
+ # end
337
+ # end # post
338
+ #
339
+ # it "should add a put method" do
340
+ # easy = @klass.put("http://localhost:3001/posts/3.xml")
341
+ # easy.code.should == 200
342
+ # easy.body.should include("REQUEST_METHOD=PUT")
343
+ # end
344
+ #
345
+ # it "should add a delete method" do
346
+ # easy = @klass.delete("http://localhost:3001/posts/3.xml")
347
+ # easy.code.should == 200
348
+ # easy.body.should include("REQUEST_METHOD=DELETE")
349
+ # end
350
+ #
351
+ # describe "#define_remote_method" do
352
+ # before(:each) do
353
+ # @klass = Class.new do
354
+ # include Typhoeus
355
+ # end
356
+ # end
357
+ #
358
+ # describe "defined methods" do
359
+ # before(:each) do
360
+ # @klass.instance_eval do
361
+ # define_remote_method :do_stuff
362
+ # end
363
+ # end
364
+ #
365
+ # it "should take a method name as the first argument and define that as a class method" do
366
+ # @klass.should respond_to(:do_stuff)
367
+ # end
368
+ #
369
+ # it "should optionally take arguments" do
370
+ # @klass.should_receive(:get)
371
+ # @klass.do_stuff
372
+ # end
373
+ #
374
+ # it "should take arguments" do
375
+ # @klass.should_receive(:get).with("", {:params=>{:foo=>"bar"}, :body=>"whatever"})
376
+ # @klass.do_stuff(:params => {:foo => "bar"}, :body => "whatever")
377
+ # end
378
+ # end
379
+ #
380
+ # describe "base_uri" do
381
+ # it "should take a :uri as an argument" do
382
+ # @klass.instance_eval do
383
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
384
+ # end
385
+ #
386
+ # @klass.should_receive(:get).with("http://pauldix.net", {})
387
+ # @klass.do_stuff
388
+ # end
389
+ #
390
+ # it "should use default_base_uri if no base_uri provided" do
391
+ # @klass.instance_eval do
392
+ # remote_defaults :base_uri => "http://kgb.com"
393
+ # define_remote_method :do_stuff
394
+ # end
395
+ #
396
+ # @klass.should_receive(:get).with("http://kgb.com", {})
397
+ # @klass.do_stuff
398
+ # end
399
+ #
400
+ # it "should override default_base_uri if uri argument is provided" do
401
+ # @klass.instance_eval do
402
+ # remote_defaults :base_uri => "http://kgb.com"
403
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
404
+ # end
405
+ #
406
+ # @klass.should_receive(:get).with("http://pauldix.net", {})
407
+ # @klass.do_stuff
408
+ # end
409
+ # end
410
+ #
411
+ # describe "path" do
412
+ # it "should take :path as an argument" do
413
+ # @klass.instance_eval do
414
+ # define_remote_method :do_stuff, :base_uri => "http://kgb.com", :path => "/default.html"
415
+ # end
416
+ #
417
+ # @klass.should_receive(:get).with("http://kgb.com/default.html", {})
418
+ # @klass.do_stuff
419
+ # end
420
+ #
421
+ # it "should use deafult_path if no path provided" do
422
+ # @klass.instance_eval do
423
+ # remote_defaults :path => "/index.html"
424
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
425
+ # end
426
+ #
427
+ # @klass.should_receive(:get).with("http://pauldix.net/index.html", {})
428
+ # @klass.do_stuff
429
+ # end
430
+ #
431
+ # it "should orverride default_path if path argument is provided" do
432
+ # @klass.instance_eval do
433
+ # remote_defaults :path => "/index.html"
434
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :path => "/foo.html"
435
+ # end
436
+ #
437
+ # @klass.should_receive(:get).with("http://pauldix.net/foo.html", {})
438
+ # @klass.do_stuff
439
+ # end
440
+ #
441
+ # it "should map symbols in path to arguments for the remote method" do
442
+ # @klass.instance_eval do
443
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :path => "/posts/:post_id/comments/:comment_id"
444
+ # end
445
+ #
446
+ # @klass.should_receive(:get).with("http://pauldix.net/posts/foo/comments/bar", {})
447
+ # @klass.do_stuff(:post_id => "foo", :comment_id => "bar")
448
+ # end
449
+ #
450
+ # it "should use a path passed into the remote method call" do
451
+ # @klass.instance_eval do
452
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
453
+ # end
454
+ #
455
+ # @klass.should_receive(:get).with("http://pauldix.net/whatev?asdf=foo", {})
456
+ # @klass.do_stuff(:path => "/whatev?asdf=foo")
457
+ # end
458
+ # end
459
+ #
460
+ # describe "method" do
461
+ # it "should take :method as an argument" do
462
+ # @klass.instance_eval do
463
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :method => :put
464
+ # end
465
+ #
466
+ # @klass.should_receive(:put).with("http://pauldix.net", {})
467
+ # @klass.do_stuff
468
+ # end
469
+ #
470
+ # it "should use :get if no method or default_method exists" do
471
+ # @klass.instance_eval do
472
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net"
473
+ # end
474
+ #
475
+ # @klass.should_receive(:get).with("http://pauldix.net", {})
476
+ # @klass.do_stuff
477
+ # end
478
+ #
479
+ # it "should use default_method if no method provided" do
480
+ # @klass.instance_eval do
481
+ # remote_defaults :method => :delete
482
+ # define_remote_method :do_stuff, :base_uri => "http://kgb.com"
483
+ # end
484
+ #
485
+ # @klass.should_receive(:delete).with("http://kgb.com", {})
486
+ # @klass.do_stuff
487
+ # end
488
+ #
489
+ # it "should override deafult_method if method argument is provided" do
490
+ # @klass.instance_eval do
491
+ # remote_defaults :method => :put
492
+ # define_remote_method :do_stuff, :base_uri => "http://pauldix.net", :method => :post
493
+ # end
494
+ #
495
+ # @klass.should_receive(:post).with("http://pauldix.net", {})
496
+ # @klass.do_stuff
497
+ # end
498
+ # end
499
+ #
500
+ # describe "on_success" do
501
+ # it "should take :on_success as an argument" do
502
+ # @klass.instance_eval do
503
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|e| e.code.should == 200; :foo}
504
+ # end
505
+ #
506
+ # @klass.do_stuff.should == :foo
507
+ # end
508
+ #
509
+ # it "should use default_on_success if no on_success provided" do
510
+ # @klass.instance_eval do
511
+ # remote_defaults :on_success => lambda {|e| e.code.should == 200; :foo}
512
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001"
513
+ # end
514
+ #
515
+ # @klass.do_stuff.should == :foo
516
+ # end
517
+ #
518
+ # it "should override default_on_success if on_success is provided" do
519
+ # @klass.instance_eval do
520
+ # remote_defaults :on_success => lambda {|e| :foo}
521
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :on_success => lambda {|e| e.code.should == 200; :bar}
522
+ # end
523
+ #
524
+ # @klass.do_stuff.should == :bar
525
+ # end
526
+ # end
527
+ #
528
+ # describe "on_failure" do
529
+ # it "should take :on_failure as an argument" do
530
+ # @klass.instance_eval do
531
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:9999", :on_failure => lambda {|e| e.code.should == 0; :foo}
532
+ # end
533
+ #
534
+ # @klass.do_stuff.should == :foo
535
+ # end
536
+ #
537
+ # it "should use default_on_failure if no on_success provided" do
538
+ # @klass.instance_eval do
539
+ # remote_defaults :on_failure => lambda {|e| e.code.should == 0; :bar}
540
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:9999"
541
+ # end
542
+ #
543
+ # @klass.do_stuff.should == :bar
544
+ # end
545
+ #
546
+ # it "should override default_on_failure if no method is provided" do
547
+ # @klass.instance_eval do
548
+ # remote_defaults :on_failure => lambda {|e| :foo}
549
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:9999", :on_failure => lambda {|e| e.code.should == 0; :bar}
550
+ # end
551
+ #
552
+ # @klass.do_stuff.should == :bar
553
+ # end
554
+ # end
555
+ #
556
+ # describe "params" do
557
+ # it "should take :params as an argument" do
558
+ # @klass.instance_eval do
559
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :params => {:foo => :bar}
560
+ # end
561
+ #
562
+ # @klass.do_stuff.body.should include("QUERY_STRING=foo=bar")
563
+ # end
564
+ #
565
+ # it "should add :params from remote method definition with params passed in when called" do
566
+ # @klass.instance_eval do
567
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :params => {:foo => :bar}
568
+ # end
569
+ #
570
+ # result = @klass.do_stuff(:params => {:asdf => :jkl})
571
+ #
572
+ # # Make this test more robust to hash ordering.
573
+ # query_string = result.body.match(/QUERY_STRING=([^\n]+)/)
574
+ # params = query_string[1].split("&")
575
+ # ["asdf=jkl", "foo=bar"].each do |param|
576
+ # params.should include(param)
577
+ # end
578
+ # end
579
+ # end
580
+ #
581
+ # describe "memoize_responses" do
582
+ # it "should only make one call to the http method and the on_success handler if :memoize_responses => true" do
583
+ # success_mock = mock("success")
584
+ # success_mock.should_receive(:call).exactly(2).times
585
+ #
586
+ # @klass.instance_eval do
587
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :on_success => lambda {|e| success_mock.call; :foo}
588
+ # end
589
+ #
590
+ # first_return_val = @klass.do_stuff(:file => "user.html")
591
+ # second_return_val = @klass.do_stuff(:file => "post.html")
592
+ # third_return_val = @klass.do_stuff(:file => "user.html")
593
+ #
594
+ # first_return_val.should == :foo
595
+ # second_return_val.should == :foo
596
+ # third_return_val.should == :foo
597
+ # end
598
+ #
599
+ # it "should clear memoized responses after a full run" do
600
+ # success_mock = mock("success")
601
+ # success_mock.should_receive(:call).exactly(2).times
602
+ #
603
+ # @klass.instance_eval do
604
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :on_success => lambda {|e| success_mock.call; :foo}
605
+ # end
606
+ #
607
+ # @klass.do_stuff(:file => "user.html").should == :foo
608
+ # @klass.do_stuff(:file => "user.html").should == :foo
609
+ # end
610
+ # end
611
+ #
612
+ # describe "cache_response" do
613
+ # before(:each) do
614
+ # @cache = Class.new do
615
+ # def self.get(key)
616
+ # @cache ||= {}
617
+ # @cache[key]
618
+ # end
619
+ #
620
+ # def self.set(key, value, timeout = 0)
621
+ # @cache ||= {}
622
+ # @cache[key] = value
623
+ # end
624
+ # end
625
+ #
626
+ # @klass.instance_eval do
627
+ # define_remote_method :do_stuff, :base_uri => "http://localhost:3001", :path => "/:file", :cache_responses => true, :on_success => lambda {|e| :foo}
628
+ # end
629
+ # end
630
+ #
631
+ # it "should pull from the cache if :cache_response => true" do
632
+ # @cache.should_receive(:get).and_return(:foo)
633
+ # @klass.cache = @cache
634
+ # Typhoeus.should_receive(:perform_easy_requests).exactly(0).times
635
+ # @klass.do_stuff.should == :foo
636
+ # end
637
+ #
638
+ # it "should only hit the cache once for the same value" do
639
+ # @cache.should_receive(:get).exactly(1).times.and_return(:foo)
640
+ # @klass.cache = @cache
641
+ # Typhoeus.should_receive(:perform_easy_requests).exactly(0).times
642
+ #
643
+ #
644
+ # first = @klass.do_stuff
645
+ # second = @klass.do_stuff
646
+ #
647
+ # first.should == :foo
648
+ # second.should == :foo
649
+ # end
650
+ #
651
+ # it "should only hit the cache once if there is a cache miss (don't check again and again inside the same block)." do
652
+ # @cache.should_receive(:get).exactly(1).times.and_return(nil)
653
+ # @cache.should_receive(:set).exactly(1).times
654
+ # @klass.cache = @cache
655
+ #
656
+ # first = @klass.do_stuff
657
+ # second = @klass.do_stuff
658
+ #
659
+ # first.should == :foo
660
+ # second.should == :foo
661
+ # end
662
+ #
663
+ # it "should store an object in the cache with a set ttl"
664
+ # it "should take a hash with get and set method pointers to enable custom caching behavior"
665
+ # end
666
+ # end # define_remote_method
667
+ #
668
+ # describe "cache_server" do
669
+ # it "should store a cache_server" do
670
+ # @klass.cache = :foo
671
+ # end
672
+ # end
673
+ #
674
+ # describe "get_memcache_resposne_key" do
675
+ # it "should return a key that is an and of the method name, args, and options" do
676
+ # @klass.get_memcache_response_key(:do_stuff, ["foo"]).should == "20630a9d4864c41cbbcb8bd8ac91ab4767e72107b93329aa2e6f5629037392f3"
677
+ # end
678
+ # end
679
+ #
680
+ # # describe "multiple with post" do
681
+ # # require 'rubygems'
682
+ # # require 'json'
683
+ # # it "shoudl do stuff" do
684
+ # # @klass.instance_eval do
685
+ # # define_remote_method :post_stuff, :path => "/entries/metas/:meta_id/ids", :base_uri => "http://localhost:4567", :method => :post
686
+ # # define_remote_method :get_stuff, :base_uri => "http://localhost:4567"
687
+ # # end
688
+ # #
689
+ # # Typhoeus.service_access do
690
+ # # @klass.post_stuff("paul-tv", :body => ["foo", "bar"].to_json) {|e| }
691
+ # # @klass.get_stuff {|e| }
692
+ # # end
693
+ # # end
694
+ # # end
695
+ end