typhoeus 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/{CHANGELOG.markdown → CHANGELOG.md} +21 -12
  2. data/LICENSE +2 -0
  3. data/README.md +455 -0
  4. data/Rakefile +6 -26
  5. data/lib/typhoeus.rb +4 -6
  6. data/lib/typhoeus/curl.rb +453 -0
  7. data/lib/typhoeus/easy.rb +60 -358
  8. data/lib/typhoeus/easy/auth.rb +14 -0
  9. data/lib/typhoeus/easy/callbacks.rb +33 -0
  10. data/lib/typhoeus/easy/ffi_helper.rb +61 -0
  11. data/lib/typhoeus/easy/infos.rb +90 -0
  12. data/lib/typhoeus/easy/options.rb +115 -0
  13. data/lib/typhoeus/easy/proxy.rb +20 -0
  14. data/lib/typhoeus/easy/ssl.rb +82 -0
  15. data/lib/typhoeus/form.rb +30 -1
  16. data/lib/typhoeus/{normalized_header_hash.rb → header.rb} +2 -6
  17. data/lib/typhoeus/hydra.rb +9 -12
  18. data/lib/typhoeus/hydra_mock.rb +2 -2
  19. data/lib/typhoeus/multi.rb +118 -9
  20. data/lib/typhoeus/param_processor.rb +43 -0
  21. data/lib/typhoeus/request.rb +18 -21
  22. data/lib/typhoeus/response.rb +5 -4
  23. data/lib/typhoeus/utils.rb +14 -27
  24. data/lib/typhoeus/version.rb +1 -1
  25. metadata +155 -152
  26. data/Gemfile.lock +0 -37
  27. data/ext/typhoeus/.gitignore +0 -7
  28. data/ext/typhoeus/extconf.rb +0 -65
  29. data/ext/typhoeus/native.c +0 -12
  30. data/ext/typhoeus/native.h +0 -22
  31. data/ext/typhoeus/typhoeus_easy.c +0 -232
  32. data/ext/typhoeus/typhoeus_easy.h +0 -20
  33. data/ext/typhoeus/typhoeus_form.c +0 -59
  34. data/ext/typhoeus/typhoeus_form.h +0 -13
  35. data/ext/typhoeus/typhoeus_multi.c +0 -217
  36. data/ext/typhoeus/typhoeus_multi.h +0 -16
  37. data/lib/typhoeus/.gitignore +0 -1
  38. data/lib/typhoeus/service.rb +0 -20
  39. data/spec/fixtures/placeholder.gif +0 -0
  40. data/spec/fixtures/placeholder.txt +0 -1
  41. data/spec/fixtures/placeholder.ukn +0 -0
  42. data/spec/fixtures/result_set.xml +0 -60
  43. data/spec/servers/app.rb +0 -97
  44. data/spec/spec_helper.rb +0 -19
  45. data/spec/support/typhoeus_localhost_server.rb +0 -58
  46. data/spec/typhoeus/easy_spec.rb +0 -391
  47. data/spec/typhoeus/filter_spec.rb +0 -35
  48. data/spec/typhoeus/form_spec.rb +0 -117
  49. data/spec/typhoeus/hydra_mock_spec.rb +0 -300
  50. data/spec/typhoeus/hydra_spec.rb +0 -602
  51. data/spec/typhoeus/multi_spec.rb +0 -74
  52. data/spec/typhoeus/normalized_header_hash_spec.rb +0 -41
  53. data/spec/typhoeus/remote_method_spec.rb +0 -141
  54. data/spec/typhoeus/remote_proxy_object_spec.rb +0 -65
  55. data/spec/typhoeus/remote_spec.rb +0 -695
  56. data/spec/typhoeus/request_spec.rb +0 -387
  57. data/spec/typhoeus/response_spec.rb +0 -192
  58. data/spec/typhoeus/utils_spec.rb +0 -22
  59. data/typhoeus.gemspec +0 -33
