vcr 4.0.0 → 6.1.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.
@@ -2,137 +2,121 @@ require 'vcr/util/version_checker'
2
2
  require 'vcr/request_handler'
3
3
  require 'typhoeus'
4
4
 
5
- if Float(Typhoeus::VERSION[/^\d+\.\d+/]) < 0.5
6
- require 'vcr/library_hooks/typhoeus_0.4'
7
- else
8
- VCR::VersionChecker.new('Typhoeus', Typhoeus::VERSION, '0.5.0').check_version!
9
-
10
- module VCR
11
- class LibraryHooks
5
+ module VCR
6
+ class LibraryHooks
7
+ # @private
8
+ module Typhoeus
12
9
  # @private
13
- module Typhoeus
14
- # @private
15
- class RequestHandler < ::VCR::RequestHandler
16
- attr_reader :request
17
- def initialize(request)
18
- @request = request
19
- request.block_connection = false if VCR.turned_on?
20
- end
21
-
22
- def vcr_request
23
- @vcr_request ||= VCR::Request.new \
24
- request.options.fetch(:method, :get),
25
- request.url,
26
- request_body,
27
- request.options.fetch(:headers, {})
28
- end
29
-
30
- private
10
+ class RequestHandler < ::VCR::RequestHandler
11
+ attr_reader :request
12
+ def initialize(request)
13
+ @request = request
14
+ request.block_connection = false if VCR.turned_on?
15
+ end
31
16
 
32
- def externally_stubbed?
33
- ::Typhoeus::Expectation.find_by(request)
34
- end
17
+ def vcr_request
18
+ @vcr_request ||= VCR::Request.new \
19
+ request.options.fetch(:method, :get),
20
+ request.url,
21
+ request.encoded_body,
22
+ request.options.fetch(:headers, {})
23
+ end
35
24
 
36
- def set_typed_request_for_after_hook(*args)
37
- super
38
- request.instance_variable_set(:@__typed_vcr_request, @after_hook_typed_request)
39
- end
25
+ private
40
26
 
41
- def on_unhandled_request
42
- invoke_after_request_hook(nil)
43
- super
44
- end
27
+ def externally_stubbed?
28
+ ::Typhoeus::Expectation.find_by(request)
29
+ end
45
30
 
46
- def on_stubbed_by_vcr_request
47
- response = ::Typhoeus::Response.new \
48
- :http_version => stubbed_response.http_version,
49
- :code => stubbed_response.status.code,
50
- :status_message => stubbed_response.status.message,
51
- :headers => stubbed_response_headers,
52
- :body => stubbed_response.body,
53
- :effective_url => stubbed_response.adapter_metadata.fetch('effective_url', request.url),
54
- :mock => true
55
-
56
- first_header_line = "HTTP/#{stubbed_response.http_version} #{response.code} #{response.status_message}\r\n"
57
- response.instance_variable_set(:@first_header_line, first_header_line)
58
- response.instance_variable_get(:@options)[:response_headers] =
59
- first_header_line + response.headers.map { |k,v| "#{k}: #{v}"}.join("\r\n")
60
-
61
- response
62
- end
31
+ def set_typed_request_for_after_hook(*args)
32
+ super
33
+ request.instance_variable_set(:@__typed_vcr_request, @after_hook_typed_request)
34
+ end
63
35
 
64
- def stubbed_response_headers
65
- @stubbed_response_headers ||= {}.tap do |hash|
66
- stubbed_response.headers.each do |key, values|
67
- hash[key] = values.size == 1 ? values.first : values
68
- end if stubbed_response.headers
69
- end
70
- end
36
+ def on_unhandled_request
37
+ invoke_after_request_hook(nil)
38
+ super
39
+ end
71
40
 
72
- if ::Typhoeus::Request.method_defined?(:encoded_body)
73
- def request_body
74
- request.encoded_body
75
- end
76
- else
77
- def request_body
78
- request.options.fetch(:body, "")
79
- end
80
- end
41
+ def on_stubbed_by_vcr_request
42
+ response = ::Typhoeus::Response.new \
43
+ :http_version => stubbed_response.http_version,
44
+ :code => stubbed_response.status.code,
45
+ :status_message => stubbed_response.status.message,
46
+ :headers => stubbed_response_headers,
47
+ :body => stubbed_response.body,
48
+ :effective_url => stubbed_response.adapter_metadata.fetch('effective_url', request.url),
49
+ :mock => true
50
+
51
+ first_header_line = "HTTP/#{stubbed_response.http_version} #{response.code} #{response.status_message}\r\n"
52
+ response.instance_variable_set(:@first_header_line, first_header_line)
53
+ response.instance_variable_get(:@options)[:response_headers] =
54
+ first_header_line + response.headers.map { |k,v| "#{k}: #{v}"}.join("\r\n")
55
+
56
+ response
81
57
  end
