test-queue 0.7.0 → 0.9.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 +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'