mutant 0.7.4 → 0.7.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/.travis.yml +3 -2
- data/Changelog.md +6 -2
- data/Gemfile +1 -0
- data/config/flay.yml +1 -1
- data/config/reek.yml +1 -1
- data/lib/mutant.rb +4 -3
- data/lib/mutant/cli.rb +2 -2
- data/lib/mutant/config.rb +2 -3
- data/lib/mutant/env.rb +29 -132
- data/lib/mutant/env/bootstrap.rb +155 -0
- data/lib/mutant/expression.rb +27 -0
- data/lib/mutant/expression/namespace.rb +2 -2
- data/lib/mutant/matcher/method.rb +1 -1
- data/lib/mutant/matcher/method/instance.rb +1 -1
- data/lib/mutant/mutation.rb +2 -30
- data/lib/mutant/mutator/node/begin.rb +1 -3
- data/lib/mutant/mutator/node/if.rb +2 -2
- data/lib/mutant/reporter/cli/printer.rb +5 -4
- data/lib/mutant/result.rb +1 -1
- data/lib/mutant/runner.rb +3 -3
- data/lib/mutant/runner/sink.rb +86 -53
- data/lib/mutant/selector.rb +17 -0
- data/lib/mutant/selector/expression.rb +28 -0
- data/lib/mutant/subject.rb +1 -19
- data/lib/mutant/version.rb +1 -1
- data/mutant.gemspec +3 -3
- data/spec/spec_helper.rb +1 -1
- data/spec/support/corpus.rb +5 -5
- data/spec/support/shared_context.rb +1 -6
- data/spec/unit/mutant/cli_spec.rb +2 -2
- data/spec/unit/mutant/env/boostrap_spec.rb +130 -0
- data/spec/unit/mutant/env_spec.rb +61 -49
- data/spec/unit/mutant/expression_spec.rb +13 -0
- data/spec/unit/mutant/matcher/filter_spec.rb +1 -1
- data/spec/unit/mutant/matcher/method/instance_spec.rb +1 -1
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +1 -1
- data/spec/unit/mutant/mutation_spec.rb +0 -36
- data/spec/unit/mutant/reporter/trace_spec.rb +1 -1
- data/spec/unit/mutant/require_highjack_spec.rb +2 -4
- data/spec/unit/mutant/result/subject_spec.rb +2 -1
- data/spec/unit/mutant/runner/{sink_spec.rb → sink/mutation_spec.rb} +1 -3
- data/spec/unit/mutant/runner_spec.rb +4 -3
- data/spec/unit/mutant/selector/expression_spec.rb +60 -0
- data/spec/unit/mutant/subject/method/instance_spec.rb +3 -5
- data/spec/unit/mutant/subject/method/singleton_spec.rb +2 -3
- data/spec/unit/mutant/subject_spec.rb +1 -53
- data/spec/unit/mutant/warning_filter_spec.rb +2 -4
- metadata +18 -15
- data/lib/mutant/line_trace.rb +0 -34
- data/spec/unit/mutant/line_trace_spec.rb +0 -38
- data/spec/unit/mutant/subject/context_spec.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9aa6cee93941cfb9307169023bb523bdc18c290a
|
4
|
+
data.tar.gz: 3130e644fa7c02db1ed0adef9300d711269e7323
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eba0e605c2fd699c0bd22b08d65332701c14a190da37e017d400fadc8a7869b54dbfefb577c537d329da487039046e3868529a9ec88847d4c3f7a17cab0c1845
|
7
|
+
data.tar.gz: 3ff08e6ca56e920894f440e90084599116731914c662f61780a09d800db505794207c79919ffb3dc945d1a3f9780280523527598932f0ef7f5e077e8d499c771
|
data/.travis.yml
CHANGED
@@ -4,12 +4,13 @@ script: "bundle exec rake ci"
|
|
4
4
|
env:
|
5
5
|
- TRAVIS=true
|
6
6
|
rvm:
|
7
|
+
- '1.9'
|
7
8
|
- '2.0'
|
8
9
|
- '2.1'
|
9
|
-
- rbx
|
10
|
+
- rbx
|
10
11
|
matrix:
|
11
12
|
allow_failures:
|
12
|
-
- rvm: rbx
|
13
|
+
- rvm: rbx
|
13
14
|
notifications:
|
14
15
|
irc:
|
15
16
|
channels:
|
data/Changelog.md
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
# v0.7.5 2015-01-14
|
2
|
+
|
3
|
+
* Bump deps to support MRI 2.2.
|
4
|
+
|
1
5
|
# v0.7.4 2014-12-22
|
2
6
|
|
3
|
-
* Fix rspec example visibility on duplicate metadata examples
|
4
|
-
* Add naked if/else body emitter
|
7
|
+
* Fix rspec example visibility on duplicate metadata examples [#279](https://github.com/mbj/mutant/issues/279).
|
8
|
+
* Add naked if/else body emitter [#280](https://github.com/mbj/mutant/issues/280).
|
5
9
|
|
6
10
|
# v0.7.3 2014-12-09
|
7
11
|
|
data/Gemfile
CHANGED
data/config/flay.yml
CHANGED
data/config/reek.yml
CHANGED
@@ -47,7 +47,7 @@ NestedIterators:
|
|
47
47
|
- Mutant::Mutator::Node::Arguments#emit_argument_mutations
|
48
48
|
- Mutant::RequireHighjack#infect
|
49
49
|
- Mutant::RequireHighjack#disinfect
|
50
|
-
- Mutant::
|
50
|
+
- Mutant::Selector::Expression#call
|
51
51
|
- Mutant::Parallel::Master#run
|
52
52
|
- Parser::Lexer#self.new
|
53
53
|
max_allowed_nesting: 1
|
data/lib/mutant.rb
CHANGED
@@ -95,6 +95,7 @@ end # Mutant
|
|
95
95
|
|
96
96
|
require 'mutant/version'
|
97
97
|
require 'mutant/env'
|
98
|
+
require 'mutant/env/bootstrap'
|
98
99
|
require 'mutant/ast'
|
99
100
|
require 'mutant/ast/sexp'
|
100
101
|
require 'mutant/ast/types'
|
@@ -202,6 +203,8 @@ require 'mutant/expression/methods'
|
|
202
203
|
require 'mutant/expression/namespace'
|
203
204
|
require 'mutant/test'
|
204
205
|
require 'mutant/integration'
|
206
|
+
require 'mutant/selector'
|
207
|
+
require 'mutant/selector/expression'
|
205
208
|
require 'mutant/cli'
|
206
209
|
require 'mutant/color'
|
207
210
|
require 'mutant/diff'
|
@@ -215,7 +218,6 @@ require 'mutant/reporter/cli'
|
|
215
218
|
require 'mutant/reporter/cli/printer'
|
216
219
|
require 'mutant/reporter/cli/tput'
|
217
220
|
require 'mutant/reporter/cli/format'
|
218
|
-
require 'mutant/line_trace'
|
219
221
|
require 'mutant/zombifier'
|
220
222
|
require 'mutant/zombifier/file'
|
221
223
|
|
@@ -228,14 +230,13 @@ module Mutant
|
|
228
230
|
debug: false,
|
229
231
|
fail_fast: false,
|
230
232
|
integration: Integration::Null.new,
|
231
|
-
|
233
|
+
matcher: Matcher::Config::DEFAULT,
|
232
234
|
includes: EMPTY_ARRAY,
|
233
235
|
requires: EMPTY_ARRAY,
|
234
236
|
isolation: Mutant::Isolation::Fork,
|
235
237
|
reporter: Reporter::CLI.build($stdout),
|
236
238
|
zombie: false,
|
237
239
|
jobs: Mutant.ci? ? CI_DEFAULT_PROCESSOR_COUNT : ::Parallel.processor_count,
|
238
|
-
actor_env: Mutant::Actor::Env.new(Thread),
|
239
240
|
expected_coverage: 100.0
|
240
241
|
)
|
241
242
|
end # Config
|
data/lib/mutant/cli.rb
CHANGED
@@ -22,7 +22,7 @@ module Mutant
|
|
22
22
|
# @api private
|
23
23
|
#
|
24
24
|
def self.run(arguments)
|
25
|
-
Runner.call(Env.
|
25
|
+
Runner.call(Env::Bootstrap.call(call(arguments))).success? ? EXIT_SUCCESS : EXIT_FAILURE
|
26
26
|
rescue Error => exception
|
27
27
|
$stderr.puts(exception.message)
|
28
28
|
EXIT_FAILURE
|
@@ -235,7 +235,7 @@ module Mutant
|
|
235
235
|
# @api private
|
236
236
|
#
|
237
237
|
def add_matcher(attribute, value)
|
238
|
-
update(
|
238
|
+
update(matcher: config.matcher.add(attribute, value))
|
239
239
|
end
|
240
240
|
|
241
241
|
end # CLI
|
data/lib/mutant/config.rb
CHANGED
@@ -4,7 +4,7 @@ module Mutant
|
|
4
4
|
include Adamantium::Flat, Anima::Update, Anima.new(
|
5
5
|
:debug,
|
6
6
|
:integration,
|
7
|
-
:
|
7
|
+
:matcher,
|
8
8
|
:includes,
|
9
9
|
:requires,
|
10
10
|
:reporter,
|
@@ -12,8 +12,7 @@ module Mutant
|
|
12
12
|
:fail_fast,
|
13
13
|
:jobs,
|
14
14
|
:zombie,
|
15
|
-
:expected_coverage
|
16
|
-
:actor_env
|
15
|
+
:expected_coverage
|
17
16
|
)
|
18
17
|
|
19
18
|
[:fail_fast, :zombie, :debug].each do |name|
|
data/lib/mutant/env.rb
CHANGED
@@ -1,39 +1,20 @@
|
|
1
1
|
module Mutant
|
2
2
|
# Abstract base class for mutant environments
|
3
3
|
class Env
|
4
|
-
include Adamantium::Flat,
|
4
|
+
include Adamantium::Flat, Anima::Update, Anima.new(
|
5
|
+
:config,
|
6
|
+
:actor_env,
|
7
|
+
:cache,
|
8
|
+
:subjects,
|
9
|
+
:matchable_scopes,
|
10
|
+
:selector,
|
11
|
+
:mutations
|
12
|
+
)
|
5
13
|
|
6
14
|
SEMANTICS_MESSAGE =
|
7
15
|
"Fix your lib to follow normal ruby semantics!\n" \
|
8
16
|
'{Module,Class}#name should return resolvable constant name as String or nil'.freeze
|
9
17
|
|
10
|
-
# Return new env
|
11
|
-
#
|
12
|
-
# @param [Config] config
|
13
|
-
#
|
14
|
-
# @return [Env]
|
15
|
-
#
|
16
|
-
# @api private
|
17
|
-
#
|
18
|
-
def self.new(config, cache = Cache.new)
|
19
|
-
super(config, cache)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Initialize env
|
23
|
-
#
|
24
|
-
# @return [undefined]
|
25
|
-
#
|
26
|
-
# @api private
|
27
|
-
#
|
28
|
-
def initialize(*)
|
29
|
-
super
|
30
|
-
|
31
|
-
infect
|
32
|
-
initialize_matchable_scopes
|
33
|
-
initialize_subjects
|
34
|
-
initialize_mutations
|
35
|
-
end
|
36
|
-
|
37
18
|
# Print warning message
|
38
19
|
#
|
39
20
|
# @param [String]
|
@@ -47,30 +28,6 @@ module Mutant
|
|
47
28
|
self
|
48
29
|
end
|
49
30
|
|
50
|
-
# Return subjects
|
51
|
-
#
|
52
|
-
# @return [Array<Subject>]
|
53
|
-
#
|
54
|
-
# @api private
|
55
|
-
#
|
56
|
-
attr_reader :subjects
|
57
|
-
|
58
|
-
# Return mutations
|
59
|
-
#
|
60
|
-
# @return [Array<Mutation>]
|
61
|
-
#
|
62
|
-
# @api private
|
63
|
-
#
|
64
|
-
attr_reader :mutations
|
65
|
-
|
66
|
-
# Return all usable match scopes
|
67
|
-
#
|
68
|
-
# @return [Array<Matcher::Scope>]
|
69
|
-
#
|
70
|
-
# @api private
|
71
|
-
#
|
72
|
-
attr_reader :matchable_scopes
|
73
|
-
|
74
31
|
# Kill mutation
|
75
32
|
#
|
76
33
|
# @param [Mutation] mutation
|
@@ -79,8 +36,8 @@ module Mutant
|
|
79
36
|
#
|
80
37
|
# @api private
|
81
38
|
#
|
82
|
-
def
|
83
|
-
test_result = mutation
|
39
|
+
def kill(mutation)
|
40
|
+
test_result = run_mutation_tests(mutation)
|
84
41
|
Result::Mutation.new(
|
85
42
|
mutation: mutation,
|
86
43
|
test_result: test_result
|
@@ -89,92 +46,32 @@ module Mutant
|
|
89
46
|
|
90
47
|
private
|
91
48
|
|
92
|
-
#
|
93
|
-
#
|
94
|
-
# @param [Class, Module] scope
|
49
|
+
# Kill mutation under isolation with integration
|
95
50
|
#
|
96
|
-
# @
|
97
|
-
#
|
51
|
+
# @param [Isolation] isolation
|
52
|
+
# @param [Integration] integration
|
98
53
|
#
|
99
|
-
# @return [
|
100
|
-
# otherwise
|
54
|
+
# @return [Result::Test]
|
101
55
|
#
|
102
56
|
# @api private
|
103
57
|
#
|
104
|
-
# rubocop:disable
|
105
|
-
#
|
106
|
-
def scope_name(scope)
|
107
|
-
scope.name
|
108
|
-
rescue => exception
|
109
|
-
warn("#{scope.class}#name from: #{scope.inspect} raised an error: #{exception.inspect}. #{SEMANTICS_MESSAGE}")
|
110
|
-
nil
|
111
|
-
end
|
112
|
-
|
113
|
-
# Try to turn scope into expression
|
114
|
-
#
|
115
|
-
# @param [Class, Module] scope
|
116
|
-
#
|
117
|
-
# @return [Expression]
|
118
|
-
# if scope can be represented in an expression
|
119
|
-
#
|
120
|
-
# @return [nil]
|
121
|
-
# otherwise
|
58
|
+
# rubocop:disable MethodLength
|
122
59
|
#
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
name = scope_name(scope) or return
|
60
|
+
def run_mutation_tests(mutation)
|
61
|
+
start = Time.now
|
62
|
+
tests = selector.call(mutation.subject)
|
127
63
|
|
128
|
-
|
129
|
-
|
130
|
-
|
64
|
+
config.isolation.call do
|
65
|
+
mutation.insert
|
66
|
+
config.integration.call(tests)
|
131
67
|
end
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
#
|
140
|
-
# @api private
|
141
|
-
#
|
142
|
-
def initialize_subjects
|
143
|
-
@subjects = Matcher::Compiler.call(self, config.matcher_config).to_a
|
144
|
-
end
|
145
|
-
|
146
|
-
# Initialize mutations
|
147
|
-
#
|
148
|
-
# @return [undefined]
|
149
|
-
#
|
150
|
-
# @api private
|
151
|
-
#
|
152
|
-
def initialize_mutations
|
153
|
-
@mutations = subjects.flat_map(&:mutations)
|
154
|
-
end
|
155
|
-
|
156
|
-
# Infect environment
|
157
|
-
#
|
158
|
-
# @return [undefined]
|
159
|
-
#
|
160
|
-
# @api private
|
161
|
-
#
|
162
|
-
def infect
|
163
|
-
config.includes.each(&$LOAD_PATH.method(:<<))
|
164
|
-
config.requires.each(&method(:require))
|
165
|
-
end
|
166
|
-
|
167
|
-
# Initialize matchable scopes
|
168
|
-
#
|
169
|
-
# @return [undefined]
|
170
|
-
#
|
171
|
-
# @api private
|
172
|
-
#
|
173
|
-
def initialize_matchable_scopes
|
174
|
-
@matchable_scopes = ObjectSpace.each_object(Module).each_with_object([]) do |scope, aggregate|
|
175
|
-
expression = expression(scope)
|
176
|
-
aggregate << Matcher::Scope.new(self, scope, expression) if expression
|
177
|
-
end.sort_by(&:identification)
|
68
|
+
rescue Isolation::Error => error
|
69
|
+
Result::Test.new(
|
70
|
+
tests: tests,
|
71
|
+
output: error.message,
|
72
|
+
runtime: Time.now - start,
|
73
|
+
passed: false
|
74
|
+
)
|
178
75
|
end
|
179
76
|
|
180
77
|
end # Env
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module Mutant
|
2
|
+
class Env
|
3
|
+
# Boostrap environment
|
4
|
+
class Bootstrap
|
5
|
+
include Adamantium::Flat, Concord::Public.new(:config, :cache), Procto.call(:env)
|
6
|
+
|
7
|
+
SEMANTICS_MESSAGE =
|
8
|
+
"Fix your lib to follow normal ruby semantics!\n" \
|
9
|
+
'{Module,Class}#name should return resolvable constant name as String or nil'.freeze
|
10
|
+
|
11
|
+
# Return scopes that are eligible for mnatching
|
12
|
+
#
|
13
|
+
# @return [Enumerable<Matcher::Scope>]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
attr_reader :matchable_scopes
|
18
|
+
|
19
|
+
# Return new bootstrap env
|
20
|
+
#
|
21
|
+
# @return [Env]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
#
|
25
|
+
def self.new(_config, _cache = Cache.new)
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
# Initialize object
|
30
|
+
#
|
31
|
+
# @return [Object]
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
def initialize(*)
|
36
|
+
super
|
37
|
+
infect
|
38
|
+
initialize_matchable_scopes
|
39
|
+
end
|
40
|
+
|
41
|
+
# Print warning message
|
42
|
+
#
|
43
|
+
# @param [String]
|
44
|
+
#
|
45
|
+
# @return [self]
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
#
|
49
|
+
def warn(message)
|
50
|
+
config.reporter.warn(message)
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
# Return environment after bootstraping
|
55
|
+
#
|
56
|
+
# @return [Env]
|
57
|
+
#
|
58
|
+
# @api private
|
59
|
+
#
|
60
|
+
def env
|
61
|
+
subjects = matched_subjects
|
62
|
+
|
63
|
+
Env.new(
|
64
|
+
actor_env: Actor::Env.new(Thread),
|
65
|
+
config: config,
|
66
|
+
cache: cache,
|
67
|
+
subjects: subjects,
|
68
|
+
matchable_scopes: matchable_scopes,
|
69
|
+
selector: Selector::Expression.new(config.integration),
|
70
|
+
mutations: subjects.flat_map(&:mutations)
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# Return scope name
|
77
|
+
#
|
78
|
+
# @param [Class, Module] scope
|
79
|
+
#
|
80
|
+
# @return [String]
|
81
|
+
# if scope has a name and does not raise exceptions obtaining it
|
82
|
+
#
|
83
|
+
# @return [nil]
|
84
|
+
# otherwise
|
85
|
+
#
|
86
|
+
# @api private
|
87
|
+
#
|
88
|
+
# rubocop:disable LineLength
|
89
|
+
#
|
90
|
+
def scope_name(scope)
|
91
|
+
scope.name
|
92
|
+
rescue => exception
|
93
|
+
warn("#{scope.class}#name from: #{scope.inspect} raised an error: #{exception.inspect}. #{SEMANTICS_MESSAGE}")
|
94
|
+
nil
|
95
|
+
end
|
96
|
+
|
97
|
+
# Infect environment
|
98
|
+
#
|
99
|
+
# @return [undefined]
|
100
|
+
#
|
101
|
+
# @api private
|
102
|
+
#
|
103
|
+
def infect
|
104
|
+
config.includes.each(&$LOAD_PATH.method(:<<))
|
105
|
+
config.requires.each(&method(:require))
|
106
|
+
end
|
107
|
+
|
108
|
+
# Try to turn scope into expression
|
109
|
+
#
|
110
|
+
# @param [Class, Module] scope
|
111
|
+
#
|
112
|
+
# @return [Expression]
|
113
|
+
# if scope can be represented in an expression
|
114
|
+
#
|
115
|
+
# @return [nil]
|
116
|
+
# otherwise
|
117
|
+
#
|
118
|
+
# @api private
|
119
|
+
#
|
120
|
+
def expression(scope)
|
121
|
+
name = scope_name(scope) or return
|
122
|
+
|
123
|
+
unless name.instance_of?(String)
|
124
|
+
warn("#{scope.class}#name from: #{scope.inspect} returned #{name.inspect}. #{SEMANTICS_MESSAGE}")
|
125
|
+
return
|
126
|
+
end
|
127
|
+
|
128
|
+
Expression.try_parse(name)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Return matched subjects
|
132
|
+
#
|
133
|
+
# @return [Enumerable<Subject>]
|
134
|
+
#
|
135
|
+
# @api private
|
136
|
+
#
|
137
|
+
def matched_subjects
|
138
|
+
Matcher::Compiler.call(self, config.matcher).to_a
|
139
|
+
end
|
140
|
+
|
141
|
+
# Initialize matchable scopes
|
142
|
+
#
|
143
|
+
# @return [undefined]
|
144
|
+
#
|
145
|
+
# @api private
|
146
|
+
#
|
147
|
+
def initialize_matchable_scopes
|
148
|
+
@matchable_scopes = ObjectSpace.each_object(Module).each_with_object([]) do |scope, aggregate|
|
149
|
+
expression = expression(scope)
|
150
|
+
aggregate << Matcher::Scope.new(self, scope, expression) if expression
|
151
|
+
end.sort_by(&:identification)
|
152
|
+
end
|
153
|
+
end # Boostrap
|
154
|
+
end # Env
|
155
|
+
end # Mutant
|