82
58
 
83
- # @private
84
- class << self
85
- def vcr_response_from(response)
86
- VCR::Response.new \
87
- VCR::ResponseStatus.new(response.code, response.status_message),
88
- response.headers,
89
- response.body,
90
- response.http_version,
91
- { "effective_url" => response.effective_url }
59
+ def stubbed_response_headers
60
+ @stubbed_response_headers ||= {}.tap do |hash|
61
+ stubbed_response.headers.each do |key, values|
62
+ hash[key] = values.size == 1 ? values.first : values
63
+ end if stubbed_response.headers
92
64
  end
65
+ end
66
+ end
93
67
 
94
- def collect_chunks(request)
95
- chunks = ''
96
- request.on_body.unshift(
97
- Proc.new do |body, response|
98
- chunks += body
99
- request.instance_variable_set(:@chunked_body, chunks)
100
- end
101
- )
102
- end
68
+ # @private
69
+ class << self
70
+ def vcr_response_from(response)
71
+ VCR::Response.new \
72
+ VCR::ResponseStatus.new(response.code, response.status_message),
73
+ response.headers,
74
+ response.body,
75
+ response.http_version,
76
+ { "effective_url" => response.effective_url }
77
+ end
103
78
 
104
- def restore_body_from_chunks(response, request)
105
- response.options[:response_body] = request.instance_variable_get(:@chunked_body)
106
- end
79
+ def collect_chunks(request)
80
+ chunks = ''
81
+ request.on_body.unshift(
82
+ Proc.new do |body, response|
83
+ chunks += body
84
+ request.instance_variable_set(:@chunked_body, chunks)
85
+ end
86
+ )
107
87
  end
108
88
 
109
- ::Typhoeus.on_complete do |response|
110
- request = response.request
89
+ def restore_body_from_chunks(response, request)
90
+ response.options[:response_body] = request.instance_variable_get(:@chunked_body)
91
+ end
92
+ end
111
93
 
112
- restore_body_from_chunks(response, request) if request.streaming?
94
+ ::Typhoeus.on_complete do |response|
95
+ request = response.request
113
96
 
114
- unless VCR.library_hooks.disabled?(:typhoeus)
115
- vcr_response = vcr_response_from(response)
116
- typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
97
+ restore_body_from_chunks(response, request) if request.streaming?
117
98
 
118
- unless request.response.mock
119
- http_interaction = VCR::HTTPInteraction.new(typed_vcr_request, vcr_response)
120
- VCR.record_http_interaction(http_interaction)
121
- end
99
+ unless VCR.library_hooks.disabled?(:typhoeus)
100
+ vcr_response = vcr_response_from(response)
101
+ typed_vcr_request = request.send(:remove_instance_variable, :@__typed_vcr_request)
122
102
 
123
- VCR.configuration.invoke_hook(:after_http_request, typed_vcr_request, vcr_response)
103
+ unless request.response.mock
104
+ http_interaction = VCR::HTTPInteraction.new(typed_vcr_request, vcr_response)
105
+ VCR.record_http_interaction(http_interaction)
124
106
  end
107
+
108
+ VCR.configuration.invoke_hook(:after_http_request, typed_vcr_request, vcr_response)
125
109
  end
110
+ end
126
111
 
127
- ::Typhoeus.before do |request|
128
- collect_chunks(request) if request.streaming?
129
- if response = VCR::LibraryHooks::Typhoeus::RequestHandler.new(request).handle
130
- request.on_headers.each { |cb| cb.call(response) }
131
- request.on_body.each { |cb| cb.call(response.body, response) }
132
- request.finish(response)
133
- else
134
- true
135
- end
112
+ ::Typhoeus.before do |request|
113
+ collect_chunks(request) if request.streaming?
114
+ if response = VCR::LibraryHooks::Typhoeus::RequestHandler.new(request).handle
115
+ request.on_headers.each { |cb| cb.call(response) }
116
+ request.on_body.each { |cb| cb.call(response.body, response) }
117
+ request.finish(response)
118
+ else
119
+ true
136
120
  end
