test-queue 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +42 -42
  3. data/exe/cucumber-queue +2 -1
  4. data/exe/minitest-queue +3 -2
  5. data/exe/rspec-queue +2 -1
  6. data/exe/testunit-queue +2 -1
  7. data/lib/test-queue.rb +2 -0
  8. data/lib/test_queue/iterator.rb +22 -14
  9. data/lib/test_queue/runner/cucumber.rb +3 -0
  10. data/lib/test_queue/runner/{sample.rb → example.rb} +30 -9
  11. data/lib/test_queue/runner/minitest.rb +5 -3
  12. data/lib/test_queue/runner/minitest4.rb +12 -7
  13. data/lib/test_queue/runner/minitest5.rb +37 -22
  14. data/lib/test_queue/runner/puppet_lint.rb +6 -4
  15. data/lib/test_queue/runner/rspec.rb +14 -3
  16. data/lib/test_queue/runner/rspec2.rb +24 -24
  17. data/lib/test_queue/runner/rspec3.rb +11 -11
  18. data/lib/test_queue/runner/testunit.rb +6 -3
  19. data/lib/test_queue/runner.rb +87 -97
  20. data/lib/test_queue/stats.rb +17 -13
  21. data/lib/test_queue/test_framework.rb +2 -0
  22. data/lib/test_queue/version.rb +5 -0
  23. data/lib/test_queue.rb +1 -5
  24. metadata +7 -44
  25. data/.github/workflows/test.yml +0 -94
  26. data/.gitignore +0 -7
  27. data/Appraisals +0 -43
  28. data/Gemfile +0 -7
  29. data/Rakefile +0 -14
  30. data/gemfiles/cucumber1_3.gemfile +0 -9
  31. data/gemfiles/cucumber2_4.gemfile +0 -9
  32. data/gemfiles/minitest4.gemfile +0 -7
  33. data/gemfiles/minitest5.gemfile +0 -7
  34. data/gemfiles/rspec2.gemfile +0 -8
  35. data/gemfiles/rspec3.gemfile +0 -7
  36. data/gemfiles/rspec4.gemfile +0 -11
  37. data/gemfiles/testunit.gemfile +0 -7
  38. data/script/bootstrap +0 -13
  39. data/spec/stats_spec.rb +0 -79
  40. data/test/cucumber.bats +0 -57
  41. data/test/minitest4.bats +0 -34
  42. data/test/minitest5.bats +0 -194
  43. data/test/rspec2.bats +0 -46
  44. data/test/rspec3.bats +0 -56
  45. data/test/rspec4.bats +0 -56
  46. data/test/samples/features/bad.feature +0 -5
  47. data/test/samples/features/sample.feature +0 -25
  48. data/test/samples/features/sample2.feature +0 -29
  49. data/test/samples/features/step_definitions/common.rb +0 -19
  50. data/test/samples/sample_minispec.rb +0 -37
  51. data/test/samples/sample_minitest4.rb +0 -25
  52. data/test/samples/sample_minitest5.rb +0 -33
  53. data/test/samples/sample_rspec_helper.rb +0 -1
  54. data/test/samples/sample_shared_examples_for_spec.rb +0 -3
  55. data/test/samples/sample_spec.rb +0 -25
  56. data/test/samples/sample_split_spec.rb +0 -17
  57. data/test/samples/sample_testunit.rb +0 -25
  58. data/test/samples/sample_use_shared_example1_spec.rb +0 -7
  59. data/test/samples/sample_use_shared_example2_spec.rb +0 -7
  60. data/test/sleepy_runner.rb +0 -16
  61. data/test/testlib.bash +0 -89
  62. data/test/testunit.bats +0 -20
  63. data/test-queue.gemspec +0 -21
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ::RSpec::Core::ExampleGroup
2
4
  def self.failure_count
3
- examples.map {|e| e.execution_result[:status] == "failed"}.length
5
+ examples.map { |e| e.execution_result[:status] == 'failed' }.length
4
6
  end
