mutant 0.10.4 → 0.10.9
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/bin/mutant +0 -2
- data/lib/mutant.rb +7 -5
- data/lib/mutant/cli/command.rb +8 -6
- data/lib/mutant/cli/command/run.rb +23 -10
- data/lib/mutant/config.rb +80 -77
- data/lib/mutant/env.rb +14 -4
- data/lib/mutant/integration.rb +7 -10
- data/lib/mutant/integration/null.rb +0 -1
- data/lib/mutant/isolation.rb +11 -48
- data/lib/mutant/isolation/fork.rb +107 -40
- data/lib/mutant/isolation/none.rb +18 -5
- data/lib/mutant/license/subscription/commercial.rb +2 -3
- data/lib/mutant/license/subscription/opensource.rb +0 -1
- data/lib/mutant/matcher/config.rb +13 -0
- data/lib/mutant/matcher/method/instance.rb +0 -2
- data/lib/mutant/mutator/node/send.rb +1 -1
- data/lib/mutant/parallel.rb +0 -1
- data/lib/mutant/parallel/worker.rb +0 -2
- data/lib/mutant/reporter/cli.rb +0 -2
- data/lib/mutant/reporter/cli/printer/config.rb +9 -5
- data/lib/mutant/reporter/cli/printer/coverage_result.rb +19 -0
- data/lib/mutant/reporter/cli/printer/env_progress.rb +2 -0
- data/lib/mutant/reporter/cli/printer/isolation_result.rb +19 -35
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +4 -9
- data/lib/mutant/reporter/cli/printer/subject_result.rb +2 -2
- data/lib/mutant/result.rb +91 -30
- data/lib/mutant/runner/sink.rb +12 -5
- data/lib/mutant/timer.rb +60 -11
- data/lib/mutant/transform.rb +25 -21
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warnings.rb +0 -1
- data/lib/mutant/world.rb +67 -0
- metadata +12 -13
- data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -28
- data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -58
- data/lib/mutant/reporter/cli/printer/test_result.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2d4849ffe2057370e38c3718afe4cbbfcbfaf76b058c4c5364ff2a7475a3122
|
4
|
+
data.tar.gz: 6e9abc09f95b929c6ee5b1f09745aa7ce01cc66ab70aaa3e044f2da5b897ce25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '050159a447e4f328e9283cea9785dc08bd51d6132995ff9ecda4cdfbda08f665f8294607f5eeaf390e9b3a069ae69dab675fc2767b1300973ec9bfa2b918b70a'
|
7
|
+
data.tar.gz: 582384118f7e8df7091280f6bc78e6d6f95f612f28a0892637d1e1a845c93754df29f5e463e8a1a69ca5f85ed95e666f82ab4ac957bf3a896d3f34fb26a5693b
|
data/bin/mutant
CHANGED
@@ -10,7 +10,6 @@ require 'mutant'
|
|
10
10
|
|
11
11
|
command = Mutant::CLI.parse(
|
12
12
|
arguments: ARGV,
|
13
|
-
config: Mutant::Config::DEFAULT,
|
14
13
|
world: Mutant::WORLD
|
15
14
|
)
|
16
15
|
|
@@ -40,7 +39,6 @@ status =
|
|
40
39
|
|
41
40
|
Zombie::Mutant::CLI.parse(
|
42
41
|
arguments: ARGV,
|
43
|
-
config: Zombie::Mutant::Config::DEFAULT,
|
44
42
|
world: Zombie::Mutant::WORLD
|
45
43
|
).call
|
46
44
|
else
|
data/lib/mutant.rb
CHANGED
@@ -163,6 +163,7 @@ require 'mutant/integration/null'
|
|
163
163
|
require 'mutant/selector'
|
164
164
|
require 'mutant/selector/expression'
|
165
165
|
require 'mutant/selector/null'
|
166
|
+
require 'mutant/world'
|
166
167
|
require 'mutant/config'
|
167
168
|
require 'mutant/cli'
|
168
169
|
require 'mutant/cli/command'
|
@@ -178,16 +179,14 @@ require 'mutant/reporter/sequence'
|
|
178
179
|
require 'mutant/reporter/cli'
|
179
180
|
require 'mutant/reporter/cli/printer'
|
180
181
|
require 'mutant/reporter/cli/printer/config'
|
182
|
+
require 'mutant/reporter/cli/printer/coverage_result'
|
181
183
|
require 'mutant/reporter/cli/printer/env'
|
182
184
|
require 'mutant/reporter/cli/printer/env_progress'
|
183
185
|
require 'mutant/reporter/cli/printer/env_result'
|
184
186
|
require 'mutant/reporter/cli/printer/isolation_result'
|
185
|
-
require 'mutant/reporter/cli/printer/mutation_progress_result'
|
186
187
|
require 'mutant/reporter/cli/printer/mutation_result'
|
187
188
|
require 'mutant/reporter/cli/printer/status_progressive'
|
188
|
-
require 'mutant/reporter/cli/printer/subject_progress'
|
189
189
|
require 'mutant/reporter/cli/printer/subject_result'
|
190
|
-
require 'mutant/reporter/cli/printer/test_result'
|
191
190
|
require 'mutant/reporter/cli/format'
|
192
191
|
require 'mutant/repository'
|
193
192
|
require 'mutant/repository/diff'
|
@@ -218,12 +217,14 @@ module Mutant
|
|
218
217
|
stderr: $stderr,
|
219
218
|
stdout: $stdout,
|
220
219
|
thread: Thread,
|
220
|
+
timer: Timer.new(Process),
|
221
221
|
warnings: Warnings.new(Warning)
|
222
222
|
)
|
223
223
|
|
224
224
|
# Reopen class to initialize constant to avoid dep circle
|
225
225
|
class Config
|
226
226
|
DEFAULT = new(
|
227
|
+
coverage_criteria: Config::CoverageCriteria::DEFAULT,
|
227
228
|
expression_parser: Expression::Parser.new([
|
228
229
|
Expression::Method,
|
229
230
|
Expression::Methods,
|
@@ -232,10 +233,11 @@ module Mutant
|
|
232
233
|
]),
|
233
234
|
fail_fast: false,
|
234
235
|
includes: EMPTY_ARRAY,
|
235
|
-
integration:
|
236
|
+
integration: nil,
|
236
237
|
isolation: Mutant::Isolation::Fork.new(WORLD),
|
237
|
-
jobs:
|
238
|
+
jobs: nil,
|
238
239
|
matcher: Matcher::Config::DEFAULT,
|
240
|
+
mutation_timeout: nil,
|
239
241
|
reporter: Reporter::CLI.build(WORLD.stdout),
|
240
242
|
requires: EMPTY_ARRAY,
|
241
243
|
zombie: false
|
data/lib/mutant/cli/command.rb
CHANGED
@@ -4,7 +4,7 @@ module Mutant
|
|
4
4
|
module CLI
|
5
5
|
# rubocop:disable Metrics/ClassLength
|
6
6
|
class Command
|
7
|
-
include AbstractType, Anima.new(:world, :
|
7
|
+
include AbstractType, Anima.new(:world, :main, :parent, :arguments)
|
8
8
|
|
9
9
|
include Equalizer.new(:parent, :arguments)
|
10
10
|
|
@@ -105,7 +105,7 @@ module Mutant
|
|
105
105
|
def parse
|
106
106
|
Either
|
107
107
|
.wrap_error(OptionParser::InvalidOption) { parser.order(arguments) }
|
108
|
-
.lmap
|
108
|
+
.lmap(&method(:with_help))
|
109
109
|
.bind(&method(:parse_remaining))
|
110
110
|
end
|
111
111
|
|
@@ -159,9 +159,7 @@ module Mutant
|
|
159
159
|
command_name, *arguments = arguments
|
160
160
|
|
161
161
|
if command_name.nil?
|
162
|
-
Either::Left.new(
|
163
|
-
"Missing required subcommand!\n\n#{parser}"
|
164
|
-
)
|
162
|
+
Either::Left.new(with_help('Missing required subcommand!'))
|
165
163
|
else
|
166
164
|
find_command(command_name).bind do |command|
|
167
165
|
command.parse(**to_h, parent: self, arguments: arguments)
|
@@ -187,9 +185,13 @@ module Mutant
|
|
187
185
|
if subcommand
|
188
186
|
Either::Right.new(subcommand)
|
189
187
|
else
|
190
|
-
Either::Left.new("
|
188
|
+
Either::Left.new(with_help("Cannot find subcommand #{name.inspect}"))
|
191
189
|
end
|
192
190
|
end
|
191
|
+
|
192
|
+
def with_help(message)
|
193
|
+
"#{full_name}: #{message}\n\n#{parser}"
|
194
|
+
end
|
193
195
|
end # Command
|
194
196
|
# rubocop:enable Metrics/ClassLength
|
195
197
|
end # CLI
|
@@ -28,20 +28,30 @@ module Mutant
|
|
28
28
|
#
|
29
29
|
# @return [Bool]
|
30
30
|
def zombie?
|
31
|
-
config.zombie
|
31
|
+
@config.zombie
|
32
32
|
end
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
+
def initialize(attributes)
|
37
|
+
super(attributes)
|
38
|
+
@config = Config.env
|
39
|
+
end
|
40
|
+
|
36
41
|
def execute
|
37
42
|
soft_fail(License.apply(world))
|
38
|
-
.bind { Config.load_config_file(world
|
39
|
-
.
|
43
|
+
.bind { Config.load_config_file(world) }
|
44
|
+
.fmap(&method(:expand))
|
45
|
+
.bind { Bootstrap.apply(world, @config) }
|
40
46
|
.bind(&Runner.public_method(:apply))
|
41
47
|
.from_right { |error| world.stderr.puts(error); return false }
|
42
48
|
.success?
|
43
49
|
end
|
44
50
|
|
51
|
+
def expand(file_config)
|
52
|
+
@config = @config.merge(file_config)
|
53
|
+
end
|
54
|
+
|
45
55
|
def soft_fail(result)
|
46
56
|
result.either(
|
47
57
|
lambda do |message|
|
@@ -60,7 +70,7 @@ module Mutant
|
|
60
70
|
end
|
61
71
|
|
62
72
|
def parse_remaining_arguments(arguments)
|
63
|
-
traverse(config.expression_parser.public_method(:apply), arguments)
|
73
|
+
traverse(@config.expression_parser.public_method(:apply), arguments)
|
64
74
|
.fmap do |match_expressions|
|
65
75
|
matcher(match_expressions: match_expressions)
|
66
76
|
self
|
@@ -78,19 +88,19 @@ module Mutant
|
|
78
88
|
end
|
79
89
|
|
80
90
|
def set(**attributes)
|
81
|
-
@config = config.with(attributes)
|
91
|
+
@config = @config.with(attributes)
|
82
92
|
end
|
83
93
|
|
84
94
|
def matcher(**attributes)
|
85
|
-
set(matcher: config.matcher.with(attributes))
|
95
|
+
set(matcher: @config.matcher.with(attributes))
|
86
96
|
end
|
87
97
|
|
88
98
|
def add(attribute, value)
|
89
|
-
set(attribute => config.public_send(attribute) + [value])
|
99
|
+
set(attribute => @config.public_send(attribute) + [value])
|
90
100
|
end
|
91
101
|
|
92
102
|
def add_matcher(attribute, value)
|
93
|
-
set(matcher: config.matcher.add(attribute, value))
|
103
|
+
set(matcher: @config.matcher.add(attribute, value))
|
94
104
|
end
|
95
105
|
|
96
106
|
def add_environment_options(parser)
|
@@ -119,10 +129,10 @@ module Mutant
|
|
119
129
|
parser.separator('Matcher:')
|
120
130
|
|
121
131
|
parser.on('--ignore-subject EXPRESSION', 'Ignore subjects that match EXPRESSION as prefix') do |pattern|
|
122
|
-
add_matcher(:ignore_expressions, config.expression_parser.apply(pattern).from_right)
|
132
|
+
add_matcher(:ignore_expressions, @config.expression_parser.apply(pattern).from_right)
|
123
133
|
end
|
124
134
|
parser.on('--start-subject EXPRESSION', 'Start mutation testing at a specific subject') do |pattern|
|
125
|
-
add_matcher(:start_expressions, config.expression_parser.apply(pattern).from_right)
|
135
|
+
add_matcher(:start_expressions, @config.expression_parser.apply(pattern).from_right)
|
126
136
|
end
|
127
137
|
parser.on('--since REVISION', 'Only select subjects touched since REVISION') do |revision|
|
128
138
|
add_matcher(
|
@@ -143,6 +153,9 @@ module Mutant
|
|
143
153
|
parser.on('-j', '--jobs NUMBER', 'Number of kill jobs. Defaults to number of processors.') do |number|
|
144
154
|
set(jobs: Integer(number))
|
145
155
|
end
|
156
|
+
parser.on('-t', '--mutation-timeout NUMBER', 'Per mutation analysis timeout') do |number|
|
157
|
+
set(mutation_timeout: Float(number))
|
158
|
+
end
|
146
159
|
end
|
147
160
|
end # Run
|
148
161
|
# rubocop:enable Metrics/ClassLength
|
data/lib/mutant/config.rb
CHANGED
@@ -1,61 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Mutant
|
4
|
-
# The outer world IO objects mutant does interact with
|
5
|
-
class World
|
6
|
-
include Adamantium::Flat, Anima.new(
|
7
|
-
:condition_variable,
|
8
|
-
:gem,
|
9
|
-
:gem_method,
|
10
|
-
:io,
|
11
|
-
:json,
|
12
|
-
:kernel,
|
13
|
-
:load_path,
|
14
|
-
:marshal,
|
15
|
-
:mutex,
|
16
|
-
:object_space,
|
17
|
-
:open3,
|
18
|
-
:pathname,
|
19
|
-
:process,
|
20
|
-
:stderr,
|
21
|
-
:stdout,
|
22
|
-
:thread,
|
23
|
-
:warnings
|
24
|
-
)
|
25
|
-
|
26
|
-
INSPECT = '#<Mutant::World>'
|
27
|
-
|
28
|
-
private_constant(*constants(false))
|
29
|
-
|
30
|
-
# Object inspection
|
31
|
-
#
|
32
|
-
# @return [String]
|
33
|
-
def inspect
|
34
|
-
INSPECT
|
35
|
-
end
|
36
|
-
|
37
|
-
# Capture stdout of a command
|
38
|
-
#
|
39
|
-
# @param [Array<String>] command
|
40
|
-
#
|
41
|
-
# @return [Either<String,String>]
|
42
|
-
def capture_stdout(command)
|
43
|
-
stdout, status = open3.capture2(*command, binmode: true)
|
44
|
-
|
45
|
-
if status.success?
|
46
|
-
Either::Right.new(stdout)
|
47
|
-
else
|
48
|
-
Either::Left.new("Command #{command} failed!")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end # World
|
52
|
-
|
53
4
|
# Standalone configuration of a mutant execution.
|
54
5
|
#
|
55
6
|
# Does not reference any "external" volatile state. The configuration applied
|
56
7
|
# to current environment is being represented by the Mutant::Env object.
|
57
8
|
class Config
|
58
9
|
include Adamantium::Flat, Anima.new(
|
10
|
+
:coverage_criteria,
|
59
11
|
:expression_parser,
|
60
12
|
:fail_fast,
|
61
13
|
:includes,
|
@@ -63,6 +15,7 @@ module Mutant
|
|
63
15
|
:isolation,
|
64
16
|
:jobs,
|
65
17
|
:matcher,
|
18
|
+
:mutation_timeout,
|
66
19
|
:reporter,
|
67
20
|
:requires,
|
68
21
|
:zombie
|
@@ -72,30 +25,6 @@ module Mutant
|
|
72
25
|
define_method(:"#{name}?") { public_send(name) }
|
73
26
|
end
|
74
27
|
|
75
|
-
boolean = Transform::Boolean.new
|
76
|
-
integer = Transform::Primitive.new(Integer)
|
77
|
-
string = Transform::Primitive.new(String)
|
78
|
-
|
79
|
-
string_array = Transform::Array.new(string)
|
80
|
-
|
81
|
-
TRANSFORM = Transform::Sequence.new(
|
82
|
-
[
|
83
|
-
Transform::Exception.new(SystemCallError, :read.to_proc),
|
84
|
-
Transform::Exception.new(YAML::SyntaxError, YAML.method(:safe_load)),
|
85
|
-
Transform::Hash.new(
|
86
|
-
optional: [
|
87
|
-
Transform::Hash::Key.new('fail_fast', boolean),
|
88
|
-
Transform::Hash::Key.new('includes', string_array),
|
89
|
-
Transform::Hash::Key.new('integration', string),
|
90
|
-
Transform::Hash::Key.new('jobs', integer),
|
91
|
-
Transform::Hash::Key.new('requires', string_array)
|
92
|
-
],
|
93
|
-
required: []
|
94
|
-
),
|
95
|
-
Transform::Hash::Symbolize.new
|
96
|
-
]
|
97
|
-
)
|
98
|
-
|
99
28
|
MORE_THAN_ONE_CONFIG_FILE = <<~'MESSAGE'
|
100
29
|
Found more than one candidate for use as implicit config file: %s
|
101
30
|
MESSAGE
|
@@ -108,17 +37,62 @@ module Mutant
|
|
108
37
|
|
109
38
|
private_constant(*constants(false))
|
110
39
|
|
40
|
+
class CoverageCriteria
|
41
|
+
include Anima.new(:process_abort, :test_result, :timeout)
|
42
|
+
|
43
|
+
DEFAULT = new(
|
44
|
+
process_abort: false,
|
45
|
+
test_result: true,
|
46
|
+
timeout: false
|
47
|
+
)
|
48
|
+
|
49
|
+
TRANSFORM =
|
50
|
+
Transform::Sequence.new(
|
51
|
+
[
|
52
|
+
Transform::Hash.new(
|
53
|
+
optional: [
|
54
|
+
Transform::Hash::Key.new('process_abort', Transform::BOOLEAN),
|
55
|
+
Transform::Hash::Key.new('test_result', Transform::BOOLEAN),
|
56
|
+
Transform::Hash::Key.new('timeout', Transform::BOOLEAN)
|
57
|
+
],
|
58
|
+
required: []
|
59
|
+
),
|
60
|
+
Transform::Hash::Symbolize.new,
|
61
|
+
->(value) { Either::Right.new(DEFAULT.with(**value)) }
|
62
|
+
]
|
63
|
+
)
|
64
|
+
end # CoverageCriteria
|
65
|
+
|
66
|
+
# Merge with other config
|
67
|
+
#
|
68
|
+
# @param [Config] other
|
69
|
+
#
|
70
|
+
# @return [Config]
|
71
|
+
def merge(other)
|
72
|
+
other.with(
|
73
|
+
fail_fast: fail_fast || other.fail_fast,
|
74
|
+
includes: other.includes + includes,
|
75
|
+
jobs: other.jobs || jobs,
|
76
|
+
integration: other.integration || integration,
|
77
|
+
mutation_timeout: other.mutation_timeout || mutation_timeout,
|
78
|
+
matcher: matcher.merge(other.matcher),
|
79
|
+
requires: other.requires + requires,
|
80
|
+
zombie: zombie || other.zombie
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
111
84
|
# Load config file
|
112
85
|
#
|
113
86
|
# @param [World] world
|
114
87
|
# @param [Config] config
|
115
88
|
#
|
116
89
|
# @return [Either<String,Config>]
|
117
|
-
def self.load_config_file(world
|
118
|
-
|
90
|
+
def self.load_config_file(world)
|
91
|
+
config = DEFAULT
|
92
|
+
files = CANDIDATES.map(&world.pathname.public_method(:new)).select(&:readable?)
|
119
93
|
|
120
94
|
if files.one?
|
121
|
-
load_contents(files.first).fmap(&config.
|
95
|
+
load_contents(files.first).fmap(&config.public_method(:with))
|
122
96
|
elsif files.empty?
|
123
97
|
Either::Right.new(config)
|
124
98
|
else
|
@@ -129,9 +103,38 @@ module Mutant
|
|
129
103
|
def self.load_contents(path)
|
130
104
|
Transform::Named
|
131
105
|
.new(path.to_s, TRANSFORM)
|
132
|
-
.
|
106
|
+
.call(path)
|
133
107
|
.lmap(&:compact_message)
|
134
108
|
end
|
135
109
|
private_class_method :load_contents
|
110
|
+
|
111
|
+
# The configuration from the environment
|
112
|
+
#
|
113
|
+
# @return [Config]
|
114
|
+
def self.env
|
115
|
+
DEFAULT.with(jobs: Etc.nprocessors)
|
116
|
+
end
|
117
|
+
|
118
|
+
TRANSFORM = Transform::Sequence.new(
|
119
|
+
[
|
120
|
+
Transform::Exception.new(SystemCallError, :read.to_proc),
|
121
|
+
Transform::Exception.new(YAML::SyntaxError, YAML.method(:safe_load)),
|
122
|
+
Transform::Hash.new(
|
123
|
+
optional: [
|
124
|
+
Transform::Hash::Key.new('coverage_criteria', CoverageCriteria::TRANSFORM),
|
125
|
+
Transform::Hash::Key.new('fail_fast', Transform::BOOLEAN),
|
126
|
+
Transform::Hash::Key.new('includes', Transform::STRING_ARRAY),
|
127
|
+
Transform::Hash::Key.new('integration', Transform::STRING),
|
128
|
+
Transform::Hash::Key.new('jobs', Transform::INTEGER),
|
129
|
+
Transform::Hash::Key.new('mutation_timeout', Transform::FLOAT),
|
130
|
+
Transform::Hash::Key.new('requires', Transform::STRING_ARRAY)
|
131
|
+
],
|
132
|
+
required: []
|
133
|
+
),
|
134
|
+
Transform::Hash::Symbolize.new
|
135
|
+
]
|
136
|
+
)
|
137
|
+
|
138
|
+
private_constant(:TRANSFORM)
|
136
139
|
end # Config
|
137
140
|
end # Mutant
|
data/lib/mutant/env.rb
CHANGED
@@ -24,10 +24,15 @@ module Mutant
|
|
24
24
|
# @param [Config] config
|
25
25
|
#
|
26
26
|
# @return [Env]
|
27
|
+
#
|
28
|
+
# rubocop:disable Metrics/MethodLength
|
27
29
|
def self.empty(world, config)
|
28
30
|
new(
|
29
31
|
config: config,
|
30
|
-
integration: Integration::Null.new(
|
32
|
+
integration: Integration::Null.new(
|
33
|
+
expression_parser: config.expression_parser,
|
34
|
+
timer: world.timer
|
35
|
+
),
|
31
36
|
matchable_scopes: EMPTY_ARRAY,
|
32
37
|
mutations: EMPTY_ARRAY,
|
33
38
|
parser: Parser.new,
|
@@ -36,6 +41,7 @@ module Mutant
|
|
36
41
|
world: world
|
37
42
|
)
|
38
43
|
end
|
44
|
+
# rubocop:enable Metrics/MethodLength
|
39
45
|
|
40
46
|
# Kill mutation
|
41
47
|
#
|
@@ -43,14 +49,14 @@ module Mutant
|
|
43
49
|
#
|
44
50
|
# @return [Result::Mutation]
|
45
51
|
def kill(mutation)
|
46
|
-
start =
|
52
|
+
start = timer.now
|
47
53
|
|
48
54
|
tests = selections.fetch(mutation.subject)
|
49
55
|
|
50
56
|
Result::Mutation.new(
|
51
57
|
isolation_result: run_mutation_tests(mutation, tests),
|
52
58
|
mutation: mutation,
|
53
|
-
runtime:
|
59
|
+
runtime: timer.now - start
|
54
60
|
)
|
55
61
|
end
|
56
62
|
|
@@ -127,7 +133,7 @@ module Mutant
|
|
127
133
|
private
|
128
134
|
|
129
135
|
def run_mutation_tests(mutation, tests)
|
130
|
-
config.isolation.call do
|
136
|
+
config.isolation.call(config.mutation_timeout) do
|
131
137
|
result = mutation.insert(world.kernel)
|
132
138
|
|
133
139
|
if result.equal?(Loader::Result::VoidValue.instance)
|
@@ -138,5 +144,9 @@ module Mutant
|
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
147
|
+
def timer
|
148
|
+
world.timer
|
149
|
+
end
|
150
|
+
|
141
151
|
end # Env
|
142
152
|
end # Mutant
|