net-ping 2.0.9 → 2.1.1
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.
- checksums.yaml +4 -4
- data/CHANGES +22 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +3 -1
- data/Rakefile +93 -8
- data/lib/net/ping/external.rb +4 -2
- data/lib/net/ping/ping.rb +2 -3
- data/lib/net/ping/version.rb +6 -0
- data/net-ping-universal-linux.gemspec +4 -0
- data/net-ping-universal-mingw-ucrt.gemspec +7 -0
- data/net-ping.gemspec +6 -15
- data/test/test_net_ping.rb +2 -1
- data/test/test_net_ping_external.rb +59 -0
- data/test/test_net_ping_gem_packaging.rb +343 -0
- data/test/test_net_ping_http.rb +2 -3
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 12d4bcbcdb97fb3b116be13a5bc7ad632b4efc116127d9b5859531b5605be3ae
|
|
4
|
+
data.tar.gz: 22603f15d676ac4e3a4137a0bdec76019b7a52b8ae5ca028b452b8760ad6bd15
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ab74625d886822f7801e5c9c6e7704664bb789f745b47a29ec54cf8e7baa4cbb1a86c332df8bc16a4757900987dc3389642c290cf4d38d98badbc1e60df7ffa1
|
|
7
|
+
data.tar.gz: bb55d09ac91ec4ac1e407e7050f655d7fd305f3fcab3fa2093613745509724d138b25b22282d2d00d63eb5880d50814d7bfe0ac4d9e414904fbeb2d0e2618ec5
|
data/CHANGES
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
== 2.1.1 - 16-Aug-2026
|
|
2
|
+
* Fix the license format in net-ping.gemspec to use the SPDX identifier
|
|
3
|
+
"Artistic-2.0" [#47](https://github.com/eitoball/net-ping/pull/47).
|
|
4
|
+
* Exclude CLAUDE.md and docs/ from the packaged gem files
|
|
5
|
+
[#48](https://github.com/eitoball/net-ping/pull/48).
|
|
6
|
+
|
|
7
|
+
== 2.1.0 - 08-Aug-2026
|
|
8
|
+
* Publish platform-specific gem metadata so Linux installs cap2 and current
|
|
9
|
+
Windows RubyInstaller installs win32-security for ICMP support
|
|
10
|
+
[#44](https://github.com/eitoball/net-ping/pull/44).
|
|
11
|
+
* Fix the FreeBSD ping6 timeout option
|
|
12
|
+
[#43](https://github.com/eitoball/net-ping/pull/43).
|
|
13
|
+
* Add Ruby 4.0 to the test matrix and add win32ole as an explicit Windows
|
|
14
|
+
dependency, since it is no longer a default gem as of Ruby 4.0
|
|
15
|
+
[#41](https://github.com/eitoball/net-ping/pull/41).
|
|
16
|
+
* Move Net::Ping::VERSION into its own file so the gemspec version can no
|
|
17
|
+
longer drift out of sync with it
|
|
18
|
+
[#37](https://github.com/eitoball/net-ping/pull/37).
|
|
19
|
+
* Fix `Net::Ping::External#ping6` setting a spurious "undefined method '=~'
|
|
20
|
+
for false" exception on success
|
|
21
|
+
[#39](https://github.com/eitoball/net-ping/pull/39).
|
|
22
|
+
|
|
1
23
|
== 2.0.9 - 25-Jul-2026
|
|
2
24
|
* Add GitHub Actions CI [#33](https://github.com/eitoball/net-ping/pull/33)
|
|
3
25
|
and update its supported Ruby versions [#38](https://github.com/eitoball/net-ping/pull/38).
|
data/Gemfile
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
gemspec
|
|
3
|
+
gem 'win32-security', '>= 0.2.0' if Gem.win_platform?
|
|
4
|
+
|
|
5
|
+
# No longer a default gem as of Ruby 4.0. Used by the WMI ping class.
|
|
6
|
+
gem 'win32ole', '>= 1.8.8' if Gem.win_platform?
|
|
7
|
+
|
|
8
|
+
gem 'cap2', '>= 0.2.2' if RUBY_PLATFORM =~ /linux/i
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -3,7 +3,9 @@ A collection of classes that provide different ways to ping computers.
|
|
|
3
3
|
|
|
4
4
|
## Prerequisites
|
|
5
5
|
* ffi
|
|
6
|
-
* win32-security (
|
|
6
|
+
* win32-security (installed from the Windows gem artifact)
|
|
7
|
+
* win32ole (installed from the Windows gem artifact)
|
|
8
|
+
* cap2 (installed from the Linux gem artifact)
|
|
7
9
|
* webmock (test only)
|
|
8
10
|
* test-unit (test only)
|
|
9
11
|
|
data/Rakefile
CHANGED
|
@@ -5,25 +5,110 @@ include Object.const_defined?(:RbConfig) ? RbConfig : Config
|
|
|
5
5
|
|
|
6
6
|
CLEAN.include("**/*.gem", "**/*.rbc")
|
|
7
7
|
|
|
8
|
+
GEMSPEC_FILES = %w[
|
|
9
|
+
net-ping.gemspec
|
|
10
|
+
net-ping-universal-linux.gemspec
|
|
11
|
+
net-ping-universal-mingw-ucrt.gemspec
|
|
12
|
+
].freeze
|
|
13
|
+
|
|
14
|
+
EXPECTED_GEM_METADATA = {
|
|
15
|
+
'net-ping.gemspec' => ['ruby', {}],
|
|
16
|
+
'net-ping-universal-linux.gemspec' => ['universal-linux', {'cap2' => '>= 0.2.2'}],
|
|
17
|
+
'net-ping-universal-mingw-ucrt.gemspec' => [
|
|
18
|
+
'universal-mingw-ucrt',
|
|
19
|
+
{'win32-security' => '>= 0.2.0', 'win32ole' => '>= 1.8.8'}
|
|
20
|
+
]
|
|
21
|
+
}.freeze
|
|
22
|
+
|
|
23
|
+
def load_gem_specifications
|
|
24
|
+
GEMSPEC_FILES.map do |path|
|
|
25
|
+
spec = Gem::Specification.load(path)
|
|
26
|
+
abort("Unable to load #{path}") unless spec
|
|
27
|
+
spec
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def with_unbundled_env
|
|
32
|
+
if defined?(Bundler) && Bundler.respond_to?(:with_unbundled_env)
|
|
33
|
+
Bundler.with_unbundled_env { yield }
|
|
34
|
+
elsif defined?(Bundler) && Bundler.respond_to?(:with_clean_env)
|
|
35
|
+
Bundler.with_clean_env { yield }
|
|
36
|
+
else
|
|
37
|
+
yield
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def platform_round_trips?(platform_string)
|
|
42
|
+
Gem::Platform.new(platform_string).to_s == platform_string
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def platform_installable?(spec)
|
|
46
|
+
if Gem::Platform.respond_to?(:installable?)
|
|
47
|
+
Gem::Platform.installable?(spec)
|
|
48
|
+
else
|
|
49
|
+
Gem::Platform.match(spec.platform)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def select_install_specification(specifications = load_gem_specifications)
|
|
54
|
+
specific = specifications.find do |spec|
|
|
55
|
+
spec.platform != Gem::Platform::RUBY && platform_installable?(spec)
|
|
56
|
+
end
|
|
57
|
+
spec = specific || specifications.find { |item| item.platform == Gem::Platform::RUBY }
|
|
58
|
+
abort('Unable to find a Ruby fallback gem specification') unless spec
|
|
59
|
+
spec
|
|
60
|
+
end
|
|
61
|
+
|
|
8
62
|
namespace 'gem' do
|
|
9
|
-
desc 'Create the net-ping gem'
|
|
63
|
+
desc 'Create the net-ping gem artifacts (ruby, universal-linux, universal-mingw-ucrt)'
|
|
10
64
|
task :create => [:clean] do
|
|
11
|
-
|
|
65
|
+
specifications = load_gem_specifications
|
|
12
66
|
if Gem::VERSION.to_f < 2.0
|
|
13
|
-
|
|
67
|
+
specifications.each do |spec|
|
|
68
|
+
Gem::Builder.new(spec).build
|
|
69
|
+
end
|
|
14
70
|
else
|
|
15
71
|
require 'rubygems/package'
|
|
16
|
-
|
|
72
|
+
specifications.each do |spec|
|
|
73
|
+
Gem::Package.build(spec)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
desc 'Validate the net-ping gem artifacts'
|
|
79
|
+
task :check do
|
|
80
|
+
require 'rubygems/package'
|
|
81
|
+
|
|
82
|
+
EXPECTED_GEM_METADATA.each do |path, expectation|
|
|
83
|
+
expected_platform, expected_dependencies = expectation
|
|
84
|
+
artifact = Gem::Specification.load(path).file_name
|
|
85
|
+
packaged_spec = Gem::Package.new(artifact).spec
|
|
86
|
+
actual_dependencies = packaged_spec.runtime_dependencies.each_with_object({}) do |dependency, memo|
|
|
87
|
+
memo[dependency.name] = dependency.requirement.to_s
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
if platform_round_trips?(expected_platform) && packaged_spec.platform.to_s != expected_platform
|
|
91
|
+
abort("#{artifact}: expected platform #{expected_platform.inspect}, got #{packaged_spec.platform.to_s.inspect}")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if actual_dependencies != expected_dependencies
|
|
95
|
+
abort("#{artifact}: expected dependencies #{expected_dependencies.inspect}, got #{actual_dependencies.inspect}")
|
|
96
|
+
end
|
|
17
97
|
end
|
|
18
98
|
end
|
|
19
99
|
|
|
20
100
|
desc 'Install the net-ping gem'
|
|
21
101
|
task :install => [:create] do
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
102
|
+
spec = select_install_specification
|
|
103
|
+
|
|
104
|
+
install_command = if RUBY_PLATFORM == 'java'
|
|
105
|
+
['jruby', '-S', 'gem', 'install', '-l', spec.file_name]
|
|
25
106
|
else
|
|
26
|
-
|
|
107
|
+
['gem', 'install', '-l', spec.file_name]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
with_unbundled_env do
|
|
111
|
+
sh(*install_command)
|
|
27
112
|
end
|
|
28
113
|
end
|
|
29
114
|
end
|
data/lib/net/ping/external.rb
CHANGED
|
@@ -66,7 +66,7 @@ module Net
|
|
|
66
66
|
bool = true # Success, at least one response.
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
if err
|
|
69
|
+
if err && (err =~ /warning/i)
|
|
70
70
|
@warning = err.chomp
|
|
71
71
|
end
|
|
72
72
|
when 2
|
|
@@ -116,6 +116,8 @@ module Net
|
|
|
116
116
|
pcmd += ['-i', interval.to_s] unless RbConfig::CONFIG['busybox']
|
|
117
117
|
when /aix/i
|
|
118
118
|
pcmd += ['-c', count.to_s, '-w', timeout.to_s, host]
|
|
119
|
+
when /freebsd/i
|
|
120
|
+
pcmd += ['-c', count.to_s, '-x', timeout.to_s, host]
|
|
119
121
|
when /bsd|osx|mach|darwin/i
|
|
120
122
|
pcmd += ['-c', count.to_s, '-i', interval.to_s, host]
|
|
121
123
|
when /solaris|sunos/i
|
|
@@ -147,7 +149,7 @@ module Net
|
|
|
147
149
|
bool = true # Success, at least one response.
|
|
148
150
|
end
|
|
149
151
|
|
|
150
|
-
if err
|
|
152
|
+
if err && (err =~ /warning/i)
|
|
151
153
|
@warning = err.chomp
|
|
152
154
|
end
|
|
153
155
|
when 2
|
data/lib/net/ping/ping.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
require 'socket'
|
|
2
2
|
require 'timeout'
|
|
3
3
|
|
|
4
|
+
require_relative 'version'
|
|
5
|
+
|
|
4
6
|
# The Net module serves as a namespace only.
|
|
5
7
|
#
|
|
6
8
|
module Net
|
|
@@ -9,9 +11,6 @@ module Net
|
|
|
9
11
|
# types. You should not instantiate this class directly.
|
|
10
12
|
#
|
|
11
13
|
class Ping
|
|
12
|
-
# The version of the net-ping library.
|
|
13
|
-
VERSION = '2.0.9'
|
|
14
|
-
|
|
15
14
|
# The host to ping. In the case of Ping::HTTP, this is the URI.
|
|
16
15
|
attr_accessor :host
|
|
17
16
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
spec = Gem::Specification.load('net-ping.gemspec').dup
|
|
2
|
+
spec.platform = Gem::Platform.new(['universal', 'mingw-ucrt'])
|
|
3
|
+
spec.add_dependency('win32-security', '>= 0.2.0')
|
|
4
|
+
|
|
5
|
+
# No longer a default gem as of Ruby 4.0. Used by the WMI ping class.
|
|
6
|
+
spec.add_dependency('win32ole', '>= 1.8.8')
|
|
7
|
+
spec
|
data/net-ping.gemspec
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative "lib/net/ping/version"
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |spec|
|
|
4
4
|
spec.name = 'net-ping'
|
|
5
|
-
spec.version =
|
|
6
|
-
spec.license = 'Artistic
|
|
5
|
+
spec.version = Net::Ping::VERSION
|
|
6
|
+
spec.license = 'Artistic-2.0'
|
|
7
7
|
spec.author = 'Chris Chernesky'
|
|
8
8
|
spec.email = 'chris.netping@tinderglow.com'
|
|
9
9
|
spec.homepage = 'https://github.com/chernesk/net-ping'
|
|
10
10
|
spec.summary = 'A ping interface for Ruby.'
|
|
11
11
|
spec.test_file = 'test/test_net_ping.rb'
|
|
12
|
-
spec.files = Dir['**/*'].reject
|
|
12
|
+
spec.files = Dir['**/*'].reject do |f|
|
|
13
|
+
f.include?('git') || File.extname(f) == '.gem' || f == 'CLAUDE.md' || f == 'docs' || f.start_with?('docs/')
|
|
14
|
+
end
|
|
13
15
|
spec.metadata = {
|
|
14
16
|
'bug_tracker_uri' => "#{spec.homepage}/issues",
|
|
15
17
|
'changelog_uri' => "#{spec.homepage}/blob/master/CHANGES",
|
|
@@ -28,17 +30,6 @@ Gem::Specification.new do |spec|
|
|
|
28
30
|
spec.add_development_dependency('rake', '>= 0')
|
|
29
31
|
spec.add_development_dependency('pry-byebug', '>= 0')
|
|
30
32
|
|
|
31
|
-
if File::ALT_SEPARATOR
|
|
32
|
-
require 'rbconfig'
|
|
33
|
-
arch = RbConfig::CONFIG['build_os'] || 'mingw32' # JRuby
|
|
34
|
-
spec.platform = Gem::Platform.new(['universal', arch])
|
|
35
|
-
spec.platform.version = nil
|
|
36
|
-
|
|
37
|
-
# Used for icmp pings.
|
|
38
|
-
spec.add_dependency('win32-security', '>= 0.2.0')
|
|
39
|
-
end
|
|
40
|
-
spec.add_dependency('cap2', '>= 0.2.2') if RUBY_PLATFORM =~ /linux/i
|
|
41
|
-
|
|
42
33
|
spec.description = <<-EOF
|
|
43
34
|
The net-ping library provides a ping interface for Ruby. It includes
|
|
44
35
|
separate TCP, HTTP, LDAP, ICMP, UDP, WMI (for Windows) and external ping
|
data/test/test_net_ping.rb
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# class test won't be run unless this is run as a privileged process.
|
|
6
6
|
######################################################################
|
|
7
7
|
require 'test_net_ping_external'
|
|
8
|
+
require 'test_net_ping_gem_packaging'
|
|
8
9
|
require 'test_net_ping_http'
|
|
9
10
|
require 'test_net_ping_tcp'
|
|
10
11
|
require 'test_net_ping_udp'
|
|
@@ -38,6 +39,6 @@ end
|
|
|
38
39
|
|
|
39
40
|
class TC_Net_Ping < Test::Unit::TestCase
|
|
40
41
|
def test_net_ping_version
|
|
41
|
-
assert_equal('
|
|
42
|
+
assert_equal(Gem::Specification.load('net-ping.gemspec').version.to_s, Net::Ping::VERSION)
|
|
42
43
|
end
|
|
43
44
|
end
|
|
@@ -140,6 +140,30 @@ class TC_Net_Ping_External < Test::Unit::TestCase
|
|
|
140
140
|
assert_false(@bad.ping?)
|
|
141
141
|
end
|
|
142
142
|
|
|
143
|
+
test "ping6 uses timeout for FreeBSD" do
|
|
144
|
+
command = nil
|
|
145
|
+
original_os = RbConfig::CONFIG['host_os']
|
|
146
|
+
original_popen3 = Open3.method(:popen3)
|
|
147
|
+
|
|
148
|
+
RbConfig::CONFIG['host_os'] = 'freebsd'
|
|
149
|
+
Open3.define_singleton_method(:popen3) do |*args, &block|
|
|
150
|
+
command = args
|
|
151
|
+
stdin = StringIO.new
|
|
152
|
+
stdout = StringIO.new
|
|
153
|
+
stderr = StringIO.new
|
|
154
|
+
status = Struct.new(:exitstatus).new(0)
|
|
155
|
+
thread = Struct.new(:value).new(status)
|
|
156
|
+
block.call(stdin, stdout, stderr, thread)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
@pe.ping6('example.test', 2, 3, 4)
|
|
160
|
+
|
|
161
|
+
assert_equal(['ping6', '-c', '2', '-x', '4', 'example.test'], command)
|
|
162
|
+
ensure
|
|
163
|
+
RbConfig::CONFIG['host_os'] = original_os
|
|
164
|
+
Open3.define_singleton_method(:popen3, original_popen3)
|
|
165
|
+
end
|
|
166
|
+
|
|
143
167
|
test "ping6 uses interval for macOS" do
|
|
144
168
|
command = nil
|
|
145
169
|
original_os = RbConfig::CONFIG['host_os']
|
|
@@ -164,6 +188,41 @@ class TC_Net_Ping_External < Test::Unit::TestCase
|
|
|
164
188
|
Open3.define_singleton_method(:popen3, original_popen3)
|
|
165
189
|
end
|
|
166
190
|
|
|
191
|
+
test "ping6 succeeds without an exception when stderr is empty" do
|
|
192
|
+
stdin = StringIO.new
|
|
193
|
+
stdout = StringIO.new('64 bytes from ::1')
|
|
194
|
+
stderr = StringIO.new
|
|
195
|
+
status = Struct.new(:exitstatus).new(0)
|
|
196
|
+
thread = Struct.new(:value).new(status)
|
|
197
|
+
popen3 = Open3.method(:popen3)
|
|
198
|
+
nil_match = NilClass.instance_method(:=~) if NilClass.instance_methods(false).include?(:=~)
|
|
199
|
+
false_match = FalseClass.instance_method(:=~) if FalseClass.instance_methods(false).include?(:=~)
|
|
200
|
+
|
|
201
|
+
Open3.singleton_class.send(:define_method, :popen3) do |*args, &block|
|
|
202
|
+
block.call(stdin, stdout, stderr, thread)
|
|
203
|
+
end
|
|
204
|
+
[NilClass, FalseClass].each do |klass|
|
|
205
|
+
klass.send(:define_method, :=~) do |*args|
|
|
206
|
+
raise NoMethodError, "undefined method '=~' for #{self.inspect}"
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
assert_true(@pe.ping6('::1'))
|
|
211
|
+
assert_nil(@pe.exception)
|
|
212
|
+
ensure
|
|
213
|
+
Open3.singleton_class.send(:define_method, :popen3, popen3) if popen3
|
|
214
|
+
if nil_match
|
|
215
|
+
NilClass.send(:define_method, :=~, nil_match)
|
|
216
|
+
else
|
|
217
|
+
NilClass.send(:remove_method, :=~)
|
|
218
|
+
end
|
|
219
|
+
if false_match
|
|
220
|
+
FalseClass.send(:define_method, :=~, false_match)
|
|
221
|
+
else
|
|
222
|
+
FalseClass.send(:remove_method, :=~)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
167
226
|
def teardown
|
|
168
227
|
@host = nil
|
|
169
228
|
@bogus = nil
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
require 'open3'
|
|
2
|
+
require 'rake'
|
|
3
|
+
require 'rubygems/package'
|
|
4
|
+
require 'test/unit'
|
|
5
|
+
|
|
6
|
+
class TestNetPingGemPackaging < Test::Unit::TestCase
|
|
7
|
+
GemfileRecorder = Struct.new(:dependencies) do
|
|
8
|
+
def initialize
|
|
9
|
+
super({})
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def source(*); end
|
|
13
|
+
def gemspec(*); end
|
|
14
|
+
|
|
15
|
+
def gem(name, *requirements)
|
|
16
|
+
dependencies[name] = requirements
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
EXPECTATIONS = {
|
|
21
|
+
'net-ping.gemspec' => ['ruby', {}],
|
|
22
|
+
'net-ping-universal-linux.gemspec' => ['universal-linux', {'cap2' => '>= 0.2.2'}],
|
|
23
|
+
'net-ping-universal-mingw-ucrt.gemspec' => [
|
|
24
|
+
'universal-mingw-ucrt',
|
|
25
|
+
{'win32-security' => '>= 0.2.0', 'win32ole' => '>= 1.8.8'}
|
|
26
|
+
]
|
|
27
|
+
}.freeze
|
|
28
|
+
ROOT = File.expand_path('..', __dir__)
|
|
29
|
+
|
|
30
|
+
def test_platforms_and_runtime_dependencies
|
|
31
|
+
gem_files = nil
|
|
32
|
+
specifications = load_specifications
|
|
33
|
+
|
|
34
|
+
Dir.chdir(ROOT) do
|
|
35
|
+
gem_files = specifications.map { |_, spec| Gem::Package.build(spec) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
specifications.each do |path, spec|
|
|
39
|
+
expected_platform, expected_dependencies = EXPECTATIONS.fetch(path)
|
|
40
|
+
packaged_spec = Gem::Package.new(File.join(ROOT, spec.file_name)).spec
|
|
41
|
+
dependencies = packaged_spec.runtime_dependencies.each_with_object({}) do |dependency, memo|
|
|
42
|
+
memo[dependency.name] = dependency.requirement.to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
assert_equal(expected_dependencies, dependencies, path)
|
|
46
|
+
|
|
47
|
+
if platform_round_trips_for_test?(expected_platform)
|
|
48
|
+
assert_equal(expected_platform, packaged_spec.platform.to_s, path)
|
|
49
|
+
else
|
|
50
|
+
omit("this RubyGems (#{Gem::VERSION}) cannot round-trip the #{expected_platform.inspect} platform string")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
ensure
|
|
54
|
+
delete_files(gem_files)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_rake_create_builds_all_expected_artifacts_and_validates_them
|
|
58
|
+
stdout, stderr, status = run_rake('clean', 'gem:create', 'gem:check')
|
|
59
|
+
|
|
60
|
+
assert(status.success?, [stdout, stderr].join)
|
|
61
|
+
assert_equal(expected_gem_files, built_gem_files)
|
|
62
|
+
ensure
|
|
63
|
+
delete_files(built_gem_files)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_gem_create_excludes_generated_artifacts_from_spec_files_and_keeps_bundle_exec_usable
|
|
67
|
+
stdout, stderr, status = run_rake('clean', 'gem:create')
|
|
68
|
+
|
|
69
|
+
assert(status.success?, [stdout, stderr].join)
|
|
70
|
+
load_specifications.each do |path, spec|
|
|
71
|
+
assert_equal([], spec.files.grep(/\.gem$/).sort, path)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
stdout, stderr, status = run_bundle_exec('ruby', '-e', 'puts :bundle_exec_after_gem_create')
|
|
75
|
+
assert(status.success?, [stdout, stderr].join)
|
|
76
|
+
assert_equal("bundle_exec_after_gem_create\n", stdout)
|
|
77
|
+
ensure
|
|
78
|
+
delete_files(built_gem_files)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_gem_create_excludes_non_distributable_project_files_from_spec_files
|
|
82
|
+
load_specifications.each do |path, spec|
|
|
83
|
+
non_distributable = spec.files.select do |f|
|
|
84
|
+
f == 'CLAUDE.md' || f == 'docs' || f.start_with?('docs/')
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
assert_equal([], non_distributable, path)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_gem_check_uses_fixed_expectations_instead_of_loaded_specifications
|
|
92
|
+
stdout, stderr, status = run_rake('clean', 'gem:create')
|
|
93
|
+
|
|
94
|
+
assert(status.success?, [stdout, stderr].join)
|
|
95
|
+
|
|
96
|
+
specifications = load_specifications.map do |path, spec|
|
|
97
|
+
if path == 'net-ping-universal-linux.gemspec'
|
|
98
|
+
[path, specification_with_reported_platform(spec, Gem::Platform::RUBY)]
|
|
99
|
+
else
|
|
100
|
+
[path, spec]
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
with_rakefile do |application|
|
|
105
|
+
with_stubbed_load_gem_specifications(specifications.map(&:last)) do
|
|
106
|
+
assert_nothing_raised { application['gem:check'].invoke }
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
ensure
|
|
110
|
+
delete_files(built_gem_files)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def test_gem_install_selects_local_compatible_specification
|
|
114
|
+
with_rakefile do
|
|
115
|
+
assert_equal(expected_install_platform, select_install_specification.platform.to_s)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_gemfile_adds_win32_security_only_for_windows_development
|
|
120
|
+
assert_nil(gemfile_dependencies_for(win_platform: false)['win32-security'])
|
|
121
|
+
assert_equal(
|
|
122
|
+
['>= 0.2.0'],
|
|
123
|
+
gemfile_dependencies_for(win_platform: true)['win32-security']
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def test_with_unbundled_env_prefers_with_unbundled_env_when_available
|
|
128
|
+
calls = []
|
|
129
|
+
|
|
130
|
+
with_rakefile do
|
|
131
|
+
with_stubbed_bundler_methods(
|
|
132
|
+
:with_unbundled_env => proc do |&block|
|
|
133
|
+
calls << :with_unbundled_env
|
|
134
|
+
block.call
|
|
135
|
+
end,
|
|
136
|
+
:with_clean_env => proc do |&block|
|
|
137
|
+
calls << :with_clean_env
|
|
138
|
+
block.call
|
|
139
|
+
end
|
|
140
|
+
) do
|
|
141
|
+
assert_equal(:ran, with_unbundled_env { calls << :block; :ran })
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
assert_equal([:with_unbundled_env, :block], calls)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def test_with_unbundled_env_falls_back_to_with_clean_env
|
|
149
|
+
calls = []
|
|
150
|
+
|
|
151
|
+
with_rakefile do
|
|
152
|
+
with_stubbed_bundler_methods(
|
|
153
|
+
:with_clean_env => proc do |&block|
|
|
154
|
+
calls << :with_clean_env
|
|
155
|
+
block.call
|
|
156
|
+
end
|
|
157
|
+
) do
|
|
158
|
+
assert_equal(:ran, with_unbundled_env { calls << :block; :ran })
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
assert_equal([:with_clean_env, :block], calls)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def test_platform_installable_prefers_installable_when_available
|
|
166
|
+
spec = Struct.new(:platform).new(:preferred_platform)
|
|
167
|
+
calls = []
|
|
168
|
+
|
|
169
|
+
with_rakefile do
|
|
170
|
+
with_stubbed_platform_methods(
|
|
171
|
+
:installable? => proc do |candidate|
|
|
172
|
+
calls << [:installable?, candidate.platform]
|
|
173
|
+
true
|
|
174
|
+
end,
|
|
175
|
+
:match => proc do |platform|
|
|
176
|
+
calls << [:match, platform]
|
|
177
|
+
false
|
|
178
|
+
end
|
|
179
|
+
) do
|
|
180
|
+
assert_equal(true, platform_installable?(spec))
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
assert_equal([[:installable?, :preferred_platform]], calls)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def test_platform_installable_falls_back_to_match
|
|
188
|
+
spec = Struct.new(:platform).new(:fallback_platform)
|
|
189
|
+
calls = []
|
|
190
|
+
|
|
191
|
+
with_rakefile do
|
|
192
|
+
with_stubbed_platform_methods(
|
|
193
|
+
:match => proc do |platform|
|
|
194
|
+
calls << [:match, platform]
|
|
195
|
+
true
|
|
196
|
+
end
|
|
197
|
+
) do
|
|
198
|
+
assert_equal(true, platform_installable?(spec))
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
assert_equal([[:match, :fallback_platform]], calls)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
private
|
|
206
|
+
|
|
207
|
+
def load_specifications
|
|
208
|
+
Dir.chdir(ROOT) do
|
|
209
|
+
EXPECTATIONS.keys.map do |path|
|
|
210
|
+
assert(File.exist?(path), "#{path} does not exist")
|
|
211
|
+
|
|
212
|
+
loaded_spec = Gem::Specification.load(path)
|
|
213
|
+
spec = loaded_spec ? loaded_spec.dup : nil
|
|
214
|
+
assert_not_nil(spec, "expected #{path} to load")
|
|
215
|
+
|
|
216
|
+
[path, spec]
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def expected_gem_files
|
|
222
|
+
load_specifications.map { |_, spec| spec.file_name }.sort
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def built_gem_files
|
|
226
|
+
Dir.chdir(ROOT) { Dir['net-ping-*.gem'].sort }
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def expected_install_platform
|
|
230
|
+
specifications = load_specifications.map(&:last)
|
|
231
|
+
specific = specifications.find do |spec|
|
|
232
|
+
spec.platform != Gem::Platform::RUBY && platform_installable_for_test?(spec)
|
|
233
|
+
end
|
|
234
|
+
(specific || specifications.find { |spec| spec.platform == Gem::Platform::RUBY }).platform.to_s
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def run_rake(*tasks, env: {})
|
|
238
|
+
Open3.capture3(env, Gem.ruby, '-S', 'bundle', 'exec', 'rake', *tasks, chdir: ROOT)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def run_bundle_exec(*command, env: {})
|
|
242
|
+
Open3.capture3(env, Gem.ruby, '-S', 'bundle', 'exec', *command, chdir: ROOT)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def with_rakefile
|
|
246
|
+
original = Rake.application
|
|
247
|
+
application = Rake::Application.new
|
|
248
|
+
Rake.application = application
|
|
249
|
+
|
|
250
|
+
Dir.chdir(ROOT) do
|
|
251
|
+
load File.join(ROOT, 'Rakefile')
|
|
252
|
+
yield(application)
|
|
253
|
+
end
|
|
254
|
+
ensure
|
|
255
|
+
Rake.application = original
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def gemfile_dependencies_for(win_platform:)
|
|
259
|
+
recorder = GemfileRecorder.new
|
|
260
|
+
singleton_class = class << Gem; self; end
|
|
261
|
+
original = singleton_class.instance_method(:win_platform?)
|
|
262
|
+
singleton_class.send(:define_method, :win_platform?) { win_platform }
|
|
263
|
+
recorder.instance_eval(File.read(File.join(ROOT, 'Gemfile')), File.join(ROOT, 'Gemfile'))
|
|
264
|
+
|
|
265
|
+
recorder.dependencies
|
|
266
|
+
ensure
|
|
267
|
+
singleton_class.send(:define_method, :win_platform?, original) if singleton_class && original
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def delete_files(paths)
|
|
271
|
+
Array(paths).each do |path|
|
|
272
|
+
file = File.join(ROOT, path)
|
|
273
|
+
File.delete(file) if File.exist?(file)
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def specification_with_reported_platform(spec, platform)
|
|
278
|
+
file_name = spec.file_name
|
|
279
|
+
mutated = spec.dup
|
|
280
|
+
mutated.platform = platform
|
|
281
|
+
mutated.define_singleton_method(:file_name) { file_name }
|
|
282
|
+
mutated
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def with_stubbed_load_gem_specifications(specifications)
|
|
286
|
+
original = Object.instance_method(:load_gem_specifications)
|
|
287
|
+
Object.send(:remove_method, :load_gem_specifications)
|
|
288
|
+
Object.send(:define_method, :load_gem_specifications) { specifications }
|
|
289
|
+
Object.send(:private, :load_gem_specifications)
|
|
290
|
+
yield
|
|
291
|
+
ensure
|
|
292
|
+
Object.send(:remove_method, :load_gem_specifications)
|
|
293
|
+
Object.send(:define_method, :load_gem_specifications, original)
|
|
294
|
+
Object.send(:private, :load_gem_specifications)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def with_stubbed_bundler_methods(methods)
|
|
298
|
+
bundler = Module.new
|
|
299
|
+
methods.each do |name, implementation|
|
|
300
|
+
bundler.define_singleton_method(name, &implementation)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
with_replaced_constant(Object, :Bundler, bundler) do
|
|
304
|
+
yield
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def with_stubbed_platform_methods(methods)
|
|
309
|
+
platform = Module.new
|
|
310
|
+
methods.each do |name, implementation|
|
|
311
|
+
platform.define_singleton_method(name, &implementation)
|
|
312
|
+
end
|
|
313
|
+
platform.const_set(:RUBY, Gem::Platform::RUBY)
|
|
314
|
+
|
|
315
|
+
with_replaced_constant(Gem, :Platform, platform) do
|
|
316
|
+
yield
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def with_replaced_constant(container, name, replacement)
|
|
321
|
+
original = container.const_get(name) if container.const_defined?(name, false)
|
|
322
|
+
container.send(:remove_const, name) if container.const_defined?(name, false)
|
|
323
|
+
container.const_set(name, replacement)
|
|
324
|
+
yield
|
|
325
|
+
ensure
|
|
326
|
+
container.send(:remove_const, name) if container.const_defined?(name, false)
|
|
327
|
+
if original
|
|
328
|
+
container.const_set(name, original)
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def platform_round_trips_for_test?(platform_string)
|
|
333
|
+
Gem::Platform.new(platform_string).to_s == platform_string
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def platform_installable_for_test?(spec)
|
|
337
|
+
if Gem::Platform.respond_to?(:installable?)
|
|
338
|
+
Gem::Platform.installable?(spec)
|
|
339
|
+
else
|
|
340
|
+
Gem::Platform.match(spec.platform)
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
end
|
data/test/test_net_ping_http.rb
CHANGED
|
@@ -131,12 +131,11 @@ class TC_Net_Ping_HTTP < Test::Unit::TestCase
|
|
|
131
131
|
assert_equal(5, @bad.timeout)
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
-
# TODO: Figure out how to do this with WebMock.
|
|
135
134
|
test 'ping fails if timeout exceeded' do
|
|
136
|
-
|
|
135
|
+
stub_request(:head, 'https://www.google.com/').to_timeout
|
|
137
136
|
@http = Net::Ping::HTTP.new('https://www.google.com', 443, 0.001)
|
|
138
137
|
assert_false(@http.ping?)
|
|
139
|
-
|
|
138
|
+
assert_include(['execution expired', 'Net::OpenTimeout'], @http.exception)
|
|
140
139
|
end
|
|
141
140
|
|
|
142
141
|
test 'exception attribute basic functionality' do
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: net-ping
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Chernesky
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: test-unit
|
|
@@ -97,10 +97,14 @@ files:
|
|
|
97
97
|
- lib/net/ping/ping.rb
|
|
98
98
|
- lib/net/ping/tcp.rb
|
|
99
99
|
- lib/net/ping/udp.rb
|
|
100
|
+
- lib/net/ping/version.rb
|
|
100
101
|
- lib/net/ping/wmi.rb
|
|
102
|
+
- net-ping-universal-linux.gemspec
|
|
103
|
+
- net-ping-universal-mingw-ucrt.gemspec
|
|
101
104
|
- net-ping.gemspec
|
|
102
105
|
- test/test_net_ping.rb
|
|
103
106
|
- test/test_net_ping_external.rb
|
|
107
|
+
- test/test_net_ping_gem_packaging.rb
|
|
104
108
|
- test/test_net_ping_http.rb
|
|
105
109
|
- test/test_net_ping_icmp.rb
|
|
106
110
|
- test/test_net_ping_tcp.rb
|
|
@@ -108,7 +112,7 @@ files:
|
|
|
108
112
|
- test/test_net_ping_wmi.rb
|
|
109
113
|
homepage: https://github.com/chernesk/net-ping
|
|
110
114
|
licenses:
|
|
111
|
-
- Artistic
|
|
115
|
+
- Artistic-2.0
|
|
112
116
|
metadata:
|
|
113
117
|
bug_tracker_uri: https://github.com/chernesk/net-ping/issues
|
|
114
118
|
changelog_uri: https://github.com/chernesk/net-ping/blob/master/CHANGES
|