mutest 0.0.6 → 0.0.7
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/.buildkite/hooks/pre-command +1 -1
- data/.buildkite/pipeline.yml +9 -22
- data/.gitmodules +3 -0
- data/CHANGELOG.md +14 -1
- data/Gemfile +11 -6
- data/Gemfile.lock +27 -101
- data/README.md +42 -2
- data/Rakefile +2 -8
- data/circle.yml +4 -1
- data/lib/mutest.rb +1 -1
- data/lib/mutest/ast/meta/send.rb +6 -0
- data/lib/mutest/ast/named_children.rb +1 -1
- data/lib/mutest/ast/nodes.rb +0 -2
- data/lib/mutest/ast/regexp.rb +4 -4
- data/lib/mutest/ast/regexp/transformer.rb +4 -4
- data/lib/mutest/ast/regexp/transformer/character_set.rb +1 -1
- data/lib/mutest/ast/regexp/transformer/direct.rb +1 -1
- data/lib/mutest/ast/regexp/transformer/quantifier.rb +3 -3
- data/lib/mutest/ast/regexp/transformer/recursive.rb +1 -1
- data/lib/mutest/ast/regexp/transformer/text.rb +1 -1
- data/lib/mutest/ast/types.rb +0 -1
- data/lib/mutest/cli.rb +1 -1
- data/lib/mutest/context.rb +1 -1
- data/lib/mutest/matcher/config.rb +0 -2
- data/lib/mutest/matcher/method.rb +1 -3
- data/lib/mutest/matcher/method/instance.rb +1 -1
- data/lib/mutest/matcher/methods.rb +1 -1
- data/lib/mutest/mutator.rb +0 -2
- data/lib/mutest/mutator/node/block_pass.rb +29 -0
- data/lib/mutest/mutator/node/generic.rb +1 -0
- data/lib/mutest/mutator/node/literal/boolean.rb +0 -1
- data/lib/mutest/mutator/node/literal/range.rb +1 -1
- data/lib/mutest/mutator/node/literal/regex.rb +1 -1
- data/lib/mutest/mutator/node/literal/string.rb +3 -0
- data/lib/mutest/mutator/node/literal/symbol.rb +0 -2
- data/lib/mutest/mutator/node/send.rb +35 -6
- data/lib/mutest/mutator/node/splat.rb +3 -1
- data/lib/mutest/parallel/worker.rb +1 -1
- data/lib/mutest/reporter/cli.rb +0 -2
- data/lib/mutest/reporter/cli/format.rb +1 -1
- data/lib/mutest/reporter/cli/printer.rb +2 -2
- data/lib/mutest/reporter/cli/printer/mutation_result.rb +0 -2
- data/lib/mutest/version.rb +1 -1
- data/meta/and.rb +0 -2
- data/meta/array.rb +0 -3
- data/meta/begin.rb +0 -3
- data/meta/block.rb +0 -1
- data/meta/block_pass.rb +30 -1
- data/meta/break.rb +0 -1
- data/meta/case.rb +0 -6
- data/meta/casgn.rb +0 -3
- data/meta/cvasgn.rb +0 -1
- data/meta/def.rb +0 -7
- data/meta/dstr.rb +2 -0
- data/meta/dsym.rb +2 -0
- data/meta/ensure.rb +0 -1
- data/meta/false.rb +0 -1
- data/meta/gvasgn.rb +0 -1
- data/meta/hash.rb +0 -4
- data/meta/if.rb +0 -5
- data/meta/ivasgn.rb +0 -1
- data/meta/kwbegin.rb +0 -1
- data/meta/lvasgn.rb +0 -1
- data/meta/match_current_line.rb +0 -1
- data/meta/next.rb +0 -1
- data/meta/or.rb +0 -2
- data/meta/regexp.rb +0 -1
- data/meta/rescue.rb +0 -6
- data/meta/send.rb +60 -16
- data/meta/splat.rb +25 -0
- data/meta/str.rb +1 -0
- data/meta/true.rb +0 -1
- data/meta/until.rb +0 -1
- data/meta/while.rb +0 -2
- data/meta/yield.rb +0 -1
- data/mutest-rspec.gemspec +1 -1
- data/mutest.gemspec +0 -4
- data/spec/integration/mutest/rspec_spec.rb +1 -1
- data/spec/integrations.yml +1 -1
- data/spec/shared/command_method_behavior.rb +5 -0
- data/spec/shared/idempotent_method_behavior.rb +10 -0
- data/spec/spec_helper.rb +21 -1
- data/spec/support/xspec.rb +1 -1
- data/spec/unit/mutest/actor/sender_spec.rb +1 -1
- data/spec/unit/mutest/ast/meta/send_spec.rb +23 -11
- data/spec/unit/mutest/cli_spec.rb +13 -13
- data/spec/unit/mutest/context_spec.rb +2 -2
- data/spec/unit/mutest/diff_spec.rb +9 -9
- data/spec/unit/mutest/integration/null_spec.rb +1 -1
- data/spec/unit/mutest/integration_spec.rb +1 -1
- data/spec/unit/mutest/matcher/method/instance_spec.rb +5 -5
- data/spec/unit/mutest/matcher/method/singleton_spec.rb +5 -5
- data/spec/unit/mutest/meta/example_spec.rb +3 -3
- data/spec/unit/mutest/mutation_spec.rb +5 -5
- data/spec/unit/mutest/mutator/node_spec.rb +6 -9
- data/spec/unit/mutest/parallel/driver_spec.rb +1 -1
- data/spec/unit/mutest/reporter/null_spec.rb +1 -1
- data/spec/unit/mutest/reporter/sequence_spec.rb +1 -1
- data/spec/unit/mutest/result_spec.rb +1 -1
- data/spec/unit/mutest/runner/sink_spec.rb +1 -1
- data/spec/unit/mutest/subject/method/instance/memoized_spec.rb +1 -1
- data/spec/unit/mutest/subject/method/instance_spec.rb +3 -3
- data/spec/unit/mutest/subject/method/singleton_spec.rb +3 -3
- data/spec/unit/mutest/subject_spec.rb +2 -2
- data/test_app/Gemfile.rspec3.6 +7 -0
- metadata +9 -57
- data/build/Dockerfile +0 -71
- data/build/docker-bootstrap.sh +0 -85
- data/build/docker-exec +0 -29
- data/build/make-docker +0 -3
- data/build/ruby_matrix +0 -1
- data/build/run +0 -5
- data/build/strict-mode.sh +0 -16
- data/config/devtools.yml +0 -2
- data/config/flay.yml +0 -3
- data/config/flog.yml +0 -2
- data/config/reek.yml +0 -137
- data/lib/mutest/mutator/node/noop.rb +0 -19
data/lib/mutest/ast/nodes.rb
CHANGED
data/lib/mutest/ast/regexp.rb
CHANGED
@@ -10,14 +10,14 @@ module Mutest
|
|
10
10
|
#
|
11
11
|
# @param regexp [String]
|
12
12
|
#
|
13
|
-
# @return [Regexp::Expression]
|
13
|
+
# @return [Regexp::Expression::Base]
|
14
14
|
def self.parse(regexp)
|
15
15
|
::Regexp::Parser.parse(regexp)
|
16
16
|
end
|
17
17
|
|
18
18
|
# Check if expression is supported by mapper
|
19
19
|
#
|
20
|
-
# @param expression [Regexp::Expression]
|
20
|
+
# @param expression [Regexp::Expression::Base]
|
21
21
|
#
|
22
22
|
# @return [Boolean]
|
23
23
|
def self.supported?(expression)
|
@@ -28,7 +28,7 @@ module Mutest
|
|
28
28
|
|
29
29
|
# Convert expression into ast node
|
30
30
|
#
|
31
|
-
# @param expression [Regexp::Expression]
|
31
|
+
# @param expression [Regexp::Expression::Base]
|
32
32
|
#
|
33
33
|
# @return [Parser::AST::Node]
|
34
34
|
def self.to_ast(expression)
|
@@ -41,7 +41,7 @@ module Mutest
|
|
41
41
|
#
|
42
42
|
# @param node [Parser::AST::Node]
|
43
43
|
#
|
44
|
-
# @return [Regexp::Expression]
|
44
|
+
# @return [Regexp::Expression::Base]
|
45
45
|
def self.to_expression(node)
|
46
46
|
Transformer.lookup(node.type).to_expression(node)
|
47
47
|
end
|
@@ -32,7 +32,7 @@ module Mutest
|
|
32
32
|
|
33
33
|
# Transform expression
|
34
34
|
#
|
35
|
-
# @param expression [Regexp::Expression]
|
35
|
+
# @param expression [Regexp::Expression::Base]
|
36
36
|
#
|
37
37
|
# @return [Parser::AST::Node]
|
38
38
|
def self.to_ast(expression)
|
@@ -43,7 +43,7 @@ module Mutest
|
|
43
43
|
#
|
44
44
|
# @param node [Parser::AST::Node]
|
45
45
|
#
|
46
|
-
# @return [Regexp::Expression]
|
46
|
+
# @return [Regexp::Expression::Base]
|
47
47
|
def self.to_expression(node)
|
48
48
|
self::ASTToExpression.call(node)
|
49
49
|
end
|
@@ -101,7 +101,7 @@ module Mutest
|
|
101
101
|
|
102
102
|
# Call generic transform method and freeze result
|
103
103
|
#
|
104
|
-
# @return [Regexp::Expression]
|
104
|
+
# @return [Regexp::Expression::Base]
|
105
105
|
def call
|
106
106
|
transform.freeze
|
107
107
|
end
|
@@ -110,7 +110,7 @@ module Mutest
|
|
110
110
|
|
111
111
|
# Transformation of ast into expression
|
112
112
|
#
|
113
|
-
# @return [Regexp::Expression]
|
113
|
+
# @return [Regexp::Expression::Base]
|
114
114
|
abstract_method :transform
|
115
115
|
|
116
116
|
# Transformed children of node
|
@@ -49,7 +49,7 @@ module Mutest
|
|
49
49
|
|
50
50
|
# Transform ast into quantifier attached to expression
|
51
51
|
#
|
52
|
-
# @return [Regexp::Expression]
|
52
|
+
# @return [Regexp::Expression::Base]
|
53
53
|
def transform
|
54
54
|
Regexp.to_expression(subject).dup.tap do |expression|
|
55
55
|
expression.quantify(type, text, min, max, mode)
|
@@ -69,7 +69,7 @@ module Mutest
|
|
69
69
|
|
70
70
|
# Type of quantifier
|
71
71
|
#
|
72
|
-
# @return [:zero_or_more
|
72
|
+
# @return [Symbol] :zero_or_more, :one_or_more, or :interval
|
73
73
|
def type
|
74
74
|
quantifier.type
|
75
75
|
end
|
@@ -83,7 +83,7 @@ module Mutest
|
|
83
83
|
|
84
84
|
# The quantifier "mode"
|
85
85
|
#
|
86
|
-
# @return [:greedy
|
86
|
+
# @return [Symbol] :greedy, :possessive, or :reluctant
|
87
87
|
def mode
|
88
88
|
quantifier.mode
|
89
89
|
end
|
@@ -34,7 +34,7 @@ module Mutest
|
|
34
34
|
|
35
35
|
# Transform nodes and their children into expressions
|
36
36
|
#
|
37
|
-
# @return [Regexp::Expression]
|
37
|
+
# @return [Regexp::Expression::Base]
|
38
38
|
def transform
|
39
39
|
expression_class.new(expression_token).tap do |expression|
|
40
40
|
expression.expressions = subexpressions
|
data/lib/mutest/ast/types.rb
CHANGED
data/lib/mutest/cli.rb
CHANGED
data/lib/mutest/context.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Mutest
|
2
2
|
class Matcher
|
3
3
|
# Abstract base class for method matchers
|
4
|
-
#
|
5
|
-
# :reek:TooManyMethods { max_methods: 11 }
|
6
4
|
class Method < self
|
7
5
|
include AbstractType,
|
8
6
|
Adamantium::Flat,
|
@@ -105,7 +103,7 @@ module Mutest
|
|
105
103
|
|
106
104
|
# Full source location
|
107
105
|
#
|
108
|
-
# @return [Array
|
106
|
+
# @return [Array<String,Fixnum>]
|
109
107
|
def source_location
|
110
108
|
target_method.source_location
|
111
109
|
end
|
data/lib/mutest/mutator.rb
CHANGED
@@ -14,8 +14,6 @@ module Mutest
|
|
14
14
|
# @param parent [nil,Mutest::Mutator::Node]
|
15
15
|
#
|
16
16
|
# @return [Set<Parser::AST::Node>]
|
17
|
-
#
|
18
|
-
# :reek:LongParameterList
|
19
17
|
def self.mutate(node, filter = ->(_) {}, parent = nil)
|
20
18
|
self::REGISTRY.lookup(node.type).call(node, filter, parent)
|
21
19
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Mutest
|
2
|
+
class Mutator
|
3
|
+
class Node
|
4
|
+
class BlockPass < self
|
5
|
+
handle(:block_pass)
|
6
|
+
|
7
|
+
children :arg
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# Emit mutations
|
12
|
+
#
|
13
|
+
# @return [undefined]
|
14
|
+
def dispatch
|
15
|
+
emit_arg_mutations
|
16
|
+
emit_symbol_to_proc_mutations
|
17
|
+
end
|
18
|
+
|
19
|
+
def emit_symbol_to_proc_mutations
|
20
|
+
return unless n_sym?(arg)
|
21
|
+
|
22
|
+
Send::SELECTOR_REPLACEMENTS.fetch(*arg, EMPTY_ARRAY).each do |method|
|
23
|
+
emit_arg(s(:sym, method))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end # BlockPass
|
27
|
+
end # Node
|
28
|
+
end # Mutator
|
29
|
+
end # Mutest
|
@@ -6,6 +6,8 @@ module Mutest
|
|
6
6
|
class String < self
|
7
7
|
handle(:str)
|
8
8
|
|
9
|
+
children :value
|
10
|
+
|
9
11
|
private
|
10
12
|
|
11
13
|
# Emit mutations
|
@@ -13,6 +15,7 @@ module Mutest
|
|
13
15
|
# @return [undefined]
|
14
16
|
def dispatch
|
15
17
|
emit_singletons
|
18
|
+
emit_type(value + Util::Symbol::POSTFIX)
|
16
19
|
end
|
17
20
|
end # String
|
18
21
|
end # Literal
|
@@ -114,6 +114,7 @@ module Mutest
|
|
114
114
|
#
|
115
115
|
# @return [undefined]
|
116
116
|
def emit_selector_specific_mutations
|
117
|
+
emit_method_method_selector_replacements
|
117
118
|
emit_const_get_mutation
|
118
119
|
emit_integer_mutation
|
119
120
|
emit_array_mutation
|
@@ -132,7 +133,25 @@ module Mutest
|
|
132
133
|
RECEIVER_SELECTOR_REPLACEMENTS
|
133
134
|
.fetch(receiver.children.last, EMPTY_HASH)
|
134
135
|
.fetch(selector, EMPTY_ARRAY)
|
135
|
-
.each(&
|
136
|
+
.each(&public_method(:emit_selector))
|
137
|
+
end
|
138
|
+
|
139
|
+
# Emit selector mutations for [public_]method calls
|
140
|
+
#
|
141
|
+
# - Mutates `foo.method(:to_s)` to `foo.method(:to_str)`
|
142
|
+
# - Mutates `foo.public_method('to_s')` to `foo.public_method('to_str')`
|
143
|
+
#
|
144
|
+
# @return [undefined]
|
145
|
+
def emit_method_method_selector_replacements
|
146
|
+
return unless meta.method_object_selector? && meta.arguments.one?
|
147
|
+
|
148
|
+
arg = Mutest::Util.one(meta.arguments)
|
149
|
+
|
150
|
+
return unless n_sym?(arg) || n_str?(arg)
|
151
|
+
|
152
|
+
selector_replacements(*arg).each do |replacement|
|
153
|
+
emit_type(receiver, selector, s(arg.type, replacement))
|
154
|
+
end
|
136
155
|
end
|
137
156
|
|
138
157
|
# Emit mutation from `!!foo` to `foo`
|
@@ -149,7 +168,7 @@ module Mutest
|
|
149
168
|
#
|
150
169
|
# @return [undefined]
|
151
170
|
def emit_lambda_mutation
|
152
|
-
|
171
|
+
emit_type(nil, :lambda) if meta.proc?
|
153
172
|
end
|
154
173
|
|
155
174
|
# Emit mutation for `#dig`
|
@@ -167,7 +186,7 @@ module Mutest
|
|
167
186
|
|
168
187
|
return emit(fetch_mutation) if tail.empty?
|
169
188
|
|
170
|
-
|
189
|
+
emit_type(fetch_mutation, :dig, *tail)
|
171
190
|
end
|
172
191
|
|
173
192
|
# Emit mutation `foo[n..-1]` -> `foo.drop(n)`
|
@@ -180,7 +199,7 @@ module Mutest
|
|
180
199
|
|
181
200
|
return unless ending.eql?(s(:int, -1))
|
182
201
|
|
183
|
-
|
202
|
+
emit_type(receiver, :drop, start)
|
184
203
|
end
|
185
204
|
|
186
205
|
# Emit mutation from `to_i` to `Integer(...)`
|
@@ -189,7 +208,7 @@ module Mutest
|
|
189
208
|
def emit_integer_mutation
|
190
209
|
return unless selector.equal?(:to_i)
|
191
210
|
|
192
|
-
|
211
|
+
emit_type(nil, :Integer, receiver)
|
193
212
|
end
|
194
213
|
|
195
214
|
# Emit mutation from `Array(a)` to `[a]`
|
@@ -214,7 +233,7 @@ module Mutest
|
|
214
233
|
#
|
215
234
|
# @return [undefined]
|
216
235
|
def emit_selector_replacement
|
217
|
-
|
236
|
+
selector_replacements(selector).each(&public_method(:emit_selector))
|
218
237
|
end
|
219
238
|
|
220
239
|
# Emit naked receiver mutation
|
@@ -267,6 +286,16 @@ module Mutest
|
|
267
286
|
meta.attribute_assignment?
|
268
287
|
)
|
269
288
|
end
|
289
|
+
|
290
|
+
def selector_replacements(selector)
|
291
|
+
replacements = SELECTOR_REPLACEMENTS.fetch(selector.to_sym, EMPTY_ARRAY)
|
292
|
+
|
293
|
+
if selector.instance_of?(String)
|
294
|
+
replacements.map(&:to_s)
|
295
|
+
else
|
296
|
+
replacements
|
297
|
+
end
|
298
|
+
end
|
270
299
|
end # Send
|
271
300
|
end # Node
|
272
301
|
end # Mutator
|