random-port 0.7.4 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97daaf8ddcb40b28c9702c20272747d85619de8b19301f05a34918c6dd275cca
4
- data.tar.gz: 48a06545628a4bfb4c3ee8b59e1880d83cd22cacc5fa22a893717b70225f08a5
3
+ metadata.gz: 685cbbb964686d55837c88f3856b60207d3abaadb76e96ba9f9093bc8aba0a9c
4
+ data.tar.gz: 83e7ea6c0ac635b3c06cb1d190d3a991be61d4d534596ae10852c1a7a8df542d
5
5
  SHA512:
6
- metadata.gz: da44606055d80695de6baea9ef514b98d5b5d0cf82bac7276981edef778f2aabb7d2532d722b576eabffd2d4a58e7d21a8ee8effbb48f7d2c86e1b02dbd9ffed
7
- data.tar.gz: 49c67ec4a38bdcf60cf12d7d53078ddbf70370899cd5da8c03cd7ce82a46750ba79bf35242d2b6cf32ab31742c4ebea0bec473ee95448e6b3692c21ec6965393
6
+ metadata.gz: 48adf68a56c6ac4550287538b7cefa09cf033575e56dd8cdd6d53f0bc49004c87270f4c3b1d5c30576e721bf9c0589245c50854b494a3ec191588fc9e974253a
7
+ data.tar.gz: bd33bb2321ea165a1e9e546fa257db2a824572a07462af36ebd0e4e2fe93a4679c16f269170f51042046e139c7ed35a76bd4bd39338dd6a00777ddb4c1fb1214
data/.0pdd.yml CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -19,12 +19,13 @@
19
19
  # SOFTWARE.
20
20
  ---
21
21
  name: codecov
22
- on:
22
+ 'on':
23
23
  push:
24
24
  branches:
25
25
  - master
26
26
  jobs:
27
27
  codecov:
28
+ timeout-minutes: 5
28
29
  runs-on: ubuntu-24.04
29
30
  steps:
30
31
  - uses: actions/checkout@v4
@@ -36,3 +37,5 @@ jobs:
36
37
  - uses: codecov/codecov-action@v5
37
38
  with:
38
39
  token: ${{ secrets.CODECOV_TOKEN }}
40
+ files: coverage/.resultset.json
41
+ fail_ci_if_error: true
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -19,7 +19,7 @@
19
19
  # SOFTWARE.
20
20
  ---
21
21
  name: pdd
22
- on:
22
+ 'on':
23
23
  push:
24
24
  branches:
25
25
  - master
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -19,7 +19,7 @@
19
19
  # SOFTWARE.
20
20
  ---
21
21
  name: rake
22
- on:
22
+ 'on':
23
23
  push:
24
24
  branches:
25
25
  - master
@@ -27,8 +27,8 @@ on:
27
27
  branches:
28
28
  - master
29
29
  jobs:
30
- test:
31
- name: test
30
+ rake:
31
+ timeout-minutes: 5
32
32
  strategy:
33
33
  matrix:
34
34
  os: [ubuntu-24.04, macos-15, windows-2022]
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
data/.gitignore CHANGED
@@ -5,4 +5,4 @@ Gemfile.lock
5
5
  rdoc/
6
6
  coverage/
7
7
  .yardoc/
8
- doc/
8
+ doc/
data/.rubocop.yml CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -23,7 +23,11 @@ AllCops:
23
23
  TargetRubyVersion: 2.3.3
24
24
  NewCops: enable
25
25
  SuggestExtensions: false
26
+ require:
27
+ - rubocop-minitest
26
28
 
29
+ Minitest/EmptyLineBeforeAssertionMethods:
30
+ Enabled: false
27
31
  Layout/EmptyLineAfterGuardClause:
28
32
  Enabled: false
29
33
  Style/ClassAndModuleChildren:
@@ -44,3 +48,5 @@ Metrics/CyclomaticComplexity:
44
48
  Max: 20
45
49
  Metrics/AbcSize:
46
50
  Max: 60
51
+ Metrics/ClassLength:
52
+ Max: 150
data/.rultor.yml CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018-2024 Yegor Bugayenko
1
+ # Copyright (c) 2018-2025 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2018-2024 Yegor Bugayenko
3
+ # Copyright (c) 2018-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -24,9 +24,11 @@ source 'https://rubygems.org'
24
24
  gemspec
25
25
 
26
26
  gem 'minitest', '5.25.4', require: false
27
+ gem 'qbash', '>=0.2.2', require: false
27
28
  gem 'rake', '13.2.1', require: false
28
- gem 'rubocop', '1.69.2', require: false
29
- gem 'rubocop-rspec', '3.3.0', require: false
29
+ gem 'rubocop', '1.71.0', require: false
30
+ gem 'rubocop-minitest', '0.36.0', require: false
31
+ gem 'rubocop-rspec', '3.4.0', require: false
30
32
  gem 'simplecov', '0.22.0', require: false
31
33
  gem 'threads', '0.4.1', require: false
