mutant 0.2.12 → 0.2.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|