5
7
  end
6
8
 
@@ -14,30 +16,28 @@ module RSpec::Core
14
16
 
15
17
  def run_each(iterator)
16
18
  @configuration.reporter.report(0, @configuration.randomize? ? @configuration.seed : nil) do |reporter|
17
- begin
18
- @configuration.run_hook(:before, :suite)
19
- iterator.map {|g|
20
- if g.is_a? ::RSpec::Core::Example
21
- print " #{g.full_description}: "
22
- example = g
23
- g = example.example_group
24
- ::RSpec.world.filtered_examples.clear
25
- examples = [example]
26
- examples.extend(::RSpec::Core::Extensions::Ordered::Examples)
27
- ::RSpec.world.filtered_examples[g] = examples
28
- else
29
- print " #{g.description}: "
30
- end
31
- start = Time.now
32
- ret = g.run(reporter)
33
- diff = Time.now-start
34
- puts(" <%.3f>" % diff)
19
+ @configuration.run_hook(:before, :suite)
20
+ iterator.map { |g|
21
+ if g.is_a? ::RSpec::Core::Example
22
+ print " #{g.full_description}: "
23
+ example = g
24
+ g = example.example_group
25
+ ::RSpec.world.filtered_examples.clear
26
+ examples = [example]
27
+ examples.extend(::RSpec::Core::Extensions::Ordered::Examples)
28
+ ::RSpec.world.filtered_examples[g] = examples
29
+ else
30
+ print " #{g.description}: "
31
+ end
32
+ start = Time.now
33
+ ret = g.run(reporter)
34
+ diff = Time.now - start
35
+ puts(' <%.3f>' % diff)
35
36
 
36
- ret
37
- }.all? ? 0 : @configuration.failure_exit_code
38
- ensure
39
- @configuration.run_hook(:after, :suite)
40
- end
37
+ ret
38
+ }.all? ? 0 : @configuration.failure_exit_code
39
+ ensure
40
+ @configuration.run_hook(:after, :suite)
41
41
  end
42
42
  end
43
43
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ::RSpec::Core::ExampleGroup
2
4
  def self.failure_count
3
- examples.map {|e| e.execution_result.status == "failed"}.length
5
+ examples.map { |e| e.execution_result.status == 'failed' }.length
4
6
  end
5
7
  end
6
8
 
@@ -9,13 +11,11 @@ module RSpec::Core
9
11
  unless Configuration.method_defined?(:with_suite_hooks)
10
12
  class Configuration
11
13
  def with_suite_hooks
12
- begin
13
- hook_context = SuiteHookContext.new
14
- hooks.run(:before, :suite, hook_context)
15
- yield
16
- ensure
17
- hooks.run(:after, :suite, hook_context)
18
- end
14
+ hook_context = SuiteHookContext.new
15
+ hooks.run(:before, :suite, hook_context)
16
+ yield
17
+ ensure
18
+ hooks.run(:after, :suite, hook_context)
19
19
  end
20
20
  end
21
21
  end
@@ -41,14 +41,14 @@ module RSpec::Core
41
41
  print " #{g.description}: "
42
42
  end
43
43
  ret = g.run(reporter)
44
- diff = Time.now-start
45
- puts(" <%.3f>" % diff)
44
+ diff = Time.now - start
45
+ puts(' <%.3f>' % diff)
46
46
 
47
47
  ret
48
48
  }.all? ? 0 : @configuration.failure_exit_code
49
49
  end
50
50
  end
51
51
  end
52
- alias_method :run_each, :run_specs
52
+ alias run_each run_specs
53
53
  end
54
54
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../runner'
2
4
 
3
5
  gem 'test-unit'
@@ -28,7 +30,7 @@ class Test::Unit::TestSuite
28
30
  end
29
31
 
30
32
  def failure_count