32
34
  gem 'yard', '0.9.37', require: false
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2018-2024 Yegor Bugayenko
3
+ Copyright (c) 2018-2025 Yegor Bugayenko
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the 'Software'), to deal
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2018-2024 Yegor Bugayenko
3
+ # Copyright (c) 2018-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -2,7 +2,7 @@
2
2
 
3
3
  # (The MIT License)
4
4
  #
5
- # Copyright (c) 2018-2024 Yegor Bugayenko
5
+ # Copyright (c) 2018-2025 Yegor Bugayenko
6
6
  #
7
7
  # Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@
25
25
  # The module for all classes.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2018-2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2018-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module RandomPort
31
31
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  # (The MIT License)
4
4
  #
5
- # Copyright (c) 2018-2024 Yegor Bugayenko
5
+ # Copyright (c) 2018-2025 Yegor Bugayenko
6
6
  #
7
7
  # Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  # of this software and associated documentation files (the 'Software'), to deal
@@ -44,7 +44,7 @@ require_relative 'module'
44
44
  # passing <tt>FALSE</tt>.
45
45
  #
46
46
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
47
- # Copyright:: Copyright (c) 2018-2024 Yegor Bugayenko
47
+ # Copyright:: Copyright (c) 2018-2025 Yegor Bugayenko
48
48
  # License:: MIT
49
49
  class RandomPort::Pool
50
50
  # If can't acquire by time out.
@@ -55,12 +55,13 @@ class RandomPort::Pool
55
55
  # Ctor.
56
56
  # @param [Boolean] sync Set it to FALSE if you want this pool to be NOT thread-safe
57
57
  # @param [Integer] limit Set the maximum number of ports in the pool
58
- def initialize(sync: true, limit: 65_536)
58
+ # @param [Integer] start The next port to try
59
+ def initialize(sync: true, limit: 65_536, start: 1025)
59
60
  @ports = []
60
61
  @sync = sync
61
62
  @monitor = Monitor.new
62
63
  @limit = limit
63
- @next = 1024
64
+ @next = start
64
65
  end
65
66
 
66
67
  # Application wide pool of ports
@@ -133,7 +134,7 @@ class RandomPort::Pool
133
134
  # @param [Integer] total How many ports to take
134
135
  # @return [Array<Integer>|nil] Ports found or NIL if impossible now
135
136
  def group(total)
136
- return if @ports.count + total > @limit
137
+ return nil if @ports.count + total > @limit
137
138
  opts = Array.new(0, total)
138
139
  begin
139
140
  (0..(total - 1)).each do |i|
@@ -141,23 +142,26 @@ class RandomPort::Pool
141
142
  opts[i] = take(port)
142
143
  end
143
144
  rescue Errno::EADDRINUSE, SocketError
144
- return
145
+ return nil
145
146
  end
146
- return if opts.any? { |p| @ports.include?(p) }
147
+ return nil if opts.any? { |p| @ports.include?(p) }
147
148
  d = total * (total - 1) / 2
148
- return unless opts.inject(&:+) - (total * opts.min) == d
149
+ return nil unless opts.inject(&:+) - (total * opts.min) == d
149
150
  @ports += opts
150
151
  opts
151
152
  end
152
153
 
153
- # Find one possible TCP port.
154
- # @param [Integer] opt Suggested port number
155
- # @return [Integer] Port found
156
- def take(opt = 0)
157
- server = TCPServer.new('127.0.0.1', opt)
158
- p = server.addr[1]
159
- server.close
160
- p
154
+ # Find one possible TCP port or raise exception if this port can't be used.
155
+ #
156
+ # If port is occupied, this method raises an error (+Errno::EADDRINUSE+).
157
+ #
158
+ # @param [Integer] port Suggested port number
159
+ # @return [Integer] The same port number
160
+ def take(port)
161
+ ['127.0.0.1', '::1', '0.0.0.0', 'localhost'].each do |host|
162
+ TCPServer.new(host, port).close
163
+ end
164
+ port
161
165
  end
162
166
 
163
167
  def safe(&block)
data/lib/random-port.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # (The MIT License)
4
4
  #
5
- # Copyright (c) 2018-2024 Yegor Bugayenko
5
+ # Copyright (c) 2018-2025 Yegor Bugayenko
6
6
  #
7
7
  # Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  # of this software and associated documentation files (the 'Software'), to deal
data/random-port.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # (The MIT License)
4
4
  #
5
- # Copyright (c) 2018-2024 Yegor Bugayenko
5
+ # Copyright (c) 2018-2025 Yegor Bugayenko
6
6
  #
7
7
  # Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  # of this software and associated documentation files (the 'Software'), to deal
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
28
28
  s.required_ruby_version = '>=2.3'
29
29
  s.name = 'random-port'
30
- s.version = '0.7.4'
30
+ s.version = '0.7.5'
31
31
  s.license = 'MIT'
32
32
  s.summary = 'Random TCP port'
33
33
  s.description = 'Reserves a random TCP port'
data/test/test__helper.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2018-2024 Yegor Bugayenko
3
+ # Copyright (c) 2018-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -24,4 +24,5 @@ $stdout.sync = true
24
24
 
25
25
  require 'simplecov'
26
26
  SimpleCov.start
