test-queue 0.7.0 → 0.9.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.
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 +9 -9
  12. data/lib/test_queue/runner/minitest5.rb +37 -22
  13. data/lib/test_queue/runner/puppet_lint.rb +6 -4
  14. data/lib/test_queue/runner/rspec.rb +16 -10
  15. data/lib/test_queue/runner/{rspec3.rb → rspec_ext.rb} +11 -11
  16. data/lib/test_queue/runner/testunit.rb +6 -3
  17. data/lib/test_queue/runner.rb +82 -98
  18. data/lib/test_queue/stats.rb +17 -13
  19. data/lib/test_queue/test_framework.rb +2 -0
  20. data/lib/test_queue/version.rb +5 -0
  21. data/lib/test_queue.rb +1 -5
  22. metadata +8 -47
  23. data/.github/workflows/test.yml +0 -94
  24. data/.gitignore +0 -7
  25. data/Appraisals +0 -43
  26. data/Gemfile +0 -7
  27. data/Rakefile +0 -14
  28. data/gemfiles/cucumber1_3.gemfile +0 -9
  29. data/gemfiles/cucumber2_4.gemfile +0 -9
  30. data/gemfiles/minitest4.gemfile +0 -7
  31. data/gemfiles/minitest5.gemfile +0 -7
  32. data/gemfiles/rspec2.gemfile +0 -8
  33. data/gemfiles/rspec3.gemfile +0 -7
  34. data/gemfiles/rspec4.gemfile +0 -11
  35. data/gemfiles/testunit.gemfile +0 -7
  36. data/lib/test_queue/runner/minitest4.rb +0 -88
  37. data/lib/test_queue/runner/rspec2.rb +0 -44
  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,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,26 @@ 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"]
109
- end
91
+ @socket = socket || ENV['TEST_QUEUE_SOCKET'] || "/tmp/test_queue_#{$$}_#{object_id}.sock"
92
+ @relay = relay || ENV['TEST_QUEUE_RELAY']
93
+ @remote_master_message = ENV['TEST_QUEUE_REMOTE_MASTER_MESSAGE'] if ENV.key?('TEST_QUEUE_REMOTE_MASTER_MESSAGE')
110
94
 
111
95
  if @relay == @socket
112
- STDERR.puts "*** Detected TEST_QUEUE_RELAY == TEST_QUEUE_SOCKET. Disabling relay mode."
96
+ warn '*** Detected TEST_QUEUE_RELAY == TEST_QUEUE_SOCKET. Disabling relay mode.'
113
97
  @relay = nil
114
98
  elsif @relay
115
99
  @queue = []
@@ -144,7 +128,7 @@ module TestQueue
144
128
 
145
129
  def summarize_internal
146
130
  puts
147
- puts "==> Summary (#{@completed.size} workers in %.4fs)" % (Time.now-@start_time)
131
+ puts "==> Summary (#{@completed.size} workers in %.4fs)" % (Time.now - @start_time)
148
132
  puts
149
133
 
150
134
  estatus = 0
@@ -167,9 +151,9 @@ module TestQueue
167
151
 
168
152
  summarize_worker(worker)
169
153
 
170
- @failures << worker.failure_output if worker.failure_output
154
+ @failures += worker.failure_output if worker.failure_output
171
155
 