31
- (@iterator || @tests).map {|t| t.instance_variable_get(:@_result).failure_count}.inject(0, :+)
33
+ (@iterator || @tests).sum { |t| t.instance_variable_get(:@_result).failure_count }
32
34
  end
33
35
  end
34
36
 
@@ -37,13 +39,14 @@ module TestQueue
37
39
  class TestUnit < Runner
38
40
  def initialize
39
41
  if Test::Unit::Collector::Descendant.new.collect.tests.any?
40
- fail "Do not `require` test files. Pass them via ARGV instead and they will be required as needed."
42
+ raise 'Do not `require` test files. Pass them via ARGV instead and they will be required as needed.'
41
43
  end
44
+
42
45
  super(TestFramework::TestUnit.new)
43
46
  end
44
47
 
45
48
  def run_worker(iterator)
46
- @suite = Test::Unit::TestSuite.new("specified by test-queue master")
49
+ @suite = Test::Unit::TestSuite.new('specified by test-queue master')
47
50
  @suite.iterator = iterator
48
51
  res = Test::Unit::UI::Console::TestRunner.new(@suite).start
49
52
  res.run_count - res.pass_count
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
  require 'socket'
3
5
  require 'fileutils'
@@ -33,7 +35,7 @@ module TestQueue
33
35
 
34
36
  TOKEN_REGEX = /\ATOKEN=(\w+)/
35
37
 
36
- def initialize(test_framework, concurrency=nil, socket=nil, relay=nil)
38
+ def initialize(test_framework, concurrency = nil, socket = nil, relay = nil)
37
39
  @test_framework = test_framework
38
40
  @stats = Stats.new(stats_file)
39
41
 
@@ -48,7 +50,7 @@ module TestQueue
48
50
 
49
51
  @procline = $0
50
52
 
51
- @allowlist = if forced = ENV['TEST_QUEUE_FORCE']
53
+ @allowlist = if (forced = ENV['TEST_QUEUE_FORCE'])
52
54
  forced.split(/\s*,\s*/)
53
55
  else
54
56
  []
@@ -57,13 +59,13 @@ module TestQueue
57
59
 
58
60
  all_files = @test_framework.all_suite_files.to_set
59
61
  @queue = @stats.all_suites
60
- .select { |suite| all_files.include?(suite.path) }
61
- .sort_by { |suite| -suite.duration }
62
- .map { |suite| [suite.name, suite.path] }
62
+ .select { |suite| all_files.include?(suite.path) }
63
+ .sort_by { |suite| -suite.duration }
64
+ .map { |suite| [suite.name, suite.path] }
63
65
 
64
66
  if @allowlist.any?
65
- @queue.select! { |suite_name, path| @allowlist.include?(suite_name) }
66
- @queue.sort_by! { |suite_name, path| @allowlist.index(suite_name) }
67
+ @queue.select! { |suite_name, _path| @allowlist.include?(suite_name) }
68
+ @queue.sort_by! { |suite_name, _path| @allowlist.index(suite_name) }
67
69
  end
68
70
 
69
71
  @awaited_suites = Set.new(@allowlist)
@@ -72,44 +74,32 @@ module TestQueue
72
74
  @workers = {}
73
75
  @completed = []
74
76
 
75
- @concurrency =
76
- concurrency ||
77
- (ENV['TEST_QUEUE_WORKERS'] && ENV['TEST_QUEUE_WORKERS'].to_i) ||
78
- if File.exist?('/proc/cpuinfo')
79
- File.read('/proc/cpuinfo').split("\n").grep(/processor/).size
80
- elsif RUBY_PLATFORM =~ /darwin/
81
- `/usr/sbin/sysctl -n hw.activecpu`.to_i
82
- else
83
- 2
84
- end
77
+ @concurrency = concurrency || ENV['TEST_QUEUE_WORKERS']&.to_i ||
78
+ if File.exist?('/proc/cpuinfo')
79
+ File.read('/proc/cpuinfo').split("\n").grep(/processor/).size
80
+ elsif RUBY_PLATFORM.include?('darwin')
81
+ `/usr/sbin/sysctl -n hw.activecpu`.to_i
82
+ else
83
+ 2
84
+ end
85
85
  unless @concurrency > 0
