mutant 0.2.12 → 0.2.13
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.
- data/Changelog.md +4 -0
- data/Gemfile +1 -1
- data/Gemfile.devtools +39 -19
- data/README.md +3 -2
- data/TODO +3 -1
- data/config/flay.yml +1 -1
- data/config/site.reek +10 -3
- data/lib/mutant.rb +6 -73
- data/lib/mutant/constants.rb +49 -0
- data/lib/mutant/killer/forking.rb +6 -2
- data/lib/mutant/loader.rb +6 -79
- data/lib/mutant/matcher/scope_methods.rb +2 -2
- data/lib/mutant/mutation.rb +3 -2
- data/lib/mutant/mutation/filter/whitelist.rb +2 -0
- data/lib/mutant/mutator/node.rb +20 -9
- data/lib/mutant/mutator/node/assignment.rb +8 -1
- data/lib/mutant/mutator/node/block.rb +1 -0
- data/lib/mutant/mutator/node/default_arguments.rb +1 -0
- data/lib/mutant/mutator/node/formal_arguments_19.rb +1 -0
- data/lib/mutant/mutator/node/formal_arguments_19/default_mutations.rb +1 -0
- data/lib/mutant/mutator/node/{if_statement.rb → if.rb} +21 -6
- data/lib/mutant/mutator/node/iter_19.rb +1 -0
- data/lib/mutant/mutator/node/literal.rb +4 -3
- data/lib/mutant/mutator/node/literal/hash.rb +2 -1
- data/lib/mutant/mutator/node/literal/range.rb +2 -1
- data/lib/mutant/mutator/node/noop.rb +2 -0
- data/lib/mutant/mutator/node/receiver_case.rb +1 -19
- data/lib/mutant/mutator/node/send.rb +8 -136
- data/lib/mutant/mutator/node/send/binary_operator_method.rb +61 -0
- data/lib/mutant/mutator/node/send/with_arguments.rb +81 -0
- data/lib/mutant/mutator/node/super.rb +2 -0
- data/lib/mutant/mutator/node/{arguments.rb → when.rb} +4 -4
- data/lib/mutant/mutator/node/while.rb +2 -0
- data/lib/mutant/mutator/util/array.rb +2 -1
- data/lib/mutant/mutator/util/symbol.rb +1 -1
- data/lib/mutant/reporter/null.rb +1 -0
- data/lib/mutant/runner.rb +3 -4
- data/lib/mutant/singleton_methods.rb +28 -0
- data/lib/mutant/strategy.rb +2 -0
- data/lib/mutant/strategy/rspec/example_lookup.rb +4 -2
- data/mutant.gemspec +4 -4
- data/spec/shared/mutator_behavior.rb +1 -2
- data/spec/support/zombie.rb +35 -2
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +5 -6
- data/spec/unit/mutant/mutator/node/literal/float_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +61 -61
- metadata +12 -10
- data/spec/unit/mutant/loader/rubinius/class_methods/run_spec.rb +0 -42
@@ -106,7 +106,7 @@ module Mutant
|
|
106
106
|
abstract_method :method_names
|
107
107
|
|
108
108
|
class Singleton < self
|
109
|
-
MATCHER =
|
109
|
+
MATCHER = Matcher::Method::Singleton
|
110
110
|
|
111
111
|
# Return method for name
|
112
112
|
#
|
@@ -141,7 +141,7 @@ module Mutant
|
|
141
141
|
end
|
142
142
|
|
143
143
|
class Instance < self
|
144
|
-
MATCHER =
|
144
|
+
MATCHER = Matcher::Method::Instance
|
145
145
|
|
146
146
|
# Return method for name
|
147
147
|
#
|
data/lib/mutant/mutation.rb
CHANGED
@@ -37,7 +37,7 @@ module Mutant
|
|
37
37
|
# @api private
|
38
38
|
#
|
39
39
|
def insert
|
40
|
-
Loader::Eval.run(root, subject
|
40
|
+
Loader::Eval.run(root, subject)
|
41
41
|
self
|
42
42
|
end
|
43
43
|
|
@@ -110,9 +110,10 @@ module Mutant
|
|
110
110
|
@subject, @node = subject, node
|
111
111
|
end
|
112
112
|
|
113
|
+
# Noop mutation
|
113
114
|
class Noop < self
|
114
115
|
|
115
|
-
#
|
116
|
+
# Initialize object
|
116
117
|
#
|
117
118
|
# @param [Subject] subject
|
118
119
|
#
|
data/lib/mutant/mutator/node.rb
CHANGED
@@ -103,7 +103,9 @@ module Mutant
|
|
103
103
|
mutator.each(value) do |mutation|
|
104
104
|
dup = dup_node
|
105
105
|
dup.public_send(:"#{name}=", mutation)
|
106
|
-
|
106
|
+
if block_given?
|
107
|
+
dup = yield(dup)
|
108
|
+
end
|
107
109
|
emit(dup)
|
108
110
|
end
|
109
111
|
end
|
@@ -118,22 +120,31 @@ module Mutant
|
|
118
120
|
emit(new_nil)
|
119
121
|
end
|
120
122
|
|
123
|
+
# Return new Rubiinius::AST::SendWithArguments node
|
124
|
+
#
|
125
|
+
# @param [Rubnius::AST::Node] receiver
|
126
|
+
# @param [Symbol] name
|
127
|
+
# @param [Object] arguments
|
128
|
+
#
|
129
|
+
# @return [Rubinius::AST::SendWithArguments]
|
130
|
+
#
|
131
|
+
# @api private
|
132
|
+
#
|
133
|
+
def new_send_with_arguments(receiver, name, arguments)
|
134
|
+
new(Rubinius::AST::SendWithArguments, receiver, name, arguments)
|
135
|
+
end
|
136
|
+
|
121
137
|
# Return AST representing send
|
122
138
|
#
|
123
139
|
# @param [Rubinius::AST::Node] receiver
|
124
140
|
# @param [Symbol] name
|
125
|
-
# @param [Rubinius::AST::Node] arguments
|
126
141
|
#
|
127
|
-
# @return [Rubnius::AST::
|
142
|
+
# @return [Rubnius::AST::Send]
|
128
143
|
#
|
129
144
|
# @api private
|
130
145
|
#
|
131
|
-
def new_send(receiver, name
|
132
|
-
|
133
|
-
new(Rubinius::AST::SendWithArguments, receiver, name, arguments)
|
134
|
-
else
|
135
|
-
new(Rubinius::AST::Send, receiver, name)
|
136
|
-
end
|
146
|
+
def new_send(receiver, name)
|
147
|
+
new(Rubinius::AST::Send, receiver, name)
|
137
148
|
end
|
138
149
|
|
139
150
|
# Return duplicated (unfrozen) node each call
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module Mutant
|
2
2
|
class Mutator
|
3
3
|
class Node
|
4
|
+
|
5
|
+
# Abstract base class for assignment mutators
|
4
6
|
class Assignment < self
|
5
7
|
|
6
8
|
private
|
7
9
|
|
10
|
+
# Abstract base class for variable assignments
|
8
11
|
class Variable < self
|
9
12
|
|
10
13
|
# Emit mutants
|
@@ -16,32 +19,36 @@ module Mutant
|
|
16
19
|
def dispatch
|
17
20
|
emit_attribute_mutations(:name) do |mutation|
|
18
21
|
mutation.name = "#{self.class::PREFIX}#{mutation.name}".to_sym
|
22
|
+
mutation
|
19
23
|
end
|
20
24
|
emit_attribute_mutations(:value)
|
21
25
|
end
|
22
26
|
|
27
|
+
# Mutator for local variable assignments
|
23
28
|
class Local < self
|
24
29
|
PREFIX = ''.freeze
|
25
30
|
handle(Rubinius::AST::LocalVariableAssignment)
|
26
31
|
end
|
27
32
|
|
33
|
+
# Mutator for instance variable assignments
|
28
34
|
class Instance < self
|
29
35
|
PREFIX = '@'.freeze
|
30
36
|
handle(Rubinius::AST::InstanceVariableAssignment)
|
31
37
|
end
|
32
38
|
|
39
|
+
# Mutator for class variable assignments
|
33
40
|
class Class < self
|
34
41
|
PREFIX = '@@'.freeze
|
35
42
|
handle(Rubinius::AST::ClassVariableAssignment)
|
36
43
|
end
|
37
44
|
|
45
|
+
# Mutator for global variable assignments
|
38
46
|
class Global < self
|
39
47
|
PREFIX = '$'.freeze
|
40
48
|
handle(Rubinius::AST::GlobalVariableAssignment)
|
41
49
|
end
|
42
50
|
|
43
51
|
end
|
44
|
-
|
45
52
|
end
|
46
53
|
end
|
47
54
|
end
|
@@ -2,7 +2,7 @@ module Mutant
|
|
2
2
|
class Mutator
|
3
3
|
class Node
|
4
4
|
# Mutator for Rubinius::AST::If nodes
|
5
|
-
class
|
5
|
+
class If < self
|
6
6
|
|
7
7
|
handle(Rubinius::AST::If)
|
8
8
|
|
@@ -16,13 +16,29 @@ module Mutant
|
|
16
16
|
#
|
17
17
|
def dispatch
|
18
18
|
emit_attribute_mutations(:condition)
|
19
|
-
emit_attribute_mutations(:body)
|
20
|
-
emit_attribute_mutations(:else)
|
19
|
+
emit_attribute_mutations(:body) unless nil_literal?(:body)
|
20
|
+
emit_attribute_mutations(:else) unless nil_literal?(:else)
|
21
21
|
emit_inverted_condition
|
22
22
|
emit_deleted_if_branch
|
23
23
|
emit_deleted_else_branch
|
24
24
|
end
|
25
25
|
|
26
|
+
# Test if attribute is non nil literal
|
27
|
+
#
|
28
|
+
# @param [Symbol] name
|
29
|
+
#
|
30
|
+
# @return [true]
|
31
|
+
# if attribute value a nil literal
|
32
|
+
#
|
33
|
+
# @return [false]
|
34
|
+
# otherwise
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
#
|
38
|
+
def nil_literal?(name)
|
39
|
+
node.public_send(name).kind_of?(Rubinius::AST::NilLiteral)
|
40
|
+
end
|
41
|
+
|
26
42
|
# Emit inverted condition
|
27
43
|
#
|
28
44
|
# Especially the same like swap branches but more universal as it also
|
@@ -53,9 +69,8 @@ module Mutant
|
|
53
69
|
# @api private
|
54
70
|
#
|
55
71
|
def emit_deleted_if_branch
|
56
|
-
body = else_branch
|
57
|
-
|
58
|
-
emit_self(condition, else_branch, nil)
|
72
|
+
body = else_branch || return
|
73
|
+
emit_self(condition, body, nil)
|
59
74
|
end
|
60
75
|
|
61
76
|
# Return if_branch of node
|
@@ -40,7 +40,8 @@ module Mutant
|
|
40
40
|
# @api private
|
41
41
|
#
|
42
42
|
def nan
|
43
|
-
|
43
|
+
zero_float = new_float(0)
|
44
|
+
new_send_with_arguments(zero_float, :/, zero_float)
|
44
45
|
end
|
45
46
|
|
46
47
|
# Return AST representing negative infinity
|
@@ -50,7 +51,7 @@ module Mutant
|
|
50
51
|
# @api private
|
51
52
|
#
|
52
53
|
def negative_infinity
|
53
|
-
|
54
|
+
new_send_with_arguments(new_float(-1), :/, new_float(0))
|
54
55
|
end
|
55
56
|
|
56
57
|
# Return AST representing infinity
|
@@ -60,7 +61,7 @@ module Mutant
|
|
60
61
|
# @api private
|
61
62
|
#
|
62
63
|
def infinity
|
63
|
-
|
64
|
+
new_send_with_arguments(new_float(1), :/, new_float(0))
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
@@ -35,6 +35,8 @@ module Mutant
|
|
35
35
|
handle(Rubinius::AST::OpAssignOr19)
|
36
36
|
handle(Rubinius::AST::BlockPass19)
|
37
37
|
handle(Rubinius::AST::OpAssign1)
|
38
|
+
handle(Rubinius::AST::OpAssign2)
|
39
|
+
handle(Rubinius::AST::SplatValue)
|
38
40
|
handle(Rubinius::AST::ConstantAccess)
|
39
41
|
handle(Rubinius::AST::Yield)
|
40
42
|
handle(Rubinius::AST::Begin)
|
@@ -1,24 +1,6 @@
|
|
1
1
|
module Mutant
|
2
2
|
class Mutator
|
3
3
|
class Node
|
4
|
-
# Mutator for Rubinius::AST::When nodes
|
5
|
-
class When < self
|
6
|
-
|
7
|
-
handle(Rubinius::AST::When)
|
8
|
-
|
9
|
-
private
|
10
|
-
|
11
|
-
# Emit mutations
|
12
|
-
#
|
13
|
-
# @return [undefined]
|
14
|
-
#
|
15
|
-
# @api private
|
16
|
-
#
|
17
|
-
def dispatch
|
18
|
-
emit_attribute_mutations(:body)
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
4
|
|
23
5
|
# Mutator for Rubinius::AST::ReceiverCase nodes
|
24
6
|
class ReceiverCase < self
|
@@ -57,7 +39,7 @@ module Mutant
|
|
57
39
|
# @api private
|
58
40
|
#
|
59
41
|
def emit_when_branch_mutations
|
60
|
-
when_branches.each_with_index do |branch,index|
|
42
|
+
when_branches.each_with_index do |branch, index|
|
61
43
|
Mutator.each(branch) do |mutant|
|
62
44
|
branches = dup_when_branches
|
63
45
|
branches[index]=mutant
|
@@ -1,29 +1,12 @@
|
|
1
1
|
module Mutant
|
2
2
|
class Mutator
|
3
3
|
class Node
|
4
|
-
|
4
|
+
|
5
|
+
# Namespace for send mutators
|
5
6
|
class Send < self
|
6
7
|
|
7
8
|
handle(Rubinius::AST::Send)
|
8
9
|
|
9
|
-
# Test if node corresponds to "self.class"
|
10
|
-
#
|
11
|
-
# @param [Rubinius::AST::Node] node
|
12
|
-
#
|
13
|
-
# @return [true]
|
14
|
-
# if node equals to self.class
|
15
|
-
#
|
16
|
-
# @return [false]
|
17
|
-
# otherwise
|
18
|
-
#
|
19
|
-
# @api private
|
20
|
-
#
|
21
|
-
def self.keyword_name?(node)
|
22
|
-
node.kind_of?(Rubinius::AST::Send) &&
|
23
|
-
Mutant::KEYWORDS.include?(node.name) &&
|
24
|
-
node.receiver.kind_of?(Rubinius::AST::Self)
|
25
|
-
end
|
26
|
-
|
27
10
|
private
|
28
11
|
|
29
12
|
# Emit mutations
|
@@ -59,9 +42,7 @@ module Mutant
|
|
59
42
|
# @api private
|
60
43
|
#
|
61
44
|
def emit_block_mutations
|
62
|
-
if node.block
|
63
|
-
emit_attribute_mutations(:block)
|
64
|
-
end
|
45
|
+
emit_attribute_mutations(:block) if node.block
|
65
46
|
end
|
66
47
|
|
67
48
|
# Emit receiver mutations
|
@@ -71,11 +52,7 @@ module Mutant
|
|
71
52
|
# @api private
|
72
53
|
#
|
73
54
|
def emit_receiver_mutations
|
74
|
-
|
75
|
-
|
76
|
-
unless to_self? or util.keyword_name?(receiver)
|
77
|
-
emit_attribute_mutations(:receiver)
|
78
|
-
end
|
55
|
+
emit_attribute_mutations(:receiver)
|
79
56
|
end
|
80
57
|
|
81
58
|
# Emit block absence mutation
|
@@ -150,119 +127,14 @@ module Mutant
|
|
150
127
|
# @api private
|
151
128
|
#
|
152
129
|
def emit_implicit_self_receiver
|
153
|
-
|
154
|
-
|
130
|
+
unless to_self? and !Mutant::KEYWORDS.include?(node.name)
|
131
|
+
return
|
132
|
+
end
|
133
|
+
|
155
134
|
mutant = dup_node
|
156
135
|
mutant.privately = true
|
157
|
-
# TODO: Fix rubinius to allow this as an attr_accessor
|
158
|
-
mutant.instance_variable_set(:@vcall_style, true)
|
159
136
|
emit(mutant)
|
160
137
|
end
|
161
|
-
|
162
|
-
class SendWithArguments < self
|
163
|
-
|
164
|
-
handle(Rubinius::AST::SendWithArguments)
|
165
|
-
|
166
|
-
class BinaryOperatorMethod < Node
|
167
|
-
|
168
|
-
private
|
169
|
-
|
170
|
-
# Emit mutations
|
171
|
-
#
|
172
|
-
# @return [undefined]
|
173
|
-
#
|
174
|
-
# @api private
|
175
|
-
#
|
176
|
-
def dispatch
|
177
|
-
emit_left_mutations
|
178
|
-
emit_right_mutations
|
179
|
-
end
|
180
|
-
|
181
|
-
# Emit left mutations
|
182
|
-
#
|
183
|
-
# @return [undefined]
|
184
|
-
#
|
185
|
-
# @api private
|
186
|
-
#
|
187
|
-
def emit_left_mutations
|
188
|
-
emit_attribute_mutations(:receiver)
|
189
|
-
end
|
190
|
-
|
191
|
-
# Emit right mutations
|
192
|
-
#
|
193
|
-
# @return [undefined]
|
194
|
-
#
|
195
|
-
# @api private
|
196
|
-
#
|
197
|
-
def emit_right_mutations
|
198
|
-
right = node.arguments.array.first
|
199
|
-
Mutator.each(right).each do |mutated|
|
200
|
-
dup = dup_node
|
201
|
-
dup.arguments.array[0] = mutated
|
202
|
-
emit(dup)
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
end
|
207
|
-
|
208
|
-
private
|
209
|
-
|
210
|
-
# Emit mutations
|
211
|
-
#
|
212
|
-
# @return [undefined]
|
213
|
-
#
|
214
|
-
# @api private
|
215
|
-
#
|
216
|
-
def dispatch
|
217
|
-
super
|
218
|
-
emit_call_remove_mutation
|
219
|
-
emit_argument_mutations
|
220
|
-
end
|
221
|
-
|
222
|
-
# Test if message is a binary operator
|
223
|
-
#
|
224
|
-
# @return [true]
|
225
|
-
# if message is a binary operator
|
226
|
-
#
|
227
|
-
# @return [false]
|
228
|
-
# otherwise
|
229
|
-
#
|
230
|
-
# @api private
|
231
|
-
#
|
232
|
-
def binary_operator?
|
233
|
-
Mutant::BINARY_METHOD_OPERATORS.include?(node.name)
|
234
|
-
end
|
235
|
-
|
236
|
-
# Emit argument mutations
|
237
|
-
#
|
238
|
-
# @api private
|
239
|
-
#
|
240
|
-
# @return [undefined]
|
241
|
-
#
|
242
|
-
# @api private
|
243
|
-
#
|
244
|
-
def emit_argument_mutations
|
245
|
-
if binary_operator?
|
246
|
-
run(BinaryOperatorMethod)
|
247
|
-
return
|
248
|
-
end
|
249
|
-
|
250
|
-
emit_attribute_mutations(:arguments)
|
251
|
-
end
|
252
|
-
|
253
|
-
# Emit transfomr call mutation
|
254
|
-
#
|
255
|
-
# @return [undefined]
|
256
|
-
#
|
257
|
-
# @api private
|
258
|
-
#
|
259
|
-
def emit_call_remove_mutation
|
260
|
-
array = node.arguments.array
|
261
|
-
return unless array.length == 1
|
262
|
-
emit(array.first)
|
263
|
-
end
|
264
|
-
|
265
|
-
end
|
266
138
|
end
|
267
139
|
end
|
268
140
|
end
|