@@ -1,602 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
- # some of these tests assume that you have some local services running.
4
- # ruby spec/servers/app.rb -p 3000
5
- # ruby spec/servers/app.rb -p 3001
6
- # ruby spec/servers/app.rb -p 3002
7
- describe Typhoeus::Hydra do
8
- before(:all) do
9
- cache_class = Class.new do
10
- def initialize
11
- @cache = {}
12
- end
13
- def get(key)
14
- @cache[key]
15
- end
16
- def set(key, object, timeout = 0)
17
- @cache[key] = object
18
- end
19
- end
20
- @cache = cache_class.new
21
- end
22
-
23
- it "has a singleton" do
24
- Typhoeus::Hydra.hydra.should be_a Typhoeus::Hydra
25
- end
26
-
27
- it "has a setter for the singleton" do
28
- Typhoeus::Hydra.hydra = :foo
29
- Typhoeus::Hydra.hydra.should == :foo
30
- Typhoeus::Hydra.hydra = Typhoeus::Hydra.new
31
- end
32
-
33
- it "queues a request" do
34
- hydra = Typhoeus::Hydra.new
35
- hydra.queue Typhoeus::Request.new("http://localhost:3000")
36
- end
37
-
38
- it "runs a batch of requests" do
39
- hydra = Typhoeus::Hydra.new
40
- first = Typhoeus::Request.new("http://localhost:3000/first")
41
- second = Typhoeus::Request.new("http://localhost:3001/second")
42
- hydra.queue first
43
- hydra.queue second
44
- hydra.run
45
- first.response.body.should include("first")
46
- second.response.body.should include("second")
47
- end
48
-
49
- it "runs queued requests in order of queuing" do
50
- hydra = Typhoeus::Hydra.new :max_concurrency => 1
51
- first = Typhoeus::Request.new("http://localhost:3000/first")
52
- second = Typhoeus::Request.new("http://localhost:3001/second")
53
- third = Typhoeus::Request.new("http://localhost:3001/third")
54
- second.on_complete do |response|
55
- first.response.should_not == nil
56
- third.response.should == nil
57
- end
58
- third.on_complete do |response|
59
- first.response.should_not == nil
60
- second.response.should_not == nil
61
- end
62
-
63
- hydra.queue first
64
- hydra.queue second
65
- hydra.queue third
66
- hydra.run
67
- first.response.body.should include("first")
68
- second.response.body.should include("second")
69
- third.response.body.should include("third")
70
- end
71
-
72
- it "should store the curl return codes on the reponses" do
73
- hydra = Typhoeus::Hydra.new
74
- first = Typhoeus::Request.new("http://localhost:3001/?delay=1", :timeout => 100)
75
- second = Typhoeus::Request.new("http://localhost:3999", :connect_timout => 100)
76
- hydra.queue first
77
- hydra.queue second
78
- hydra.run
79
- first.response.curl_return_code == 28
80
- second.response.curl_return_code == 7
81
- end
82
-
83
- it "aborts a batch of requests" do
84
- urls = [
85
- 'http://localhost:3000',
86
- 'http://localhost:3001',
87
- 'http://localhost:3002'
88
- ]
89
-
90
- # this will make testing easier
91
- hydra = Typhoeus::Hydra.new( :max_concurrency => 1 )
92
- completed = 0
93
-
94
- 10.times {
95
- |i|
96
-
97
- req = Typhoeus::Request.new( urls[ i % urls.size], :params => { :cnt => i } )
98
- req.on_complete {
99
- |res|
100
- completed += 1
101
- hydra.abort if completed == 5
102
- }
103
-
104
- hydra.queue( req )
105
- }
106
-
107
- hydra.run
108
-
109
- # technically this should be '== 6' but I don't trust it...
110
- completed.should < 10
111
- end
112
-
113
- it "has a cache_setter proc" do
114
- hydra = Typhoeus::Hydra.new
115
- hydra.cache_setter do |request|
116
- # @cache.set(request.cache_key, request.response, request.cache_timeout)
117
- end
118
- end
119
-
120
- it "has a cache_getter" do
121
- hydra = Typhoeus::Hydra.new
122
- hydra.cache_getter do |request|
123
- # @cache.get(request.cache_key) rescue nil
124
- end
125
- end
126
-
127
- it "memoizes GET reqeusts" do
128
- hydra = Typhoeus::Hydra.new
129
- first = Typhoeus::Request.new("http://localhost:3000/foo", :params => {:delay => 1})
130
- second = Typhoeus::Request.new("http://localhost:3000/foo", :params => {:delay => 1})
131
- hydra.queue first
132
- hydra.queue second
133
- start_time = Time.now
134
- hydra.run
135
- first.response.body.should include("foo")
136
- first.handled_response.body.should include("foo")
137
- first.response.should == second.response
138
- first.handled_response.should == second.handled_response
139
- (Time.now - start_time).should < 1.2 # if it had run twice it would be ~ 2 seconds
140
- end
141
-
142
- it "can turn off memoization for GET requests" do
143
- hydra = Typhoeus::Hydra.new
144
- hydra.disable_memoization
145
- first = Typhoeus::Request.new("http://localhost:3000/foo")
146
- second = Typhoeus::Request.new("http://localhost:3000/foo")
147
- hydra.queue first
148
- hydra.queue second
149
- hydra.run
150
- first.response.body.should include("foo")
151
- first.response.object_id.should_not == second.response.object_id
152
- end
153
-
154
- it "pulls GETs from cache" do
155
- hydra = Typhoeus::Hydra.new
156
- start_time = Time.now
157
- hydra.cache_getter do |request|
158
- @cache.get(request.cache_key) rescue nil
159
- end
160
- hydra.cache_setter do |request|
161
- @cache.set(request.cache_key, request.response, request.cache_timeout)
162
- end
163
-
164
- first = Typhoeus::Request.new("http://localhost:3000/foo", :params => {:delay => 1})
165
- @cache.set(first.cache_key, :foo, 60)
166
- hydra.queue first
167
- hydra.run
168
- (Time.now - start_time).should < 0.1
169
- first.response.should == :foo
170
- end
171
-
172
- it "sets GET responses to cache when the request has a cache_timeout value" do
173
- hydra = Typhoeus::Hydra.new
174
- hydra.cache_getter do |request|
175
- @cache.get(request.cache_key) rescue nil
176
- end
177
- hydra.cache_setter do |request|
178
- @cache.set(request.cache_key, request.response, request.cache_timeout)
179
- end
180
-
181
- first = Typhoeus::Request.new("http://localhost:3000/first", :cache_timeout => 0)
182
- second = Typhoeus::Request.new("http://localhost:3000/second")
183
- hydra.queue first
184
- hydra.queue second
185
- hydra.run
186
- first.response.body.should include("first")
187
- @cache.get(first.cache_key).should == first.response
188
- @cache.get(second.cache_key).should be_nil
189
- end
190
-
191
- it "continues queued requests after a queued cache hit" do
192
- # Set max_concurrency to 1 so that the second and third requests will end
193
- # up in the request queue.
194
- hydra = Typhoeus::Hydra.new :max_concurrency => 1
195
- hydra.cache_getter do |request|
196
- @cache.get(request.cache_key) rescue nil
197
- end
198
- hydra.cache_setter do |request|
199
- @cache.set(request.cache_key, request.response, request.cache_timeout)
200
- end
201
-
202
- first = Typhoeus::Request.new("http://localhost:3000/first", :params => {:delay => 1})
203
- second = Typhoeus::Request.new("http://localhost:3000/second", :params => {:delay => 1})
204
- third = Typhoeus::Request.new("http://localhost:3000/third", :params => {:delay => 1})
205
- @cache.set(second.cache_key, "second", 60)
206
- hydra.queue first
207
- hydra.queue second
208
- hydra.queue third
209
- hydra.run
210
-
211
- first.response.body.should include("first")
212
- second.response.should == "second"
213
- third.response.body.should include("third")
214
- end
215
-
216
- it "has a global on_complete" do
217
- foo = nil
218
- hydra = Typhoeus::Hydra.new
219
- hydra.on_complete do |response|
220
- foo = :called
221
- end
222
-
223
- first = Typhoeus::Request.new("http://localhost:3000/first")
224
- hydra.queue first
225
- hydra.run
226
- first.response.body.should include("first")
227
- foo.should == :called
228
- end
229
-
230
- it "has a global on_complete setter" do
231
- foo = nil
232
- hydra = Typhoeus::Hydra.new
233
- proc = Proc.new {|response| foo = :called}
234
- hydra.on_complete = proc
235
-
236
- first = Typhoeus::Request.new("http://localhost:3000/first")
237
- hydra.queue first
238
- hydra.run
239
- first.response.body.should include("first")
240
- foo.should == :called
241
- end
242
-
243
- it "should reuse connections from the pool for a host"
244
-
245
- it "should queue up requests while others are running" do
246
- hydra = Typhoeus::Hydra.new
247
-
248
- start_time = Time.now
249
- @responses = []
250
-
251
- request = Typhoeus::Request.new("http://localhost:3000/first", :params => {:delay => 1})
252
- request.on_complete do |response|
253
- @responses << response
254
- response.body.should include("first")
255
- end
256
-
257
- request.after_complete do |object|
258
- second_request = Typhoeus::Request.new("http://localhost:3001/second", :params => {:delay => 2})
259
- second_request.on_complete do |response|
260
- @responses << response
261
- response.body.should include("second")
262
- end
263
- hydra.queue second_request
264
- end
265
- hydra.queue request
266
-
267
- third_request = Typhoeus::Request.new("http://localhost:3002/third", :params => {:delay => 3})
268
- third_request.on_complete do |response|
269
- @responses << response
270
- response.body.should include("third")
271
- end
272
- hydra.queue third_request
273
-
274
- hydra.run
275
- @responses.size.should == 3
276
- (Time.now - start_time).should < 3.3
277
- end
278
-
279
- it "should fire and forget" do
280
- # this test is totally hacky. I have no clue how to make it verify. I just look at the test servers
281
- # to verify that stuff is running
282
- hydra = Typhoeus::Hydra.new
283
- first = Typhoeus::Request.new("http://localhost:3000/first?delay=1")
284
- second = Typhoeus::Request.new("http://localhost:3001/second?delay=2")
285
- hydra.queue first
286
- hydra.queue second
287
- hydra.fire_and_forget
288
- third = Typhoeus::Request.new("http://localhost:3002/third?delay=3")
289
- hydra.queue third
290
- hydra.fire_and_forget
291
- sleep 3 # have to do this or future tests may break.
292
- end
293
-
294
- it "should take the maximum number of concurrent requests as an argument" do
295
- hydra = Typhoeus::Hydra.new(:max_concurrency => 2)
296
- first = Typhoeus::Request.new("http://localhost:3000/first?delay=1")
297
- second = Typhoeus::Request.new("http://localhost:3001/second?delay=1")
298
- third = Typhoeus::Request.new("http://localhost:3002/third?delay=1")
299
- hydra.queue first
300
- hydra.queue second
301
- hydra.queue third
302
-
303
- start_time = Time.now
304
- hydra.run
305
- finish_time = Time.now
306
-
307
- first.response.code.should == 200
308
- second.response.code.should == 200
309
- third.response.code.should == 200
310
- (finish_time - start_time).should > 2.0
311
- end
312
-
313
- it "should respect the follow_location option when set on a request" do
314
- hydra = Typhoeus::Hydra.new
315
- request = Typhoeus::Request.new("http://localhost:3000/redirect", :follow_location => true)
316
- hydra.queue request
317
- hydra.run
318
-
319
- request.response.code.should == 200
320
- end
321
-
322
- it "should pass through the max_redirects option when set on a request" do
323
- hydra = Typhoeus::Hydra.new
324
- request = Typhoeus::Request.new("http://localhost:3000/bad_redirect", :max_redirects => 5)
325
- hydra.queue request
326
- hydra.run
327
-
328
- request.response.code.should == 302
329
- end
330
- end
331
-
332
- describe Typhoeus::Hydra::Stubbing do
333
- shared_examples_for "any stubbable target" do
334
- before(:each) do
335
- @on_complete_handler_called = nil
336
- @request = Typhoeus::Request.new("http://localhost:3000/foo",
337
- :headers => { 'user-agent' => 'test' })
338
- @request.on_complete do |response|
339
- @on_complete_handler_called = true
340
- response.code.should == 404
341
- response.headers.should == "whatever"
342
- end
343
- @response = Typhoeus::Response.new(:code => 404,
344
- :headers => "whatever",
345
- :body => "not found",
346
- :time => 0.1)
347
- end
348
-
349
- after(:each) do
350
- @stub_target.clear_stubs
351
- @stub_target.stub_finders.clear
352
- end
353
-
354
- it 'allows users to register a custom stub finder' do
355
- @stub_target.register_stub_finder do |request|
356
- Typhoeus::Response.new :code => 200, :body => "stub for #{request.url.split('/').last}"
357
- end
358
-
359
- request = Typhoeus::Request.new("http://localhost:3000/foo")
360
- returned_response = nil
361
- request.on_complete { |response| returned_response = response }
362
- @hydra.queue(request); @hydra.run
363
-
364
- returned_response.code.should == 200
365
- returned_response.body.should == "stub for foo"
366
- end
367
-
368
- it 'ignores the custom stub finder if it the block returns nil' do
369
- @stub_target.register_stub_finder { |r| }
370
-
371
- @stub_target.stub(:get, "http://localhost:3000/foo",
372
- :headers => { 'user-agent' => 'test'}).
373
- and_return(@response)
374
-
375
- @hydra.queue(@request)
376
- @hydra.run
377
- @on_complete_handler_called.should be_true
378
- @response.request.should == @request
379
- end
380
-
381
- it "should provide a stubs accessor" do
382
- begin
383
- @stub_target.stubs.should == []
384
- @stub_target.stubs = [:foo]
385
- ensure
386
- @stub_target.clear_stubs
387
- end
388
- end
389
-
390
- it "stubs requests to a specific URI" do
391
- @stub_target.stub(:get, "http://localhost:3000/foo",
392
- :headers => { 'user-agent' => 'test'}).
393
- and_return(@response)
394
-
395
- @hydra.queue(@request)
396
- @hydra.run
397
- @on_complete_handler_called.should be_true
398
- @response.request.should == @request
399
- end
400
-
401
- it "stubs requests to URIs matching a pattern" do
402
- @stub_target.stub(:get, /foo/,
403
- :headers => { 'user-agent' => 'test' }).
404
- and_return(@response)
405
- @hydra.queue(@request)
406
- @hydra.run
407
- @on_complete_handler_called.should be_true
408
- @response.request.should == @request
409
- end
410
-
411
- it "can clear stubs" do
412
- @stub_target.clear_stubs
413
- end
414
-
415
- it "clears out previously queued requests once they are called" do
416
- @stub_target.stub(:get, "http://localhost:3000/asdf",
417
- :headers => { 'user-agent' => 'test' }).
418
- and_return(@response)
419
-
420
- call_count = 0
421
- request = Typhoeus::Request.new("http://localhost:3000/asdf", :user_agent => 'test')
422
- request.on_complete do |response|
423
- call_count += 1
424
- end
425
- @hydra.queue(request)
426
- @hydra.run
427
- call_count.should == 1
428
- @hydra.run
429
- call_count.should == 1
430
- end
431
-
432
- it "calls stubs for requests that are queued up in the on_complete of a first stub" do
433
- @stub_target.stub(:get, "http://localhost:3000/asdf").and_return(@response)
434
- @stub_target.stub(:get, "http://localhost:3000/bar").and_return(@response)
435
-
436
- second_handler_called = false
437
- request = Typhoeus::Request.new("http://localhost:3000/asdf")
438
- request.on_complete do |response|
439
- r = Typhoeus::Request.new("http://localhost:3000/bar")
440
- r.on_complete do |res|
441
- second_handler_called = true
442
- end
443
- @hydra.queue(r)
444
- end
445
- @hydra.queue(request)
446
- @hydra.run
447
-
448
- second_handler_called.should be_true
449
- end
450
- end
451
-
452
- describe "global (class-level) stubbing" do
453
- before(:each) do
454
- @hydra = Typhoeus::Hydra.new
455
- @stub_target = Typhoeus::Hydra
456
- end
457
-
458
- it_should_behave_like "any stubbable target"
459
- end
460
-
461
- describe "instance stubbing" do
462
- before(:each) do
463
- @hydra = Typhoeus::Hydra.new
464
- @stub_target = @hydra
465
- end
466
-
467
- it_should_behave_like "any stubbable target"
468
- end
469
- end
470
-
471
- describe Typhoeus::Hydra::Callbacks do
472
- before(:all) do
473
- @klass = Typhoeus::Hydra
474
- end
475
-
476
- describe "#after_request_before_on_complete" do
477
- it "should provide a global hook after a request" do
478
- begin
479
- http_method = nil
480
- @klass.after_request_before_on_complete do |request|
481
- http_method = request.method
482
- end
483
-
484
- hydra = @klass.new
485
- request = Typhoeus::Request.new('http://localhost:3000',
486
- :method => :get)
487
- response = Typhoeus::Response.new(:code => 404,
488
- :headers => "whatever",
489
- :body => "not found",
490
- :time => 0.1)
491
- hydra.stub(:get, 'http://localhost:3000').
492
- and_return(response)
493
-
494
- hydra.queue(request)
495
- hydra.run
496
-
497
- http_method.should == :get
498
- ensure
499
- @klass.clear_global_hooks
500
- end
501
- end
502
- end
503
- end
504
-
505
- describe Typhoeus::Hydra::ConnectOptions do
506
- before(:all) do
507
- @klass = Typhoeus::Hydra
508
- end
509
-
510
- let!(:old_net_connect) { @klass.allow_net_connect }
511
- let!(:old_ignore_localhost) { @klass.ignore_localhost }
512
- let(:hydra) { @klass.new }
513
-
514
- after(:each) do
515
- @klass.allow_net_connect = old_net_connect
516
- @klass.ignore_localhost = old_ignore_localhost
517
- end
518
-
519
- def request_for(host)
520
- Typhoeus::Request.new("http://#{host}:3000")
521
- end
522
-
523
- describe "#ignore_localhost" do
524
- context "when set to true" do
525
- before(:each) { @klass.ignore_localhost = true }
526
-
527
- [true, false].each do |val|
528
- it "allows localhost requests when allow_net_connect is #{val}" do
529
- @klass.allow_net_connect = val
530
- expect { hydra.queue(request_for('localhost')) }.to_not raise_error
531
- end
532
- end
533
- end
534
-
535
- context "when set to false" do
536
- before(:each) { @klass.ignore_localhost = false }
537
-
538
- it "allows localhost requests when allow_net_connect is true" do
539
- @klass.allow_net_connect = true
540
- expect { hydra.queue(request_for('localhost')) }.to_not raise_error
541
- end
542
-
543
- it "does not allow localhost requests when allow_net_connect is false" do
544
- @klass.allow_net_connect = false
545
- expect { hydra.queue(request_for('localhost')) }.to raise_error(Typhoeus::Hydra::NetConnectNotAllowedError)
546
- end
547
- end
548
- end
549
-
550
- describe "#ignore_hosts" do
551
- context 'when allow_net_connect is set to false' do
552
- before(:each) do
553
- @klass.ignore_localhost = false
554
- @klass.allow_net_connect = false
555
- end
556
-
557
- Typhoeus::Request::LOCALHOST_ALIASES.each do |disallowed_host|
558
- ignore_hosts = Typhoeus::Request::LOCALHOST_ALIASES - [disallowed_host]
559
-
560
- context "when set to #{ignore_hosts.join(' and ')}" do
561
- before(:each) { @klass.ignore_hosts = ignore_hosts }
562
-
563
- it "does not allow a request to #{disallowed_host}" do
564
- expect { hydra.queue(request_for(disallowed_host)) }.to raise_error(Typhoeus::Hydra::NetConnectNotAllowedError)
565
- end
566
-
567
- ignore_hosts.each do |host|
568
- it "allows a request to #{host}" do
569
- expect { hydra.queue(request_for(host)) }.to_not raise_error
570
- end
571
- end
572
- end
573
- end
574
- end
575
- end
576
-
577
- describe "#allow_net_connect" do
578
- it "should be settable" do
579
- @klass.allow_net_connect = true
580
- @klass.allow_net_connect.should be_true
581
- end
582
-
583
- it "should default to true" do
584
- @klass.allow_net_connect.should be_true
585
- end
586
-
587
- it "should raise an error if we queue a request while its false" do
588
- @klass.allow_net_connect = false
589
- @klass.ignore_localhost = false
590
-
591
- expect {
592
- hydra.queue(request_for('example.com'))
593
- }.to raise_error(Typhoeus::Hydra::NetConnectNotAllowedError)
594
- end
595
- end
596
-
597
- describe "#allow_net_connect?" do
598
- it "should return true by default" do
599
- @klass.allow_net_connect?.should be_true
600
- end
601
- end
602
- end