137
121
  end
138
122
  end
@@ -146,4 +130,3 @@ VCR.configuration.after_library_hooks_loaded do
146
130
  WebMock::HttpLibAdapters::TyphoeusAdapter.disable!
147
131
  end
148
132
  end
149
-
@@ -12,8 +12,6 @@ module VCR
12
12
  module WebMock
13
13
  extend self
14
14
 
15
- @global_hook_disabled_requests = {}
16
-
17
15
  def with_global_hook_disabled(request)
18
16
  global_hook_disabled_requests << request
19
17
 
@@ -25,19 +23,12 @@ module VCR
25
23
  end
26
24
 
27
25
  def global_hook_disabled?(request)
28
- requests = @global_hook_disabled_requests[Thread.current.object_id]
26
+ requests = Thread.current[:_vcr_webmock_disabled_requests]
29
27
  requests && requests.include?(request)
30
28
  end
31
29
 
32
30
  def global_hook_disabled_requests
33
- requests = @global_hook_disabled_requests[Thread.current.object_id]
34
- return requests if requests
35
-
36
- ObjectSpace.define_finalizer(Thread.current, lambda {
37
- @global_hook_disabled_requests.delete(Thread.current.object_id)
38
- })
39
-
40
- @global_hook_disabled_requests[Thread.current.object_id] = []
31
+ Thread.current[:_vcr_webmock_disabled_requests] ||= []
41
32
  end
42
33
 
43
34
  # @private
@@ -9,8 +9,8 @@ module VCR
9
9
  include Enumerable
10
10
 
11
11
  # Creates a new list of context-owned cassettes and linked cassettes
12
- # @param [Array] context-owned cassettes
13
- # @param [Array] context-unowned (linked) cassettes
12
+ # @param cassettes [Array] context-owned cassettes
13
+ # @param linked_cassettes [Array] context-unowned (linked) cassettes
14
14
  def initialize(cassettes, linked_cassettes)
15
15
  @cassettes = cassettes
16
16
  @linked_cassettes = linked_cassettes
@@ -52,8 +52,8 @@ module VCR
52
52
  end
53
53
 
54
54
  # Create a new CassetteList
55
- # @param [Array] context-owned cassettes
56
- # @param [Array] context-unowned (linked) cassettes
55
+ # @param cassettes [Array] context-owned cassettes
56
+ # @param linked_cassettes [Array] context-unowned (linked) cassettes
57
57
  def self.list(cassettes, linked_cassettes)
58
58
  CassetteList.new(cassettes, linked_cassettes)
59
59
  end
@@ -74,7 +74,7 @@ module VCR
74
74
  def after_request(response)
75
75
  vcr_response = vcr_response_for(response)
76
76
 
77
- if should_record?
77
+ if vcr_response && should_record?
78
78
  VCR.record_http_interaction(VCR::HTTPInteraction.new(vcr_request, vcr_response))
79
79
  end
80
80
 
@@ -31,6 +31,11 @@ module VCR
31
31
  RequestHandler.new(@app, env).handle
32
32
  end
33
33
 
34
+ # Close any persistent connections.
35
+ def close
36
+ @app.close if @app.respond_to?(:close)
37
+ end
38
+
34
39
  # @private
35
40
  class RequestHandler < ::VCR::RequestHandler
36
41
  attr_reader :app, :env
@@ -25,10 +25,18 @@ module VCR
25
25
  end
26
26
  end
27
27
 
28
+ def localhost_ignored?
29
+ (LOCALHOST_ALIASES & ignore_hosts.to_a).any?
30
+ end
31
+
28
32
  def ignore_hosts(*hosts)
29
33
  ignored_hosts.merge(hosts)
30
34
  end
31
35
 
36
+ def unignore_hosts(*hosts)
37
+ ignored_hosts.subtract(hosts)
38
+ end
39
+
32
40
  def ignore?(request)
33
41
  invoke_hook(:ignore_request, request).any?
34
42
  end
@@ -40,4 +48,3 @@ module VCR
40
48
  end
41
49
  end
42
50
  end
43
-
@@ -110,12 +110,12 @@ module VCR
110
110
 
