minitest-parallel_fork 2.0.0 → 2.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG +4 -0
- data/README.rdoc +14 -0
- data/lib/minitest/parallel_fork/fail_fast.rb +2 -54
- data/lib/minitest/parallel_fork/halt.rb +55 -0
- data/lib/minitest/parallel_fork/interrupt.rb +45 -0
- data/lib/minitest/parallel_fork.rb +19 -15
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 617125ad38c5fbb98d110eb3374a6f4ffac5d95ffedfed197c6354e7b273d7ef
|
4
|
+
data.tar.gz: 7e4768a75b06806da43547902dc02c89ae793a907ea2dc0f00dc18a5bf69ec82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79d9a44f01350fe19f9e50cfdbef0957b692ddf2fc5322ba91d2ceadf3c0e6c091681e08c8c3b5b86f9115ae3ac80055aa9c5eea8e88f076be5d9b161a888e9d
|
7
|
+
data.tar.gz: e86395fb13775e0a4d11249639446ff64a5ca8743350f261cfc8f01b6b4416162e02d15b9977071f75801b95a4fe51a07832749e0493eeb78d67a2b90cd2d63c
|
data/CHANGELOG
CHANGED
data/README.rdoc
CHANGED
@@ -79,6 +79,20 @@ Note that minitest-parallel_fork uses suite-based parallelism, so tests will not
|
|
79
79
|
stop until one child has a failing test suite (test class that has a failing test
|
80
80
|
method), and other children are signaled and also stop processing.
|
81
81
|
|
82
|
+
== Interrupt Support
|
83
|
+
|
84
|
+
If you would like to run tests in parallel, but allow for shutting down children
|
85
|
+
when SIGINT is sent to the process, you can use:
|
86
|
+
|
87
|
+
RUBYOPT=-rminitest/parallel_fork/interrupt ruby spec_runner.rb
|
88
|
+
|
89
|
+
The first SIGINT to a process will ask the child processes to shut down gracefully
|
90
|
+
with SIGUSR1. The second SIGINT to a process will kill the child processes with
|
91
|
+
SIGKILL.
|
92
|
+
|
93
|
+
Note that if you use rake to run the specs, the second SIGINT may not be sent to
|
94
|
+
to the parent process, as rake does it's own SIGINT handling.
|
95
|
+
|
82
96
|
== ActiveRecord
|
83
97
|
|
84
98
|
To use this with Rails/ActiveRecord, you probably want to use hooks similar to:
|
@@ -1,69 +1,17 @@
|
|
1
|
+
require_relative 'halt'
|
1
2
|
require_relative '../parallel_fork'
|
2
3
|
|
3
4
|
module Minitest::ParalleForkFailFast
|
4
|
-
|
5
|
-
super
|
6
|
-
Signal.trap(:USR1) do
|
7
|
-
@parallel_fork_stop = true
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def parallel_fork_data_to_marshal
|
12
|
-
super << @parallel_fork_stop
|
13
|
-
end
|
14
|
-
|
15
|
-
def parallel_fork_data_from_marshal(data)
|
16
|
-
data = Marshal.load(data)
|
17
|
-
@parallel_fork_stop = true if data.pop
|
18
|
-
data
|
19
|
-
end
|
20
|
-
|
21
|
-
def parallel_fork_run_test_suites(suites, reporter, options)
|
22
|
-
suites.each do |suite|
|
23
|
-
parallel_fork_run_test_suite(suite, reporter, options)
|
24
|
-
|
25
|
-
# Fail fast if this child process had a failure,
|
26
|
-
# Or the USR1 signal was received indicating other child processes had a failure.
|
27
|
-
break if @parallel_fork_stop
|
28
|
-
end
|
29
|
-
end
|
5
|
+
include Minitest::ParallelForkHalt
|
30
6
|
|
31
7
|
def parallel_fork_run_test_suite(suite, reporter, options)
|
32
8
|
super
|
33
9
|
|
34
|
-
|
35
10
|
if parallel_fork_stat_reporter.results.any?{|r| !r.failure.is_a?(Minitest::Skip)}
|
36
11
|
# At least one failure or error, mark as failing fast
|
37
12
|
@parallel_fork_stop = true
|
38
13
|
end
|
39
14
|
end
|
40
|
-
|
41
|
-
def parallel_fork_child_data(data)
|
42
|
-
threads = {}
|
43
|
-
data.each{|pid, read| threads[pid] = Thread.new(read, &:read)}
|
44
|
-
results = []
|
45
|
-
|
46
|
-
while sleep(0.01) && !threads.empty?
|
47
|
-
threads.to_a.each do |pid, thread|
|
48
|
-
unless thread.alive?
|
49
|
-
threads.delete(pid)
|
50
|
-
results << parallel_fork_data_from_marshal(thread.value)
|
51
|
-
|
52
|
-
if @parallel_fork_stop
|
53
|
-
# If any child failed fast, signal other children to fail fast
|
54
|
-
threads.each_key do |pid|
|
55
|
-
Process.kill(:USR1, pid)
|
56
|
-
end
|
57
|
-
|
58
|
-
# Set a flag indicating that all child processes have been signaled
|
59
|
-
@parallel_fork_stop = :FINISHED
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
results
|
66
|
-
end
|
67
15
|
end
|
68
16
|
|
69
17
|
Minitest.singleton_class.prepend(Minitest::ParalleForkFailFast)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Minitest::ParallelForkHalt
|
2
|
+
def run_after_parallel_fork_hook(i)
|
3
|
+
super
|
4
|
+
Signal.trap(:USR1) do
|
5
|
+
@parallel_fork_stop = true
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def parallel_fork_data_to_marshal
|
10
|
+
super << @parallel_fork_stop
|
11
|
+
end
|
12
|
+
|
13
|
+
def parallel_fork_data_from_marshal(data)
|
14
|
+
data = Marshal.load(data)
|
15
|
+
@parallel_fork_stop = true if data.pop
|
16
|
+
data
|
17
|
+
end
|
18
|
+
|
19
|
+
def parallel_fork_run_test_suites(suites, reporter, options)
|
20
|
+
suites.each do |suite|
|
21
|
+
parallel_fork_run_test_suite(suite, reporter, options)
|
22
|
+
|
23
|
+
# Halt if this child process requested an exit,
|
24
|
+
# Or other child processes requested an exit.
|
25
|
+
break if @parallel_fork_stop
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def parallel_fork_child_data(data)
|
30
|
+
threads = {}
|
31
|
+
data.each{|pid, read| threads[pid] = Thread.new(read, &:read)}
|
32
|
+
results = []
|
33
|
+
|
34
|
+
while sleep(0.01) && !threads.empty?
|
35
|
+
threads.to_a.each do |pid, thread|
|
36
|
+
unless thread.alive?
|
37
|
+
threads.delete(pid)
|
38
|
+
results << parallel_fork_data_from_marshal(thread.value)
|
39
|
+
|
40
|
+
if @parallel_fork_stop
|
41
|
+
# If halt is requested, signal other children to halt
|
42
|
+
threads.each_key do |pid|
|
43
|
+
Process.kill(:USR1, pid)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Set a flag indicating that all child processes have been signaled
|
47
|
+
@parallel_fork_stop = :FINISHED
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
results
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'minitest'
|
2
|
+
|
3
|
+
require_relative 'halt'
|
4
|
+
require_relative '../parallel_fork'
|
5
|
+
|
6
|
+
module Minitest
|
7
|
+
@parallel_fork_child_pids = []
|
8
|
+
end
|
9
|
+
|
10
|
+
module Minitest::ParallelForkInterrupt
|
11
|
+
include Minitest::ParallelForkHalt
|
12
|
+
|
13
|
+
def run_before_parallel_fork_hook
|
14
|
+
Signal.trap(:INT) do
|
15
|
+
Signal.trap(:INT) do
|
16
|
+
parallel_fork_kill_all :KILL
|
17
|
+
end
|
18
|
+
$stderr.puts "\nInterrupted.\nExiting ...\nInterrupt again to exit immediately."
|
19
|
+
parallel_fork_kill_all :USR1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def run_after_parallel_fork_hook(i)
|
24
|
+
super
|
25
|
+
Signal.trap(:INT, 'IGNORE')
|
26
|
+
end
|
27
|
+
|
28
|
+
def parallel_fork_fork_child(i, suites, reporter, options)
|
29
|
+
res = super
|
30
|
+
@parallel_fork_child_pids << res[0]
|
31
|
+
res
|
32
|
+
end
|
33
|
+
|
34
|
+
def parallel_fork_kill_all(signal)
|
35
|
+
@parallel_fork_child_pids.each do |pid|
|
36
|
+
begin
|
37
|
+
Process.kill(signal, pid)
|
38
|
+
rescue Errno::ESRCH
|
39
|
+
# Process already terminated
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Minitest.singleton_class.prepend(Minitest::ParallelForkInterrupt)
|
@@ -81,23 +81,27 @@ class << Minitest
|
|
81
81
|
set_parallel_fork_stat_reporter(reporter)
|
82
82
|
run_before_parallel_fork_hook
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
84
|
+
parallel_fork_number.times.map do |i|
|
85
|
+
parallel_fork_fork_child(i, suites, reporter, options)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def parallel_fork_fork_child(i, suites, reporter, options)
|
90
|
+
read, write = IO.pipe.each{|io| io.binmode}
|
91
|
+
pid = Process.fork do
|
92
|
+
read.close
|
93
|
+
run_after_parallel_fork_hook(i)
|
94
|
+
|
95
|
+
p_suites = []
|
96
|
+
n = parallel_fork_number
|
97
|
+
suites.each_with_index{|s, j| p_suites << s if j % n == i}
|
98
|
+
parallel_fork_run_test_suites(p_suites, reporter, options)
|
99
|
+
|
100
|
+
write.write(Marshal.dump(parallel_fork_data_to_marshal))
|
98
101
|
write.close
|
99
|
-
[pid, read]
|
100
102
|
end
|
103
|
+
write.close
|
104
|
+
[pid, read]
|
101
105
|
end
|
102
106
|
|
103
107
|
def parallel_fork_child_data(data)
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitest-parallel_fork
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: minitest
|
@@ -63,15 +62,17 @@ email: code@jeremyevans.net
|
|
63
62
|
executables: []
|
64
63
|
extensions: []
|
65
64
|
extra_rdoc_files:
|
66
|
-
- README.rdoc
|
67
65
|
- CHANGELOG
|
68
66
|
- MIT-LICENSE
|
67
|
+
- README.rdoc
|
69
68
|
files:
|
70
69
|
- CHANGELOG
|
71
70
|
- MIT-LICENSE
|
72
71
|
- README.rdoc
|
73
72
|
- lib/minitest/parallel_fork.rb
|
74
73
|
- lib/minitest/parallel_fork/fail_fast.rb
|
74
|
+
- lib/minitest/parallel_fork/halt.rb
|
75
|
+
- lib/minitest/parallel_fork/interrupt.rb
|
75
76
|
homepage: http://github.com/jeremyevans/minitest-parallel_fork
|
76
77
|
licenses:
|
77
78
|
- MIT
|
@@ -80,7 +81,6 @@ metadata:
|
|
80
81
|
changelog_uri: https://github.com/jeremyevans/minitest-parallel_fork/blob/master/CHANGELOG
|
81
82
|
mailing_list_uri: https://github.com/jeremyevans/minitest-parallel_fork/discussions
|
82
83
|
source_code_uri: https://github.com/jeremyevans/minitest-parallel_fork
|
83
|
-
post_install_message:
|
84
84
|
rdoc_options:
|
85
85
|
- "--quiet"
|
86
86
|
- "--line-numbers"
|
@@ -102,8 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
requirements: []
|
105
|
-
rubygems_version: 3.
|
106
|
-
signing_key:
|
105
|
+
rubygems_version: 3.6.7
|
107
106
|
specification_version: 4
|
108
107
|
summary: Fork-based parallelization for minitest
|
109
108
|
test_files: []
|