mutant 0.10.4 → 0.10.5
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 +3 -2
- data/lib/mutant/cli/command.rb +1 -1
- data/lib/mutant/cli/command/run.rb +20 -10
- data/lib/mutant/config.rb +28 -52
- data/lib/mutant/matcher/config.rb +13 -0
- data/lib/mutant/reporter/cli/printer/config.rb +2 -2
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/world.rb +52 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2e6667e21b413029cf11b268c6d36986a5960921945aad01199aaff5881a3c2
|
4
|
+
data.tar.gz: 3434159c18f80d786ecc728b3fde7eaa5e2c3939ec70c5d931e717288ba6d48f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a036402f0e95f0a41b16dbbede078a56f5ccee4d241052b034022fd6a7db505037cefb5b093061d2d12326f6a4e2ae7bd250ad7bb160586aa14dc831d019a398
|
7
|
+
data.tar.gz: 188b1bb29e0639c6a7f3c72b5ee4ca24ac25bc799181b1f7d2e6f0b056fb92aabe6b7c657345ac080e4002625dad227752c1e7c4a57d5e0f506d608f3c4be28d
|
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'
|
@@ -232,9 +233,9 @@ 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,
|
239
240
|
reporter: Reporter::CLI.build(WORLD.stdout),
|
240
241
|
requires: EMPTY_ARRAY,
|
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
|
|
@@ -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::DEFAULT
|
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.env.merge(file_config).merge(@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(
|
data/lib/mutant/config.rb
CHANGED
@@ -1,55 +1,6 @@
|
|
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
|
@@ -106,6 +57,23 @@ module Mutant
|
|
106
57
|
mutant.yml
|
107
58
|
].freeze
|
108
59
|
|
60
|
+
# Merge with other config
|
61
|
+
#
|
62
|
+
# @param [Config] other
|
63
|
+
#
|
64
|
+
# @return [Config]
|
65
|
+
def merge(other)
|
66
|
+
other.with(
|
67
|
+
fail_fast: fail_fast || other.fail_fast,
|
68
|
+
includes: includes + other.includes,
|
69
|
+
jobs: other.jobs || jobs,
|
70
|
+
integration: other.integration || integration,
|
71
|
+
matcher: matcher.merge(other.matcher),
|
72
|
+
requires: requires + other.requires,
|
73
|
+
zombie: zombie || other.zombie
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
109
77
|
private_constant(*constants(false))
|
110
78
|
|
111
79
|
# Load config file
|
@@ -114,11 +82,12 @@ module Mutant
|
|
114
82
|
# @param [Config] config
|
115
83
|
#
|
116
84
|
# @return [Either<String,Config>]
|
117
|
-
def self.load_config_file(world
|
118
|
-
|
85
|
+
def self.load_config_file(world)
|
86
|
+
config = DEFAULT
|
87
|
+
files = CANDIDATES.map(&world.pathname.public_method(:new)).select(&:readable?)
|
119
88
|
|
120
89
|
if files.one?
|
121
|
-
load_contents(files.first).fmap(&config.
|
90
|
+
load_contents(files.first).fmap(&config.public_method(:with))
|
122
91
|
elsif files.empty?
|
123
92
|
Either::Right.new(config)
|
124
93
|
else
|
@@ -133,5 +102,12 @@ module Mutant
|
|
133
102
|
.lmap(&:compact_message)
|
134
103
|
end
|
135
104
|
private_class_method :load_contents
|
105
|
+
|
106
|
+
# The configuration from the environment
|
107
|
+
#
|
108
|
+
# @return [Config]
|
109
|
+
def self.env
|
110
|
+
DEFAULT.with(jobs: Etc.nprocessors)
|
111
|
+
end
|
136
112
|
end # Config
|
137
113
|
end # Mutant
|
@@ -44,6 +44,19 @@ module Mutant
|
|
44
44
|
with(attribute => public_send(attribute) + [value])
|
45
45
|
end
|
46
46
|
|
47
|
+
# Merge with other config
|
48
|
+
#
|
49
|
+
# @param [Config] other
|
50
|
+
#
|
51
|
+
# @return [Config]
|
52
|
+
def merge(other)
|
53
|
+
self.class.new(
|
54
|
+
to_h
|
55
|
+
.map { |name, value| [name, value + other.public_send(name)] }
|
56
|
+
.to_h
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
47
60
|
private
|
48
61
|
|
49
62
|
def present_attributes
|
@@ -14,8 +14,8 @@ module Mutant
|
|
14
14
|
# @return [undefined]
|
15
15
|
def run
|
16
16
|
info 'Matcher: %s', object.matcher.inspect
|
17
|
-
info 'Integration: %s', object.integration
|
18
|
-
info 'Jobs: %
|
17
|
+
info 'Integration: %s', object.integration || 'null'
|
18
|
+
info 'Jobs: %s', object.jobs || 'auto'
|
19
19
|
info 'Includes: %s', object.includes
|
20
20
|
info 'Requires: %s', object.requires
|
21
21
|
end
|
data/lib/mutant/version.rb
CHANGED
data/lib/mutant/world.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
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
|
+
end # Mutant
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mutant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Schirp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: abstract_type
|
@@ -450,6 +450,7 @@ files:
|
|
450
450
|
- lib/mutant/util.rb
|
451
451
|
- lib/mutant/version.rb
|
452
452
|
- lib/mutant/warnings.rb
|
453
|
+
- lib/mutant/world.rb
|
453
454
|
- lib/mutant/zombifier.rb
|
454
455
|
homepage: https://github.com/mbj/mutant
|
455
456
|
licenses:
|