111
111
  def register_built_ins
112
112
  register(:method) { |r1, r2| r1.method == r2.method }
113
- register(:uri) { |r1, r2| r1.uri == r2.uri }
113
+ register(:uri) { |r1, r2| r1.parsed_uri == r2.parsed_uri }
114
114
  register(:body) { |r1, r2| r1.body == r2.body }
115
115
  register(:headers) { |r1, r2| r1.headers == r2.headers }
116
116
 
117
117
  register(:host) do |r1, r2|
118
- r1.parsed_uri.host == r2.parsed_uri.host
118
+ r1.parsed_uri.host.chomp('.') == r2.parsed_uri.host.chomp('.')
119
119
  end
120
120
  register(:path) do |r1, r2|
121
121
  r1.parsed_uri.path == r2.parsed_uri.path
@@ -138,7 +138,7 @@ module VCR
138
138
 
139
139
  register(:body_as_json) do |r1, r2|
140
140
  begin
141
- JSON.parse(r1.body) == JSON.parse(r2.body)
141
+ r1.body == r2.body || JSON.parse(r1.body) == JSON.parse(r2.body)
142
142
  rescue JSON::ParserError
143
143
  false
144
144
  end
data/lib/vcr/structs.rb CHANGED
@@ -62,7 +62,7 @@ module VCR
62
62
  super
63
63
 
64
64
  if body && !body.is_a?(String)
65
- raise ArgumentError, "#{self.class} initialized with an invalid body: #{body.inspect}."
65
+ raise ArgumentError, "#{self.class} initialized with an invalid (non-String) body of class #{body.class}: #{body.inspect}."
66
66
  end
67
67
 
68
68
  # Ensure that the body is a raw string, in case the string instance
@@ -167,25 +167,6 @@ module VCR
167
167
  end
168
168
  end
169
169
 
170
- # @private
171
- module OrderedHashSerializer
172
- def each
173
- @ordered_keys.each do |key|
174
- yield key, self[key] if has_key?(key)
175
- end
176
- end
177
-
178
- if RUBY_VERSION.to_f > 1.8
179
- # 1.9+ hashes are already ordered.
180
- def self.apply_to(*args); end
181
- else
182
- def self.apply_to(hash, keys)
183
- hash.instance_variable_set(:@ordered_keys, keys)
184
- hash.extend self
185
- end
186
- end
187
- end
188
-
189
170
  # The request of an {HTTPInteraction}.
190
171
  #
191
172
  # @attr [Symbol] method the HTTP method (i.e. :head, :options, :get, :post, :put, :patch or :delete)
@@ -219,7 +200,7 @@ module VCR
219
200
  'uri' => uri,
220
201
  'body' => serializable_body,
221
202
  'headers' => headers
222
- }.tap { |h| OrderedHashSerializer.apply_to(h, members) }
203
+ }
223
204
  end
224
205
 
225
206
  # Constructs a new instance from a hash.
@@ -365,11 +346,10 @@ module VCR
365
346
  {
366
347
  'status' => status.to_hash,
367
348
  'headers' => headers,
368
- 'body' => serializable_body,
369
- 'http_version' => http_version
349
+ 'body' => serializable_body
370
350
  }.tap do |hash|
351
+ hash['http_version'] = http_version if http_version
371
352
  hash['adapter_metadata'] = adapter_metadata unless adapter_metadata.empty?
372
- OrderedHashSerializer.apply_to(hash, members)
373
353
  end
374
354
  end
375
355
 
@@ -403,6 +383,11 @@ module VCR
403
383
  %w[ gzip deflate ].include? content_encoding
404
384
  end
405
385
 
386
+ # Checks if VCR decompressed the response body
387
+ def vcr_decompressed?
388
+ adapter_metadata['vcr_decompressed']
389
+ end
390
+
406
391
  # Decodes the compressed body and deletes evidence that it was ever compressed.
407
392
  #
408
393
  # @return self
@@ -412,11 +397,43 @@ module VCR
412
397
  self.class.decompress(body, content_encoding) { |new_body|
413
398
  self.body = new_body
414
399
  update_content_length_header
400
+ adapter_metadata['vcr_decompressed'] = content_encoding
415
401
  delete_header('Content-Encoding')
416
402
  }
417
403
  return self
418
404
  end
419
405
 