172
- puts " [%2d] %60s %4d suites in %.4fs (%s %s)" % [
156
+ puts ' [%2d] %60s %4d suites in %.4fs (%s %s)' % [
173
157
  worker.num,
174
158
  worker.summary,
175
159
  worker.suites.size,
@@ -181,16 +165,16 @@ module TestQueue
181
165
 
182
166
  unless @failures.empty?
183
167
  puts
184
- puts "==> Failures"
168
+ puts '==> Failures'
185
169
  puts
186
170
  puts @failures
187
171
  end
188
172
 
189
- if !relay?
173
+ unless relay?
190
174
  unless @discovered_suites.empty?
191
175
  estatus += 1
192
176
  puts
193
- puts "The following suites were discovered but were not run:"
177
+ puts 'The following suites were discovered but were not run:'
194
178
  puts
195
179
 
196
180
  @discovered_suites.sort.each do |suite_name, path|
@@ -200,7 +184,7 @@ module TestQueue
200
184
  unless unassigned_suites.empty?
201
185
  estatus += 1
202
186
  puts
203
- puts "The following suites were not discovered but were run anyway:"
187
+ puts 'The following suites were not discovered but were run anyway:'
204
188
  puts
205
189
  unassigned_suites.sort.each do |suite_name, path|
206
190
  puts "#{suite_name} - #{path}"
@@ -209,7 +193,7 @@ module TestQueue
209
193
  unless misrun_suites.empty?
210
194
  estatus += 1
211
195
  puts
212
- puts "The following suites were run on the wrong workers:"
196
+ puts 'The following suites were run on the wrong workers:'
213
197
  puts
214
198
  misrun_suites.each do |suite_name, path, target_host, target_pid, actual_host, actual_pid|
215
199
  puts "#{suite_name} - #{path}: #{actual_host} (#{actual_pid}) - assigned to #{target_host} (#{target_pid})"
@@ -223,7 +207,7 @@ module TestQueue
223
207
 
224
208
  summarize
225
209
 
226
- estatus = @completed.inject(0){ |s, worker| s + (worker.status.exitstatus || 1)}
210
+ estatus = @completed.inject(0) { |s, worker| s + (worker.status.exitstatus || 1) }
227
211
  [estatus, 255].min
228
212
  end
229
213
 
@@ -231,8 +215,7 @@ module TestQueue
231
215
  end
232
216
 
233
217
  def stats_file
234
- ENV['TEST_QUEUE_STATS'] ||
235
- '.test_queue_stats'
218
+ ENV['TEST_QUEUE_STATS'] || '.test_queue_stats'
236
219
  end
237
220
 
238
221
  def execute_internal
@@ -250,19 +233,19 @@ module TestQueue
250
233
  end
251
234
 
252
235
  def start_master
253
- if !relay?
236
+ unless relay?
254
237
  if @socket =~ /\A(?:(.+):)?(\d+)\z/
255
238
  address = $1 || '0.0.0.0'
256
239
  port = $2.to_i
257
- @socket = "#$1:#$2"
240
+ @socket = "#{$1}:#{$2}"
258
241
  @server = TCPServer.new(address, port)
259
242
  else
260
- FileUtils.rm(@socket) if File.exist?(@socket)
243
+ FileUtils.rm_f(@socket)
261
244
  @server = UNIXServer.new(@socket)
262
245
  end
263
246
  end
264
247
 
265
- desc = "test-queue master (#{relay?? "relaying to #{@relay}" : @socket})"
248
+ desc = "test-queue master (#{relay? ? "relaying to #{@relay}" : @socket})"
266
249
  puts "Starting #{desc}"
267
250
  $0 = "#{desc} - #{@procline}"
268
251
  end
@@ -271,19 +254,19 @@ module TestQueue
271
254
  return unless relay?
272
255
 
273
256
  sock = connect_to_relay
274
- message = @remote_master_message ? " #{@remote_master_message}" : ""
275
- message.gsub!(/(\r|\n)/, "") # Our "protocol" is newline-separated
257
+ message = @remote_master_message ? " #{@remote_master_message}" : ''
258
+ message = message.gsub(/(\r|\n)/, '') # Our "protocol" is newline-separated
276
259
  sock.puts("TOKEN=#{@run_token}")
277
260
  sock.puts("REMOTE MASTER #{@concurrency} #{Socket.gethostname} #{message}")
278
261
  response = sock.gets.strip
279
- unless response == "OK"
280
- STDERR.puts "*** Got non-OK response from master: #{response}"
262
+ unless response == 'OK'
263
+ warn "*** Got non-OK response from master: #{response}"
281
264
  sock.close
282
265
  exit! 1
283
266
  end
284
267
  sock.close
285
268
  rescue Errno::ECONNREFUSED
286
- STDERR.puts "*** Unable to connect to relay #{@relay}. Aborting.."
269
+ warn "*** Unable to connect to relay #{@relay}. Aborting..."
287
270
  exit! 1
288
271
  end
289
272
 
@@ -297,12 +280,12 @@ module TestQueue
297
280
 
298
281
  def spawn_workers
299
282
  @concurrency.times do |i|
300
- num = i+1
283
+ num = i + 1
301
284
 
302
285
  pid = fork do
303
- @server.close if @server
286
+ @server&.close
304
287
 
305
- iterator = Iterator.new(@test_framework, relay?? @relay : @socket, method(:around_filter), early_failure_limit: @early_failure_limit, run_token: @run_token)
288
+ iterator = Iterator.new(@test_framework, relay? ? @relay : @socket, method(:around_filter), early_failure_limit: @early_failure_limit, run_token: @run_token)
306
289
  after_fork_internal(num, iterator)
307
290
  ret = run_worker(iterator) || 0
308
291
  cleanup_worker
@@ -324,12 +307,12 @@ module TestQueue
324
307
 
325
308
  @discovering_suites_pid = fork do
326
309
  terminate = false
327
- Signal.trap("INT") { terminate = true }
310
+ Signal.trap('INT') { terminate = true }
328
311
 
329
- $0 = "test-queue suite discovery process"
312
+ $0 = 'test-queue suite discovery process'
330
313
 
331
314
  @test_framework.all_suite_files.each do |path|
332
- @test_framework.suites_from_file(path).each do |suite_name, suite|
315
+ @test_framework.suites_from_file(path).each do |suite_name, _suite|
333
316
  Kernel.exit!(0) if terminate
334
317
 
335
318
  @server.connect_address.connect do |sock|
@@ -344,13 +327,9 @@ module TestQueue
344
327
  end
345
328
 
346
329
  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.
330
+ # We're waiting to find all the allowlisted suites so we can run them in the correct order.
331
+ # Or we don't have any suites yet, but we're working on it.
332
+ if @awaited_suites.any? || @queue.empty? && !!@discovering_suites_pid
354
333
  true
355
334
  else
356
335
  # It's fine to run any queued suites now.
@@ -379,9 +358,9 @@ module TestQueue
379
358
  if @awaited_suites.delete?(suite_name) && @awaited_suites.empty?
380
359
  # We've found all the allowlisted suites. Sort the queue to match the
381
360
  # allowlist.
382
- @queue.sort_by! { |suite_name, path| @allowlist.index(suite_name) }
361
+ @queue.sort_by! { |queued_suite_name, _path| @allowlist.index(queued_suite_name) }
383
362
 
384
- kill_suite_discovery_process("INT")
363
+ kill_suite_discovery_process('INT')
385
364
  end
386
365
  end
387
366
 
@@ -396,7 +375,7 @@ module TestQueue
396
375
 
397
376
  $0 = "test-queue worker [#{num}]"
398
377
  puts
399
- puts "==> Starting #$0 (#{Process.pid} on #{Socket.gethostname}) - iterating over #{iterator.sock}"
378
+ puts "==> Starting #{$0} (#{Process.pid} on #{Socket.gethostname}) - iterating over #{iterator.sock}"
400
379
  puts
401
380
 
402
381
  after_fork(num)
@@ -408,7 +387,7 @@ module TestQueue
408
387
  def prepare(concurrency)
409
388
  end
410
389
 
411
- def around_filter(suite)
390
+ def around_filter(_suite)
412
391
  yield
413
392
  end
414
393
 
@@ -425,7 +404,7 @@ module TestQueue
425
404
  puts " #{item.inspect}"
426
405
  end
427
406
 
428
- return 0 # exit status
407
+ 0 # exit status
429
408
  end
430
409
 
431
410
  def cleanup_worker
@@ -436,7 +415,7 @@ module TestQueue
436
415
  worker.failure_output = ''
437
416
  end
438
417
 
439
- def reap_workers(blocking=true)
418
+ def reap_workers(blocking = true)
440
419
  @workers.delete_if do |_, worker|
441
420
  if Process.waitpid(worker.pid, blocking ? 0 : Process::WNOHANG).nil?
442
421
  next false
@@ -455,35 +434,37 @@ module TestQueue
455
434
 
456
435
  def collect_worker_data(worker)
457
436
  if File.exist?(file = "/tmp/test_queue_worker_#{worker.pid}_output")
458
- worker.output = IO.binread(file)
437
+ worker.output = File.binread(file)
459
438
  FileUtils.rm(file)
460
439
  end
461
440
 
462
441
  if File.exist?(file = "/tmp/test_queue_worker_#{worker.pid}_suites")
463
- worker.suites.replace(Marshal.load(IO.binread(file)))
442
+ worker.suites.replace(Marshal.load(File.binread(file)))
464
443
  FileUtils.rm(file)
465
444
  end
466
445
  end
467
446
 
468
447
  def worker_completed(worker)
469
448
  return if @aborting
449
+
470
450
  @completed << worker
471
451
  puts worker.output if ENV['TEST_QUEUE_VERBOSE'] || worker.status.exitstatus != 0
472
452
  end
473
453
 
474
454
  def distribute_queue
475
455
  return if relay?
456
+
476
457
  remote_workers = 0
477
458
 
478
459
  until !awaiting_suites? && @queue.empty? && remote_workers == 0
479
460
  queue_status(@start_time, @queue.size, @workers.size, remote_workers)
480
461
 
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?
462
+ if (status = reap_suite_discovery_process(false))
463
+ abort('Discovering suites failed.') unless status.success?
464
+ abort("Failed to discover #{@awaited_suites.sort.join(', ')} specified in TEST_QUEUE_FORCE") if @awaited_suites.any?
484
465
  end
485
466
 
486
- if IO.select([@server], nil, nil, 0.1).nil?
467
+ if @server.wait_readable(0.1).nil?
487
468
  reap_workers(false) # check for worker deaths
488
469
  else
489
470
  sock = @server.accept
@@ -493,8 +474,8 @@ module TestQueue
493
474
  token = token[TOKEN_REGEX, 1]
494
475
  # If we have a remote master from a different test run, respond with "WRONG RUN", and it will consider the test run done.
495
476
  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."
477
+ message = token.nil? ? 'Worker sent no token to master' : "Worker from run #{token} connected to master"
478
+ warn "*** #{message} for run #{@run_token}; ignoring."
498
479
  sock.write("WRONG RUN\n")
499
480
  next
500
481
  end
@@ -504,13 +485,13 @@ module TestQueue
504
485
  hostname = $1
505
486
  pid = Integer($2)
506
487
  if awaiting_suites?
507
- sock.write(Marshal.dump("WAIT"))
508
- elsif obj = @queue.shift
488
+ sock.write(Marshal.dump('WAIT'))
489
+ elsif (obj = @queue.shift)
509
490
  data = Marshal.dump(obj)
510
491
  sock.write(data)
511
492
  @assignments[obj] = [hostname, pid]
512
493
  end
513
- when /\AREMOTE MASTER (\d+) ([\w\.-]+)(?: (.+))?/
494
+ when /\AREMOTE MASTER (\d+) ([\w.-]+)(?: (.+))?/
514
495
  num = $1.to_i
515
496
  remote_master = $2
516
497
  remote_master_message = $3
@@ -518,9 +499,9 @@ module TestQueue
518
499
  sock.write("OK\n")
519
500
  remote_workers += num
520
501
 
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
502
+ message = "*** #{num} workers connected from #{remote_master} after #{Time.now - @start_time}s"
503
+ message += " #{remote_master_message}" if remote_master_message
504
+ warn message
524
505
  when /\AWORKER (\d+)/
525
506
  data = sock.read($1.to_i)
526
507
  worker = Marshal.load(data)
@@ -534,7 +515,7 @@ module TestQueue
534
515
  # stop everything immediately and report the results.
535
516
  break
536
517
  else
537
- STDERR.puts("Ignoring unrecognized command: \"#{cmd}\"")
518
+ warn("Ignoring unrecognized command: \"#{cmd}\"")
538
519
  end
539
520
  sock.close
540
521
  end
@@ -557,7 +538,8 @@ module TestQueue
557
538
  sock = TCPSocket.new(*@relay.split(':'))
558
539
  rescue Errno::ECONNREFUSED => e
559
540
  raise e if Time.now - start > @relay_connection_timeout
560
- puts "Master not yet available, sleeping..."
541
+
542
+ puts 'Master not yet available, sleeping...'
561
543
  sleep 0.5
562
544
  end
563
545
  end
@@ -573,7 +555,7 @@ module TestQueue
573
555
  sock.puts("WORKER #{data.bytesize}")
574
556
  sock.write(data)
575
557
  ensure
576
- sock.close if sock
558
+ sock&.close
577
559
  end
578
560
 
579
561
  def kill_subprocesses
@@ -582,21 +564,23 @@ module TestQueue
582
564
  end
583
565
 
584
566
  def kill_workers
585
- @workers.each do |pid, worker|
567
+ @workers.each do |pid, _worker|
586
568
  Process.kill 'KILL', pid
587
569
  end
588
570
 
589
571
  reap_workers
590
572
  end
591
573
 
592
- def kill_suite_discovery_process(signal="KILL")
574
+ def kill_suite_discovery_process(signal = 'KILL')
593
575
  return unless @discovering_suites_pid
576
+
594
577
  Process.kill signal, @discovering_suites_pid
595
578
  reap_suite_discovery_process
596
579
  end
597
580
 
598
- def reap_suite_discovery_process(blocking=true)
581
+ def reap_suite_discovery_process(blocking = true)
599
582
  return unless @discovering_suites_pid
583
+
600
584
  _, status = Process.waitpid2(@discovering_suites_pid, blocking ? 0 : Process::WNOHANG)
601
585
  return unless status
602
586
 
@@ -612,7 +596,7 @@ module TestQueue
612
596
  def abort(message)
613
597
  @aborting = true
614
598
  kill_subprocesses
615
- Kernel::abort("Aborting: #{message}")
599
+ Kernel.abort("Aborting: #{message}")
616
600
  end
617
601
 
618
602
  # Subclasses can override to monitor the status of the queue.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TestQueue
2
4
  class Stats
3
5
  class Suite
@@ -19,17 +21,17 @@ module TestQueue
19
21
  duration == other.duration &&
20
22
  last_seen_at == other.last_seen_at
21
23
  end
22
- alias_method :eql?, :==
24
+ alias eql? ==
23
25
 
24
26
  def to_h
25
- { :name => name, :path => path, :duration => duration, :last_seen_at => last_seen_at.to_i }
27
+ { name: name, path: path, duration: duration, last_seen_at: last_seen_at.to_i }
26
28
  end
27
29
 
28
30
  def self.from_hash(hash)
29
- self.new(hash.fetch(:name),
30
- hash.fetch(:path),
31
- hash.fetch(:duration),
32
- Time.at(hash.fetch(:last_seen_at)))
31
+ new(hash.fetch(:name),
32
+ hash.fetch(:path),
33
+ hash.fetch(:duration),
34
+ Time.at(hash.fetch(:last_seen_at)))
33
35
  end
34
36
  end
35
37
 
@@ -56,7 +58,7 @@ module TestQueue
56
58
  def save
57
59
  prune
58
60
 
59
- File.open(@path, "wb") do |f|
61
+ File.open(@path, 'wb') do |f|
60
62
  Marshal.dump(to_h, f)
61
63
  end
62
64
  end
@@ -68,15 +70,17 @@ module TestQueue
68
70
  def to_h
69
71
  suites = @suites.each_value.map(&:to_h)
70
72
 
71
- { :version => CURRENT_VERSION, :suites => suites }
73
+ { version: CURRENT_VERSION, suites: suites }
72
74
  end
73
75
 
74
76
  def load
75
77
  data = begin
76
- File.open(@path, "rb") { |f| Marshal.load(f) }
77
- rescue Errno::ENOENT, EOFError, TypeError, ArgumentError
78
- end
79
- return unless data && data.is_a?(Hash) && data[:version] == CURRENT_VERSION
78
+ File.open(@path, 'rb') { |f| Marshal.load(f) }
79
+ rescue Errno::ENOENT, EOFError, TypeError, ArgumentError
80
+ # noop
81
+ end
82
+ return unless data.is_a?(Hash) && data[:version] == CURRENT_VERSION
83
+
80
84
  data[:suites].each do |suite_hash|
81
85
  suite = Suite.from_hash(suite_hash)
82
86
  @suites[suite.name] = suite
@@ -87,7 +91,7 @@ module TestQueue
87
91
 
88
92
  def prune
89
93
  earliest = Time.now - EIGHT_DAYS_S
90
- @suites.delete_if do |name, suite|
94
+ @suites.delete_if do |_name, suite|
91
95
  suite.last_seen_at < earliest
92
96
  end
93
97
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TestQueue
2
4
  # This class provides an abstraction over the various test frameworks we
3
5
  # support. The framework-specific subclasses are defined in the various
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TestQueue
4
+ VERSION = '0.9.0'
5
+ end
data/lib/test_queue.rb CHANGED
@@ -1,8 +1,4 @@
1
- if !IO.respond_to?(:binread)
2
- class << IO
3
- alias :binread :read
4
- end
5
- end
1
+ # frozen_string_literal: true
6
2
 
7
3
  require_relative 'test_queue/iterator'
8
4
  require_relative 'test_queue/runner'