random-port 0.7.4 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
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