406
+ # Recompresses the decompressed body according to adapter metadata.
407
+ #
408
+ # @raise [VCR::Errors::UnknownContentEncodingError] if the content encoding
409
+ # stored in the adapter metadata is unknown
410
+ def recompress
411
+ type = adapter_metadata['vcr_decompressed']
412
+ new_body = begin
413
+ case type
414
+ when 'gzip'
415
+ body_str = ''
416
+ args = [StringIO.new(body_str)]
417
+ args << { :encoding => 'ASCII-8BIT' } if ''.respond_to?(:encoding)
418
+ writer = Zlib::GzipWriter.new(*args)
419
+ writer.write(body)
420
+ writer.close
421
+ body_str
422
+ when 'deflate'
423
+ Zlib::Deflate.inflate(body)
424
+ when 'identity', NilClass
425
+ nil
426
+ else
427
+ raise Errors::UnknownContentEncodingError, "unknown content encoding: #{type}"
428
+ end
429
+ end
430
+ if new_body
431
+ self.body = new_body
432
+ update_content_length_header
433
+ headers['Content-Encoding'] = type
434
+ end
435
+ end
436
+
420
437
  begin
421
438
  require 'zlib'
422
439
  require 'stringio'
@@ -437,9 +454,10 @@ module VCR
437
454
 
438
455
  case type
439
456
  when 'gzip'
440
- args = [StringIO.new(body)]
441
- args << { :encoding => 'ASCII-8BIT' } if ''.respond_to?(:encoding)
442
- yield Zlib::GzipReader.new(*args).read
457
+ gzip_reader_options = {}
458
+ gzip_reader_options[:encoding] = 'ASCII-8BIT' if ''.respond_to?(:encoding)
459
+ yield Zlib::GzipReader.new(StringIO.new(body),
460
+ **gzip_reader_options).read
443
461
  when 'deflate'
444
462
  yield Zlib::Inflate.inflate(body)
445
463
  when 'identity', NilClass
@@ -463,7 +481,7 @@ module VCR
463
481
  def to_hash
464
482
  {
465
483
  'code' => code, 'message' => message
466
- }.tap { |h| OrderedHashSerializer.apply_to(h, members) }
484
+ }
467
485
  end
468
486
 
469
487
  # Constructs a new instance from a hash.
@@ -496,9 +514,7 @@ module VCR
496
514
  'request' => request.to_hash,
497
515
  'response' => response.to_hash,
498
516
  'recorded_at' => recorded_at.httpdate
499
- }.tap do |hash|
500
- OrderedHashSerializer.apply_to(hash, members)
501
- end
517
+ }
502
518
  end
503
519
 
504
520
  # Constructs a new instance from a hash.
@@ -23,10 +23,10 @@ module VCR
23
23
  # Adds `Before` and `After` cucumber hooks for the named tags that
24
24
  # will cause a VCR cassette to be used for scenarios with matching tags.
25
25
  #
26
- # @param [Array<String>] tag_names the cucumber scenario tags
27
- # @param [(optional) Hash] options the cassette options. Specify
28
- # `:use_scenario_name => true` to automatically name the
29
- # cassette according to the scenario name.
26
+ # @param tag_names [Array<String,Hash>] the cucumber scenario tags. If
27
+ # the last argument is a hash it is treated as cassette options.
28
+ # - `:use_scenario_name => true` to automatically name the
29
+ # cassette according to the scenario name.
30
30
  def tags(*tag_names)
31
31
  original_options = tag_names.last.is_a?(::Hash) ? tag_names.pop : {}
32
32
  tag_names.each do |tag_name|
@@ -47,10 +47,21 @@ module VCR
47
47
  scenario.scenario_outline.name,
48
48
  scenario.name.split("\n").first
49
49
  ].join("/")
50
- else
50
+ elsif scenario.respond_to?(:feature)
51
51
  [ scenario.feature.name.split("\n").first,
52
52
  scenario.name.split("\n").first
53
53
  ].join("/")
54
+ elsif scenario.location.lines.min == scenario.location.lines.max
55
+ # test case from a regular scenario in cucumber version 4
56
+ [ scenario.location.file.split("/").last.split(".").first,
57
+ scenario.name.split("\n").first
58
+ ].join("/")
59
+ else
60
+ # test case from a scenario with examples ("scenario outline") in cucumber version 4
61
+ [ scenario.location.file.split("/").last.split(".").first,
62
+ scenario.name.split("\n").first,
63
+ "Example at line #{scenario.location.lines.max}"
64
+ ].join("/")
54
65
  end