86
86
  raise ArgumentError, "Worker count (#{@concurrency}) must be greater than 0"
87
87
  end
88
88
 
89
- @relay_connection_timeout =
90
- (ENV['TEST_QUEUE_RELAY_TIMEOUT'] && ENV['TEST_QUEUE_RELAY_TIMEOUT'].to_i) ||
91
- 30
92
-
89
+ @relay_connection_timeout = ENV['TEST_QUEUE_RELAY_TIMEOUT']&.to_i || 30
93
90
  @run_token = ENV['TEST_QUEUE_RELAY_TOKEN'] || SecureRandom.hex(8)
94
-
95
- @socket =
96
- socket ||
97
- ENV['TEST_QUEUE_SOCKET'] ||
98
- "/tmp/test_queue_#{$$}_#{object_id}.sock"
99
-
100
- @relay =
101
- relay ||
102
- ENV['TEST_QUEUE_RELAY']
103
-
104
- @remote_master_message = if ENV.has_key?("TEST_QUEUE_REMOTE_MASTER_MESSAGE")
105
- ENV["TEST_QUEUE_REMOTE_MASTER_MESSAGE"]
106
- elsif ENV.has_key?("TEST_QUEUE_SLAVE_MESSAGE")
107
- warn("`TEST_QUEUE_SLAVE_MESSAGE` is deprecated. Use `TEST_QUEUE_REMOTE_MASTER_MESSAGE` instead.")
108
- ENV["TEST_QUEUE_SLAVE_MESSAGE"]
91
+ @socket = socket || ENV['TEST_QUEUE_SOCKET'] || "/tmp/test_queue_#{$$}_#{object_id}.sock"
92
+ @relay = relay || ENV['TEST_QUEUE_RELAY']
93
+
94
+ @remote_master_message = if ENV.key?('TEST_QUEUE_REMOTE_MASTER_MESSAGE')
95
+ ENV['TEST_QUEUE_REMOTE_MASTER_MESSAGE']
96
+ elsif ENV.key?('TEST_QUEUE_SLAVE_MESSAGE')
97
+ warn('`TEST_QUEUE_SLAVE_MESSAGE` is deprecated. Use `TEST_QUEUE_REMOTE_MASTER_MESSAGE` instead.')
98
+ ENV['TEST_QUEUE_SLAVE_MESSAGE']
109
99
  end
110
100
 
111
101
  if @relay == @socket
112
- STDERR.puts "*** Detected TEST_QUEUE_RELAY == TEST_QUEUE_SOCKET. Disabling relay mode."
102
+ warn '*** Detected TEST_QUEUE_RELAY == TEST_QUEUE_SOCKET. Disabling relay mode.'
113
103
  @relay = nil
114
104
  elsif @relay
115
105
  @queue = []
@@ -144,7 +134,7 @@ module TestQueue
144
134
 
145
135
  def summarize_internal
146
136
  puts
147
- puts "==> Summary (#{@completed.size} workers in %.4fs)" % (Time.now-@start_time)
137
+ puts "==> Summary (#{@completed.size} workers in %.4fs)" % (Time.now - @start_time)
148
138
  puts
149
139
 
150
140
  estatus = 0
@@ -167,9 +157,9 @@ module TestQueue
167
157
 
168
158
  summarize_worker(worker)
169
159
 
170
- @failures << worker.failure_output if worker.failure_output
160
+ @failures += worker.failure_output if worker.failure_output
171
161
 