27
+
27
28
  require 'minitest/autorun'
data/test/test_pool.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # (The MIT License)
4
4
  #
5
- # Copyright (c) 2018-2024 Yegor Bugayenko
5
+ # Copyright (c) 2018-2025 Yegor Bugayenko
6
6
  #
7
7
  # Permission is hereby granted, free of charge, to any person obtaining a copy
8
8
  # of this software and associated documentation files (the 'Software'), to deal
@@ -23,13 +23,15 @@
23
23
  # SOFTWARE.
24
24
 
25
25
  require 'minitest/autorun'
26
- require 'threads'
26
+ require 'qbash'
27
+ require 'shellwords'
27
28
  require 'socket'
29
+ require 'threads'
28
30
  require_relative '../lib/random-port/pool'
29
31
 
30
32
  # Pool test.
31
33
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
32
- # Copyright:: Copyright (c) 2018-2024 Yegor Bugayenko
34
+ # Copyright:: Copyright (c) 2018-2025 Yegor Bugayenko
33
35
  # License:: MIT
34
36
  class RandomPort::TestPool < Minitest::Test
35
37
  def test_acquires_and_releases
@@ -37,8 +39,8 @@ class RandomPort::TestPool < Minitest::Test
37
39
  port = pool.acquire
38
40
  server = TCPServer.new('localhost', port)
39
41
  server.close
40
- assert(!port.nil?)
41
- assert(port.positive?)
42
+ refute_nil(port)
43
+ assert_predicate(port, :positive?)
42
44
  pool.release(port)
43
45
  end
44
46
 
@@ -56,11 +58,56 @@ class RandomPort::TestPool < Minitest::Test
56
58
  assert_equal(0, pool.size)
57
59
  end
58
60
 
61
+ def test_skips_truly_busy_port
62
+ port = RandomPort::Pool.new.acquire
63
+ server = TCPServer.new('127.0.0.1', port)
64
+ other = RandomPort::Pool.new(start: port).acquire
65
+ refute_equal(other, port)
66
+ server.close
67
+ end
68
+
69
+ def test_skips_externally_busy_port
70
+ skip 'Not supported on Windows' if Gem.win_platform?
71
+ ['127.0.0.1', 'localhost', '::1', '0.0.0.0'].each do |host|
72
+ Dir.mktmpdir do |home|
73
+ port = RandomPort::Pool.new.acquire
74
+ started = File.join(home, 'started.txt')
75
+ enough = File.join(home, 'enough.txt')
76
+ t =
77
+ Thread.new do
78
+ qbash(
79
+ [
80
+ 'ruby', '-e',
81
+ Shellwords.escape(
82
+ "
83
+ require 'socket'
84
+ require 'fileutils'
85
+ TCPServer.new('#{host}', #{port})
86
+ FileUtils.touch('#{started}')
87
+ loop do
88
+ break if File.exist?('#{enough}')
89
+ end
90
+ "
91
+ )
92
+ ]
93
+ )
94
+ end
95
+ loop do
96
+ break if File.exist?(started)
97
+ end
98
+ other = RandomPort::Pool.new(start: port).acquire
99
+ FileUtils.touch(enough)
100
+ t.join
101
+ refute_equal(other, port)
102
+ end
103
+ end
104
+ end
105
+
59
106
  def test_acquires_and_releases_three_ports_in_block
60
107
  pool = RandomPort::Pool.new(limit: 3)
61
108
  assert_equal(0, pool.size)
62
109
  pool.acquire(3, timeout: 16) do |ports|
63
- assert(ports.is_a?(Array))
110
+ assert_kind_of(Array, ports)
64
111
  assert_equal(3, ports.count)
65
112
  assert_equal(3, pool.size)
66
113
  ports.each do |p|
@@ -73,8 +120,8 @@ class RandomPort::TestPool < Minitest::Test
73
120
 
74
121
  def test_acquires_and_releases_in_block
75
122
  result = RandomPort::Pool.new.acquire do |port|
76
- assert(!port.nil?)
77
- assert(port.positive?)
123
+ refute_nil(port)
124
+ assert_predicate(port, :positive?)
78
125
  123
79
126
  end
80
127
  assert_equal(123, result)
@@ -94,18 +141,18 @@ class RandomPort::TestPool < Minitest::Test
94
141
 
95
142
  def test_acquires_and_releases_safely
96
143
  pool = RandomPort::Pool.new
97
- assert_raises do
144
+ assert_raises(StandardError) do
98
145
  pool.acquire do
99
146
  raise 'Itended'
100
147
  end
101
148
  end
102
- assert(pool.count.zero?)
149
+ assert_predicate(pool.count, :zero?)
103
150
  end
104
151
 
105
152
  def test_acquires_and_releases_from_singleton
106
153
  RandomPort::Pool::SINGLETON.acquire do |port|
107
- assert(!port.nil?)
108
- assert(port.positive?)
154
+ refute_nil(port)
155
+ assert_predicate(port, :positive?)
109
156
  end
110
157
  end
111
158
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: random-port
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 0.7.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-29 00:00:00.000000000 Z
11
+ date: 2025-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tago