55
66
  else
56
67
  "cucumber_tags/#{tag_name.gsub(/\A@/, '')}"
@@ -5,38 +5,50 @@ module VCR
5
5
  module Metadata
6
6
  extend self
7
7
 
8
+ def vcr_cassette_name_for(metadata)
9
+ description =
10
+ if metadata[:description].empty?
11
+ # we have an "it { is_expected.to be something }" block
12
+ metadata[:scoped_id]
13
+ else
14
+ metadata[:description]
15
+ end
16
+ example_group =
17
+ if metadata.key?(:example_group)
18
+ metadata[:example_group]
19
+ else
20
+ metadata[:parent_example_group]
21
+ end
22
+
23
+ if example_group
24
+ [vcr_cassette_name_for(example_group), description].join('/')
25
+ else
26
+ description
27
+ end
28
+ end
29
+
8
30
  def configure!
9
31
  ::RSpec.configure do |config|
10
- vcr_cassette_name_for = lambda do |metadata|
11
- description = if metadata[:description].empty?
12
- # we have an "it { is_expected.to be something }" block
13
- metadata[:scoped_id]
14
- else
15
- metadata[:description]
16
- end
17
- example_group = if metadata.key?(:example_group)
18
- metadata[:example_group]
19
- else
20
- metadata[:parent_example_group]
21
- end
22
-
23
- if example_group
24
- [vcr_cassette_name_for[example_group], description].join('/')
25
- else
26
- description
27
- end
28
- end
29
32
 
30
33
  when_tagged_with_vcr = { :vcr => lambda { |v| !!v } }
31
34
 
32
35
  config.before(:each, when_tagged_with_vcr) do |ex|
33
36
  example = ex.respond_to?(:metadata) ? ex : ex.example
34
37
 
38
+ cassette_name = nil
35
39
  options = example.metadata[:vcr]
36
- options = options.is_a?(Hash) ? options.dup : {} # in case it's just :vcr => true
40
+ options = case options
41
+ when Hash #=> vcr: { cassette_name: 'foo' }
42
+ options.dup
43
+ when String #=> vcr: 'bar'
44
+ cassette_name = options.dup
45
+ {}
46
+ else #=> :vcr or vcr: true
47
+ {}
48
+ end
37
49
 
38
- cassette_name = options.delete(:cassette_name) ||
39
- vcr_cassette_name_for[example.metadata]
50
+ cassette_name ||= options.delete(:cassette_name) ||
51
+ VCR::RSpec::Metadata.vcr_cassette_name_for(example.metadata)
40
52
  VCR.insert_cassette(cassette_name, options)
41
53
  end
42
54
 
@@ -1,31 +1,25 @@
1
1
  module VCR
2
2
  # Ruby 1.8 provides Ping.pingecho, but it was removed in 1.9.
3
- # So we try requiring it, and if that fails, define it ourselves.
4
- begin
5
- require 'ping'
6
- Ping = ::Ping
7
- rescue LoadError
8
- # This is copied, verbatim, from Ruby 1.8.7's ping.rb.
9
- require 'timeout'
10
- require "socket"
3
+ # This is copied, verbatim, from Ruby 1.8.7's ping.rb.
4
+ require 'timeout'
5
+ require "socket"
11
6
 
12
- # @private
13
- module Ping
14
- def pingecho(host, timeout=5, service="echo")
15
- begin
16
- Timeout.timeout(timeout) do
17
- s = TCPSocket.new(host, service)
18
- s.close
19
- end
20
- rescue Errno::ECONNREFUSED
21
- return true
22
- rescue Timeout::Error, StandardError
23
- return false
7
+ # @private
8
+ module Ping
9
+ def pingecho(host, timeout=5, service="echo")
10
+ begin
11
+ Timeout.timeout(timeout) do
12
+ s = TCPSocket.new(host, service)
13
+ s.close
24
14
  end
15
+ rescue Errno::ECONNREFUSED
25
16
  return true
17
+ rescue Timeout::Error, StandardError
18
+ return false
26
19
  end
27
- module_function :pingecho
20
+ return true
28
21
  end
22
+ module_function :pingecho
29
23
  end
30
24
 
31
25
  # @private