172
- puts " [%2d] %60s %4d suites in %.4fs (%s %s)" % [
162
+ puts ' [%2d] %60s %4d suites in %.4fs (%s %s)' % [
173
163
  worker.num,
174
164
  worker.summary,
175
165
  worker.suites.size,
@@ -181,16 +171,16 @@ module TestQueue
181
171
 
182
172
  unless @failures.empty?
183
173
  puts
184
- puts "==> Failures"
174
+ puts '==> Failures'
185
175
  puts
186
176
  puts @failures
187
177
  end
188
178
 
189
- if !relay?
179
+ unless relay?
190
180
  unless @discovered_suites.empty?
191
181
  estatus += 1
192
182
  puts
193
- puts "The following suites were discovered but were not run:"
183
+ puts 'The following suites were discovered but were not run:'
194
184
  puts
195
185
 
196
186
  @discovered_suites.sort.each do |suite_name, path|
@@ -200,7 +190,7 @@ module TestQueue
200
190
  unless unassigned_suites.empty?
201
191
  estatus += 1
202
192
  puts
203
- puts "The following suites were not discovered but were run anyway:"
193
+ puts 'The following suites were not discovered but were run anyway:'
204
194
  puts
205
195
  unassigned_suites.sort.each do |suite_name, path|
206
196
  puts "#{suite_name} - #{path}"
@@ -209,7 +199,7 @@ module TestQueue
209
199
  unless misrun_suites.empty?
210
200
  estatus += 1
211
201
  puts
212
- puts "The following suites were run on the wrong workers:"
202
+ puts 'The following suites were run on the wrong workers:'
213
203
  puts
214
204
  misrun_suites.each do |suite_name, path, target_host, target_pid, actual_host, actual_pid|
215
205
  puts "#{suite_name} - #{path}: #{actual_host} (#{actual_pid}) - assigned to #{target_host} (#{target_pid})"
@@ -223,7 +213,7 @@ module TestQueue
223
213
 
224
214
  summarize
225
215
 
226
- estatus = @completed.inject(0){ |s, worker| s + (worker.status.exitstatus || 1)}
216
+ estatus = @completed.inject(0) { |s, worker| s + (worker.status.exitstatus || 1) }
227
217
  [estatus, 255].min
228
218
  end
229
219
 
@@ -231,8 +221,7 @@ module TestQueue
231
221
  end
232
222
 
233
223
  def stats_file
234
- ENV['TEST_QUEUE_STATS'] ||
235
- '.test_queue_stats'
224
+ ENV['TEST_QUEUE_STATS'] || '.test_queue_stats'
236
225
  end
237
226
 
238
227
  def execute_internal
@@ -250,19 +239,19 @@ module TestQueue
250
239
  end
251
240
 
252
241
  def start_master
253
- if !relay?
242
+ unless relay?
254
243
  if @socket =~ /\A(?:(.+):)?(\d+)\z/
255
244
  address = $1 || '0.0.0.0'
256
245
  port = $2.to_i
257
- @socket = "#$1:#$2"
246
+ @socket = "#{$1}:#{$2}"
258
247
  @server = TCPServer.new(address, port)
259
248
  else
260
- FileUtils.rm(@socket) if File.exist?(@socket)
249
+ FileUtils.rm_f(@socket)
261
250
  @server = UNIXServer.new(@socket)
262
251
  end
263
252
  end
264
253
 
265
- desc = "test-queue master (#{relay?? "relaying to #{@relay}" : @socket})"
254
+ desc = "test-queue master (#{relay? ? "relaying to #{@relay}" : @socket})"
266
255
  puts "Starting #{desc}"
267
256
  $0 = "#{desc} - #{@procline}"
268
257
  end
@@ -271,19 +260,19 @@ module TestQueue
271
260
  return unless relay?
272
261
 
273
262
  sock = connect_to_relay
274
- message = @remote_master_message ? " #{@remote_master_message}" : ""
275
- message.gsub!(/(\r|\n)/, "") # Our "protocol" is newline-separated
263
+ message = @remote_master_message ? " #{@remote_master_message}" : ''
264
+ message = message.gsub(/(\r|\n)/, '') # Our "protocol" is newline-separated
276
265
  sock.puts("TOKEN=#{@run_token}")
277
266
  sock.puts("REMOTE MASTER #{@concurrency} #{Socket.gethostname} #{message}")
278
267
  response = sock.gets.strip
279
- unless response == "OK"
280
- STDERR.puts "*** Got non-OK response from master: #{response}"
268
+ unless response == 'OK'
269
+ warn "*** Got non-OK response from master: #{response}"
281
270
  sock.close
282
271
  exit! 1
283
272
  end
284
273
  sock.close
285
274
  rescue Errno::ECONNREFUSED
286
- STDERR.puts "*** Unable to connect to relay #{@relay}. Aborting.."
275
+ warn "*** Unable to connect to relay #{@relay}. Aborting..."
287
276
  exit! 1
288
277
  end
289
278
 
@@ -297,12 +286,12 @@ module TestQueue
297
286
 
298
287
  def spawn_workers
299
288
  @concurrency.times do |i|
300
- num = i+1
289
+ num = i + 1
301
290
 
302
291
  pid = fork do
303
- @server.close if @server
292
+ @server&.close
304
293
 
305
- iterator = Iterator.new(@test_framework, relay?? @relay : @socket, method(:around_filter), early_failure_limit: @early_failure_limit, run_token: @run_token)
294
+ iterator = Iterator.new(@test_framework, relay? ? @relay : @socket, method(:around_filter), early_failure_limit: @early_failure_limit, run_token: @run_token)
306
295
  after_fork_internal(num, iterator)
307
296
  ret = run_worker(iterator) || 0
308
297
  cleanup_worker
@@ -324,12 +313,12 @@ module TestQueue
324
313
 
325
314
  @discovering_suites_pid = fork do
326
315
  terminate = false
327
- Signal.trap("INT") { terminate = true }
316
+ Signal.trap('INT') { terminate = true }
328
317
 
329
- $0 = "test-queue suite discovery process"
318
+ $0 = 'test-queue suite discovery process'
330
319
 
331
320
  @test_framework.all_suite_files.each do |path|
332
- @test_framework.suites_from_file(path).each do |suite_name, suite|
321
+ @test_framework.suites_from_file(path).each do |suite_name, _suite|
333
322
  Kernel.exit!(0) if terminate
334
323
 
335
324
  @server.connect_address.connect do |sock|
@@ -344,13 +333,9 @@ module TestQueue
344
333
  end
345
334
 
346
335
  def awaiting_suites?
347
- case
348
- when @awaited_suites.any?
349
- # We're waiting to find all the allowlisted suites so we can run them
350
- # in the correct order.
351
- true
352
- when @queue.empty? && !!@discovering_suites_pid
353
- # We don't have any suites yet, but we're working on it.
336
+ # We're waiting to find all the allowlisted suites so we can run them in the correct order.
337
+ # Or we don't have any suites yet, but we're working on it.
338
+ if @awaited_suites.any? || @queue.empty? && !!@discovering_suites_pid
354
339
  true
355
340
  else
356
341
  # It's fine to run any queued suites now.
@@ -379,9 +364,9 @@ module TestQueue
379
364
  if @awaited_suites.delete?(suite_name) && @awaited_suites.empty?
380
365
  # We've found all the allowlisted suites. Sort the queue to match the
381
366
  # allowlist.
382
- @queue.sort_by! { |suite_name, path| @allowlist.index(suite_name) }
367
+ @queue.sort_by! { |queued_suite_name, _path| @allowlist.index(queued_suite_name) }
383
368
 
384
- kill_suite_discovery_process("INT")
369
+ kill_suite_discovery_process('INT')
385
370
  end
386
371
  end
387
372
 
@@ -396,7 +381,7 @@ module TestQueue
396
381
 
397
382
  $0 = "test-queue worker [#{num}]"
398
383
  puts
399
- puts "==> Starting #$0 (#{Process.pid} on #{Socket.gethostname}) - iterating over #{iterator.sock}"
384
+ puts "==> Starting #{$0} (#{Process.pid} on #{Socket.gethostname}) - iterating over #{iterator.sock}"
400
385
  puts
401
386
 
402
387
  after_fork(num)
@@ -408,7 +393,7 @@ module TestQueue
408
393
  def prepare(concurrency)
409
394
  end
410
395
 
411
- def around_filter(suite)
396
+ def around_filter(_suite)
412
397
  yield
413
398
  end
414
399
 
@@ -425,7 +410,7 @@ module TestQueue
425
410
  puts " #{item.inspect}"
426
411
  end
427
412
 
428
- return 0 # exit status
413
+ 0 # exit status
429
414
  end
430
415
 
431
416
  def cleanup_worker
@@ -436,7 +421,7 @@ module TestQueue
436
421
  worker.failure_output = ''
437
422
  end
438
423
 
439
- def reap_workers(blocking=true)
424
+ def reap_workers(blocking = true)
440
425
  @workers.delete_if do |_, worker|
441
426
  if Process.waitpid(worker.pid, blocking ? 0 : Process::WNOHANG).nil?
442
427
  next false
@@ -455,35 +440,37 @@ module TestQueue
455
440
 
456
441
  def collect_worker_data(worker)
457
442
  if File.exist?(file = "/tmp/test_queue_worker_#{worker.pid}_output")
458
- worker.output = IO.binread(file)
443
+ worker.output = File.binread(file)
459
444
  FileUtils.rm(file)
460
445
  end
461
446
 
462
447
  if File.exist?(file = "/tmp/test_queue_worker_#{worker.pid}_suites")
463
- worker.suites.replace(Marshal.load(IO.binread(file)))
448
+ worker.suites.replace(Marshal.load(File.binread(file)))
464
449
  FileUtils.rm(file)
465
450
  end
466
451
  end
467
452
 
468
453
  def worker_completed(worker)
469
454
  return if @aborting
455
+
470
456
  @completed << worker
471
457
  puts worker.output if ENV['TEST_QUEUE_VERBOSE'] || worker.status.exitstatus != 0
472
458
  end
473
459
 
474
460
  def distribute_queue
475
461
  return if relay?
462
+
476
463
  remote_workers = 0
477
464
 
478
465
  until !awaiting_suites? && @queue.empty? && remote_workers == 0
479
466
  queue_status(@start_time, @queue.size, @workers.size, remote_workers)
480
467
 
481
- if status = reap_suite_discovery_process(false)
482
- abort("Discovering suites failed.") unless status.success?
483
- abort("Failed to discover #{@awaited_suites.sort.join(", ")} specified in TEST_QUEUE_FORCE") if @awaited_suites.any?
468
+ if (status = reap_suite_discovery_process(false))
469
+ abort('Discovering suites failed.') unless status.success?
470
+ abort("Failed to discover #{@awaited_suites.sort.join(', ')} specified in TEST_QUEUE_FORCE") if @awaited_suites.any?
484
471
  end
485
472
 
486
- if IO.select([@server], nil, nil, 0.1).nil?
473
+ if @server.wait_readable(0.1).nil?
487
474
  reap_workers(false) # check for worker deaths
488
475
  else
489
476
  sock = @server.accept
@@ -493,8 +480,8 @@ module TestQueue
493
480
  token = token[TOKEN_REGEX, 1]
494
481
  # If we have a remote master from a different test run, respond with "WRONG RUN", and it will consider the test run done.
495
482
  if token != @run_token
496
- message = token.nil? ? "Worker sent no token to master" : "Worker from run #{token} connected to master"
497
- STDERR.puts "*** #{message} for run #{@run_token}; ignoring."
483
+ message = token.nil? ? 'Worker sent no token to master' : "Worker from run #{token} connected to master"
484
+ warn "*** #{message} for run #{@run_token}; ignoring."
498
485
  sock.write("WRONG RUN\n")
499
486
  next
500
487
  end
@@ -504,13 +491,13 @@ module TestQueue
504
491
  hostname = $1
505
492
  pid = Integer($2)
506
493
  if awaiting_suites?
507
- sock.write(Marshal.dump("WAIT"))
508
- elsif obj = @queue.shift
494
+ sock.write(Marshal.dump('WAIT'))
495
+ elsif (obj = @queue.shift)
509
496
  data = Marshal.dump(obj)
510
497
  sock.write(data)
511
498
  @assignments[obj] = [hostname, pid]
512
499
  end
513
- when /\AREMOTE MASTER (\d+) ([\w\.-]+)(?: (.+))?/
500
+ when /\AREMOTE MASTER (\d+) ([\w.-]+)(?: (.+))?/
514
501
  num = $1.to_i
515
502
  remote_master = $2
516
503
  remote_master_message = $3
@@ -518,9 +505,9 @@ module TestQueue
518
505
  sock.write("OK\n")
519
506
  remote_workers += num
520
507
 
521
- message = "*** #{num} workers connected from #{remote_master} after #{Time.now-@start_time}s"
522
- message << " " + remote_master_message if remote_master_message
523
- STDERR.puts message
508
+ message = "*** #{num} workers connected from #{remote_master} after #{Time.now - @start_time}s"
509
+ message += " #{remote_master_message}" if remote_master_message
510
+ warn message
524
511
  when /\AWORKER (\d+)/
525
512
  data = sock.read($1.to_i)
526
513
  worker = Marshal.load(data)
@@ -534,7 +521,7 @@ module TestQueue
534
521
  # stop everything immediately and report the results.
535
522
  break
536
523
  else
537
- STDERR.puts("Ignoring unrecognized command: \"#{cmd}\"")
524
+ warn("Ignoring unrecognized command: \"#{cmd}\"")
538
525
  end
539
526
  sock.close
540
527
  end
@@ -557,7 +544,8 @@ module TestQueue
557
544
  sock = TCPSocket.new(*@relay.split(':'))
558
545
  rescue Errno::ECONNREFUSED => e
559
546
  raise e if Time.now - start > @relay_connection_timeout
560
- puts "Master not yet available, sleeping..."
547
+
548
+ puts 'Master not yet available, sleeping...'
561
549
  sleep 0.5
562
550
  end
563
551
  end
@@ -573,7 +561,7 @@ module TestQueue
573
561
  sock.puts("WORKER #{data.bytesize}")
574
562
  sock.write(data)
575
563
  ensure
576
- sock.close if sock
564
+ sock&.close
577
565
  end
578
566
 
579
567
  def kill_subprocesses
@@ -582,21 +570,23 @@ module TestQueue
582
570
  end
583
571
 
584
572
  def kill_workers
585
- @workers.each do |pid, worker|
573
+ @workers.each do |pid, _worker|
586
574
  Process.kill 'KILL', pid
587
575
  end
588
576
 
589
577
  reap_workers
590
578
  end
591
579
 
592
- def kill_suite_discovery_process(signal="KILL")
580
+ def kill_suite_discovery_process(signal = 'KILL')
593
581
  return unless @discovering_suites_pid
582
+
594
583
  Process.kill signal, @discovering_suites_pid
595
584
  reap_suite_discovery_process
596
585
  end
597
586
 
598
- def reap_suite_discovery_process(blocking=true)
587
+ def reap_suite_discovery_process(blocking = true)
599
588
  return unless @discovering_suites_pid
589
+
600
590
  _, status = Process.waitpid2(@discovering_suites_pid, blocking ? 0 : Process::WNOHANG)
601
591
  return unless status
602
592
 
@@ -612,7 +602,7 @@ module TestQueue
612
602
  def abort(message)
613
603
  @aborting = true
614
604
  kill_subprocesses
615
- Kernel::abort("Aborting: #{message}")
605
+ Kernel.abort("Aborting: #{message}")
616
606
  end
617
607
 
618
608
  # Subclasses can override to monitor the status of the queue.