mutant 0.5.23 → 0.5.24
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.md +10 -0
- data/config/flay.yml +1 -1
- data/config/reek.yml +19 -19
- data/lib/mutant.rb +12 -39
- data/lib/mutant/ast.rb +5 -0
- data/lib/mutant/ast/meta.rb +131 -0
- data/lib/mutant/ast/named_children.rb +98 -0
- data/lib/mutant/ast/node_predicates.rb +19 -0
- data/lib/mutant/ast/nodes.rb +21 -0
- data/lib/mutant/ast/sexp.rb +34 -0
- data/lib/mutant/ast/types.rb +48 -0
- data/lib/mutant/cache.rb +3 -2
- data/lib/mutant/cli.rb +11 -151
- data/lib/mutant/config.rb +22 -2
- data/lib/mutant/context/scope.rb +11 -21
- data/lib/mutant/delegator.rb +2 -0
- data/lib/mutant/diff.rb +7 -3
- data/lib/mutant/env.rb +49 -0
- data/lib/mutant/expression.rb +36 -8
- data/lib/mutant/expression/methods.rb +62 -0
- data/lib/mutant/expression/namespace.rb +41 -28
- data/lib/mutant/{strategy.rb → integration.rb} +12 -31
- data/lib/mutant/isolation.rb +1 -1
- data/lib/mutant/matcher.rb +1 -21
- data/lib/mutant/matcher/builder.rb +142 -0
- data/lib/mutant/matcher/method.rb +3 -7
- data/lib/mutant/matcher/method/instance.rb +6 -5
- data/lib/mutant/matcher/method/singleton.rb +2 -7
- data/lib/mutant/matcher/methods.rb +11 -14
- data/lib/mutant/matcher/namespace.rb +31 -39
- data/lib/mutant/matcher/scope.rb +13 -2
- data/lib/mutant/meta.rb +0 -1
- data/lib/mutant/meta/example/dsl.rb +5 -1
- data/lib/mutant/mutator/node.rb +16 -44
- data/lib/mutant/mutator/node/or_asgn.rb +1 -1
- data/lib/mutant/mutator/node/send.rb +5 -60
- data/lib/mutant/mutator/node/super.rb +2 -5
- data/lib/mutant/mutator/registry.rb +1 -1
- data/lib/mutant/reporter.rb +10 -0
- data/lib/mutant/reporter/cli.rb +13 -0
- data/lib/mutant/reporter/cli/printer.rb +2 -0
- data/lib/mutant/reporter/cli/progress/config.rb +1 -1
- data/lib/mutant/reporter/cli/progress/noop.rb +2 -0
- data/lib/mutant/reporter/cli/registry.rb +2 -0
- data/lib/mutant/reporter/null.rb +12 -0
- data/lib/mutant/reporter/trace.rb +4 -0
- data/lib/mutant/require_highjack.rb +2 -2
- data/lib/mutant/rspec.rb +0 -0
- data/lib/mutant/runner.rb +2 -0
- data/lib/mutant/runner/config.rb +8 -8
- data/lib/mutant/runner/killer.rb +5 -0
- data/lib/mutant/runner/subject.rb +1 -1
- data/lib/mutant/subject.rb +8 -8
- data/lib/mutant/subject/method.rb +3 -2
- data/lib/mutant/subject/method/instance.rb +1 -1
- data/lib/mutant/test.rb +7 -65
- data/lib/mutant/test/report.rb +59 -0
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warning_filter.rb +2 -0
- data/lib/mutant/zombifier.rb +3 -0
- data/lib/mutant/zombifier/file.rb +1 -1
- data/meta/or_asgn.rb +11 -0
- data/meta/send.rb +1 -1
- data/mutant-rspec.gemspec +1 -1
- data/mutant.gemspec +1 -1
- data/spec/integration/mutant/corpus_spec.rb +2 -0
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +2 -2
- data/spec/spec_helper.rb +4 -3
- data/spec/unit/mutant/cli_new_spec.rb +11 -11
- data/spec/unit/mutant/expression/methods_spec.rb +43 -0
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +1 -1
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +19 -5
- data/spec/unit/mutant/{strategy_spec.rb → integration_spec.rb} +1 -1
- data/spec/unit/mutant/isolation_spec.rb +3 -1
- data/spec/unit/mutant/matcher/method/instance_spec.rb +5 -5
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +8 -8
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +5 -8
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +5 -5
- data/spec/unit/mutant/matcher/namespace_spec.rb +18 -23
- data/spec/unit/mutant/mutation_spec.rb +1 -1
- data/spec/unit/mutant/runner/config_spec.rb +4 -5
- data/spec/unit/mutant/runner/mutation_spec.rb +21 -21
- data/spec/unit/mutant/runner/subject_spec.rb +6 -6
- data/spec/unit/mutant/subject/method/instance_spec.rb +0 -4
- data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -1
- data/spec/unit/mutant/subject_spec.rb +3 -3
- metadata +20 -6
- data/lib/mutant/node_helpers.rb +0 -52
@@ -4,7 +4,7 @@ module Mutant
|
|
4
4
|
|
5
5
|
# Example DSL
|
6
6
|
class DSL
|
7
|
-
include
|
7
|
+
include AST::Sexp
|
8
8
|
|
9
9
|
# Run DSL on block
|
10
10
|
#
|
@@ -51,6 +51,8 @@ module Mutant
|
|
51
51
|
#
|
52
52
|
# @return [self]
|
53
53
|
#
|
54
|
+
# @api private
|
55
|
+
#
|
54
56
|
def source(input)
|
55
57
|
raise 'source already defined' if @source
|
56
58
|
@source = node(input)
|
@@ -64,6 +66,8 @@ module Mutant
|
|
64
66
|
#
|
65
67
|
# @return [self]
|
66
68
|
#
|
69
|
+
# @api private
|
70
|
+
#
|
67
71
|
def mutation(input)
|
68
72
|
node = node(input)
|
69
73
|
if @expected.include?(node)
|
data/lib/mutant/mutator/node.rb
CHANGED
@@ -5,11 +5,13 @@ module Mutant
|
|
5
5
|
|
6
6
|
# Abstract base class for node mutators
|
7
7
|
class Node < self
|
8
|
-
include AbstractType,
|
8
|
+
include AbstractType, Unparser::Constants
|
9
|
+
include AST::NamedChildren, AST::NodePredicates, AST::Sexp, AST::Nodes
|
9
10
|
|
10
|
-
#
|
11
|
+
# Helper to define a named child
|
12
|
+
#
|
13
|
+
# @param [Parser::AST::Node] node
|
11
14
|
#
|
12
|
-
# @param [Symbol] name
|
13
15
|
# @param [Fixnum] index
|
14
16
|
#
|
15
17
|
# @return [undefined]
|
@@ -17,9 +19,7 @@ module Mutant
|
|
17
19
|
# @api private
|
18
20
|
#
|
19
21
|
def self.define_named_child(name, index)
|
20
|
-
|
21
|
-
children.at(index)
|
22
|
-
end
|
22
|
+
super
|
23
23
|
|
24
24
|
define_method("emit_#{name}_mutations") do |&block|
|
25
25
|
mutate_child(index, &block)
|
@@ -29,43 +29,6 @@ module Mutant
|
|
29
29
|
emit_child_update(index, node)
|
30
30
|
end
|
31
31
|
end
|
32
|
-
private_class_method :define_named_child
|
33
|
-
|
34
|
-
# Define remaining children
|
35
|
-
#
|
36
|
-
# @param [Array<Symbol>] names
|
37
|
-
#
|
38
|
-
# @return [undefined]
|
39
|
-
#
|
40
|
-
# @api private
|
41
|
-
#
|
42
|
-
def self.define_remaining_children(names)
|
43
|
-
define_method(:remaining_children_with_index) do
|
44
|
-
children.each_with_index.drop(names.length)
|
45
|
-
end
|
46
|
-
|
47
|
-
define_method(:remaining_children_indices) do
|
48
|
-
children.each_index.drop(names.length)
|
49
|
-
end
|
50
|
-
|
51
|
-
define_method(:remaining_children) do
|
52
|
-
children.drop(names.length)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
private_class_method :define_remaining_children
|
56
|
-
|
57
|
-
# Create name helpers
|
58
|
-
#
|
59
|
-
# @return [undefined]
|
60
|
-
#
|
61
|
-
# @api private
|
62
|
-
#
|
63
|
-
def self.children(*names)
|
64
|
-
names.each_with_index do |name, index|
|
65
|
-
define_named_child(name, index)
|
66
|
-
end
|
67
|
-
define_remaining_children(names)
|
68
|
-
end
|
69
32
|
private_class_method :children
|
70
33
|
|
71
34
|
private
|
@@ -98,6 +61,15 @@ module Mutant
|
|
98
61
|
end
|
99
62
|
end
|
100
63
|
|
64
|
+
# Return ast meta description
|
65
|
+
#
|
66
|
+
# @return [AST::Meta]
|
67
|
+
#
|
68
|
+
def meta
|
69
|
+
AST::Meta.for(node)
|
70
|
+
end
|
71
|
+
memoize :meta
|
72
|
+
|
101
73
|
# Return children
|
102
74
|
#
|
103
75
|
# @return [Array<Parser::AST::Node>]
|
@@ -246,7 +218,7 @@ module Mutant
|
|
246
218
|
# @api private
|
247
219
|
#
|
248
220
|
def asgn_left?
|
249
|
-
OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
|
221
|
+
AST::Types::OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
|
250
222
|
end
|
251
223
|
|
252
224
|
end # Node
|
@@ -4,6 +4,7 @@ module Mutant
|
|
4
4
|
|
5
5
|
# Namespace for send mutators
|
6
6
|
class Send < self
|
7
|
+
include AST::Types
|
7
8
|
|
8
9
|
handle(:send)
|
9
10
|
|
@@ -19,12 +20,6 @@ module Mutant
|
|
19
20
|
:== => [:eql?, :equal?]
|
20
21
|
)
|
21
22
|
|
22
|
-
INDEX_REFERENCE = :[]
|
23
|
-
INDEX_ASSIGN = :[]=
|
24
|
-
VARIABLE_ASSIGN = :'='
|
25
|
-
ASSIGNMENT_OPERATORS = [INDEX_ASSIGN, VARIABLE_ASSIGN].to_set.freeze
|
26
|
-
ATTRIBUTE_ASSIGNMENT = /\A[a-z\d_]+=\z/.freeze
|
27
|
-
|
28
23
|
private
|
29
24
|
|
30
25
|
# Perform dispatch
|
@@ -35,7 +30,7 @@ module Mutant
|
|
35
30
|
#
|
36
31
|
def dispatch
|
37
32
|
emit_singletons
|
38
|
-
if
|
33
|
+
if meta.index_assignment?
|
39
34
|
run(Index::Assign)
|
40
35
|
else
|
41
36
|
non_index_dispatch
|
@@ -50,9 +45,9 @@ module Mutant
|
|
50
45
|
#
|
51
46
|
def non_index_dispatch
|
52
47
|
case
|
53
|
-
when
|
48
|
+
when meta.binary_method_operator?
|
54
49
|
run(Binary)
|
55
|
-
when attribute_assignment?
|
50
|
+
when meta.attribute_assignment?
|
56
51
|
run(AttributeAssignment)
|
57
52
|
else
|
58
53
|
normal_dispatch
|
@@ -103,26 +98,6 @@ module Mutant
|
|
103
98
|
emit(receiver) if receiver && !NOT_ASSIGNABLE.include?(receiver.type)
|
104
99
|
end
|
105
100
|
|
106
|
-
# Test for binary operator
|
107
|
-
#
|
108
|
-
# @return [Boolean]
|
109
|
-
#
|
110
|
-
# @api private
|
111
|
-
#
|
112
|
-
def binary_operator?
|
113
|
-
arguments.one? && BINARY_METHOD_OPERATORS.include?(selector)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Test for attribute assignment
|
117
|
-
#
|
118
|
-
# @return [Boolean]
|
119
|
-
#
|
120
|
-
# @api private
|
121
|
-
#
|
122
|
-
def attribute_assignment?
|
123
|
-
arguments.one? && ATTRIBUTE_ASSIGNMENT =~ selector
|
124
|
-
end
|
125
|
-
|
126
101
|
# Mutate arguments
|
127
102
|
#
|
128
103
|
# @return [undefined]
|
@@ -173,40 +148,10 @@ module Mutant
|
|
173
148
|
KEYWORDS.include?(selector) ||
|
174
149
|
METHOD_OPERATORS.include?(selector) ||
|
175
150
|
OP_ASSIGN.include?(parent_type) ||
|
176
|
-
attribute_assignment?
|
151
|
+
meta.attribute_assignment?
|
177
152
|
)
|
178
153
|
end
|
179
154
|
|
180
|
-
# Test for assignment
|
181
|
-
#
|
182
|
-
# @return [Boolean]
|
183
|
-
#
|
184
|
-
# @api private
|
185
|
-
#
|
186
|
-
def assignment?
|
187
|
-
arguments.one? && (ASSIGNMENT_OPERATORS.include?(selector) || attribute_assignment?)
|
188
|
-
end
|
189
|
-
|
190
|
-
# Test if node is part of an mlhs
|
191
|
-
#
|
192
|
-
# @return [Boolean]
|
193
|
-
#
|
194
|
-
# @api private
|
195
|
-
#
|
196
|
-
def mlhs?
|
197
|
-
assignment? && !arguments?
|
198
|
-
end
|
199
|
-
|
200
|
-
# Test for empty arguments
|
201
|
-
#
|
202
|
-
# @return [Boolean]
|
203
|
-
#
|
204
|
-
# @api private
|
205
|
-
#
|
206
|
-
def arguments?
|
207
|
-
arguments.any?
|
208
|
-
end
|
209
|
-
|
210
155
|
end # Send
|
211
156
|
end # Node
|
212
157
|
end # Mutator
|
@@ -7,9 +7,6 @@ module Mutant
|
|
7
7
|
|
8
8
|
handle(:super)
|
9
9
|
|
10
|
-
Z_SUPER = NodeHelpers.s(:zsuper)
|
11
|
-
EMPTY_SUPER = NodeHelpers.s(:super)
|
12
|
-
|
13
10
|
private
|
14
11
|
|
15
12
|
# Emit mutations
|
@@ -20,8 +17,8 @@ module Mutant
|
|
20
17
|
#
|
21
18
|
def dispatch
|
22
19
|
emit_singletons
|
23
|
-
emit(
|
24
|
-
emit(
|
20
|
+
emit(N_ZSUPER)
|
21
|
+
emit(N_EMPTY_SUPER)
|
25
22
|
children.each_index do |index|
|
26
23
|
mutate_child(index)
|
27
24
|
delete_child(index)
|
@@ -64,7 +64,7 @@ module Mutant
|
|
64
64
|
# @api private
|
65
65
|
#
|
66
66
|
def self.assert_valid_type(type)
|
67
|
-
unless
|
67
|
+
unless AST::Types::ALL.include?(type) || type.kind_of?(Class)
|
68
68
|
raise InvalidTypeError, "invalid type registration: #{type}"
|
69
69
|
end
|
70
70
|
end
|
data/lib/mutant/reporter.rb
CHANGED
@@ -3,6 +3,16 @@ module Mutant
|
|
3
3
|
class Reporter
|
4
4
|
include Adamantium::Flat, AbstractType
|
5
5
|
|
6
|
+
# Write warning message
|
7
|
+
#
|
8
|
+
# @param [String] message
|
9
|
+
#
|
10
|
+
# @return [self]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
#
|
14
|
+
abstract_method :warn
|
15
|
+
|
6
16
|
# Report object
|
7
17
|
#
|
8
18
|
# @param [Object] object
|
data/lib/mutant/reporter/cli.rb
CHANGED
@@ -19,6 +19,19 @@ module Mutant
|
|
19
19
|
self
|
20
20
|
end
|
21
21
|
|
22
|
+
# Report warning
|
23
|
+
#
|
24
|
+
# @param [String] message
|
25
|
+
#
|
26
|
+
# @return [self]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
#
|
30
|
+
def warn(message)
|
31
|
+
output.puts(message)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
22
35
|
# Report object
|
23
36
|
#
|
24
37
|
# @param [Object] object
|
@@ -21,7 +21,7 @@ module Mutant
|
|
21
21
|
if running?
|
22
22
|
info 'Mutant configuration:'
|
23
23
|
info 'Matcher: %s', config.matcher.inspect
|
24
|
-
info '
|
24
|
+
info 'Integration: %s', config.integration.name
|
25
25
|
info 'Expect Coverage: %0.2f%%', config.expected_coverage.inspect
|
26
26
|
end
|
27
27
|
self
|
data/lib/mutant/reporter/null.rb
CHANGED
@@ -5,6 +5,18 @@ module Mutant
|
|
5
5
|
class Null < self
|
6
6
|
include Equalizer.new
|
7
7
|
|
8
|
+
# Write warning message
|
9
|
+
#
|
10
|
+
# @param [String] _message
|
11
|
+
#
|
12
|
+
# @return [self]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
#
|
16
|
+
def report(_message)
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
8
20
|
# Report object
|
9
21
|
#
|
10
22
|
# @param [Object] _object
|
@@ -20,6 +20,8 @@ module Mutant
|
|
20
20
|
#
|
21
21
|
# @return [self]
|
22
22
|
#
|
23
|
+
# @api private
|
24
|
+
#
|
23
25
|
def report(object)
|
24
26
|
report_calls << object
|
25
27
|
self
|
@@ -31,6 +33,8 @@ module Mutant
|
|
31
33
|
#
|
32
34
|
# @return [self]
|
33
35
|
#
|
36
|
+
# @api private
|
37
|
+
#
|
34
38
|
def progress(object)
|
35
39
|
progress_calls << object
|
36
40
|
self
|
@@ -15,7 +15,7 @@ module Mutant
|
|
15
15
|
#
|
16
16
|
# @return [self]
|
17
17
|
#
|
18
|
-
# @api
|
18
|
+
# @api private
|
19
19
|
#
|
20
20
|
def run
|
21
21
|
infect
|
@@ -29,7 +29,7 @@ module Mutant
|
|
29
29
|
#
|
30
30
|
# @return [self]
|
31
31
|
#
|
32
|
-
# @api
|
32
|
+
# @api private
|
33
33
|
#
|
34
34
|
def infect
|
35
35
|
callback = @callback
|
data/lib/mutant/rspec.rb
ADDED
File without changes
|
data/lib/mutant/runner.rb
CHANGED
data/lib/mutant/runner/config.rb
CHANGED
@@ -52,14 +52,14 @@ module Mutant
|
|
52
52
|
end
|
53
53
|
memoize :success?
|
54
54
|
|
55
|
-
# Return
|
55
|
+
# Return integration
|
56
56
|
#
|
57
|
-
# @return [
|
57
|
+
# @return [Integration]
|
58
58
|
#
|
59
59
|
# @api private
|
60
60
|
#
|
61
|
-
def
|
62
|
-
config.
|
61
|
+
def integration
|
62
|
+
config.integration
|
63
63
|
end
|
64
64
|
|
65
65
|
# Return coverage
|
@@ -115,13 +115,13 @@ module Mutant
|
|
115
115
|
# @api private
|
116
116
|
#
|
117
117
|
def run_subjects
|
118
|
-
|
119
|
-
|
118
|
+
integration = self.integration
|
119
|
+
integration.setup
|
120
120
|
@subjects = visit_collection(config.subjects)
|
121
|
-
|
121
|
+
integration.teardown
|
122
122
|
end
|
123
123
|
|
124
|
-
# Run
|
124
|
+
# Run configuration
|
125
125
|
#
|
126
126
|
# @return [undefined]
|
127
127
|
#
|