mutant 0.8.23 → 0.8.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 +6 -0
- data/Gemfile.lock +3 -3
- data/README.md +2 -0
- data/config/rubocop.yml +0 -4
- data/lib/mutant.rb +2 -2
- data/lib/mutant/actor.rb +1 -1
- data/lib/mutant/ast/meta/optarg.rb +1 -1
- data/lib/mutant/ast/meta/send.rb +1 -1
- data/lib/mutant/ast/regexp.rb +6 -1
- data/lib/mutant/context.rb +1 -1
- data/lib/mutant/diff.rb +3 -3
- data/lib/mutant/env.rb +1 -1
- data/lib/mutant/env/bootstrap.rb +3 -3
- data/lib/mutant/expression.rb +1 -1
- data/lib/mutant/loader.rb +5 -1
- data/lib/mutant/matcher/config.rb +5 -5
- data/lib/mutant/matcher/method.rb +2 -2
- data/lib/mutant/matcher/method/singleton.rb +1 -1
- data/lib/mutant/mutation.rb +4 -4
- data/lib/mutant/mutator/node/argument.rb +1 -1
- data/lib/mutant/mutator/node/block.rb +23 -4
- data/lib/mutant/mutator/node/literal/array.rb +3 -1
- data/lib/mutant/mutator/node/literal/regex.rb +5 -5
- data/lib/mutant/mutator/node/literal/symbol.rb +1 -1
- data/lib/mutant/mutator/util/symbol.rb +1 -1
- data/lib/mutant/reporter/cli/format.rb +1 -1
- data/lib/mutant/reporter/cli/printer.rb +1 -1
- data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +2 -2
- data/lib/mutant/reporter/cli/printer/status.rb +2 -2
- data/lib/mutant/reporter/cli/printer/status_progressive.rb +1 -1
- data/lib/mutant/reporter/cli/printer/subject_progress.rb +1 -1
- data/lib/mutant/reporter/cli/printer/test_result.rb +3 -3
- data/lib/mutant/repository.rb +2 -1
- data/lib/mutant/subject/method/instance.rb +1 -1
- data/lib/mutant/subject/method/singleton.rb +1 -1
- data/lib/mutant/version.rb +1 -1
- data/meta/block.rb +81 -0
- data/meta/file.rb +5 -0
- data/meta/lambda.rb +14 -0
- data/meta/line.rb +5 -0
- data/meta/lvasgn.rb +15 -0
- data/meta/regexp.rb +9 -0
- data/spec/integrations.yml +3 -8
- data/spec/support/corpus.rb +5 -5
- data/spec/support/warning.rb +1 -1
- data/spec/unit/mutant/ast/regexp/parse_spec.rb +14 -2
- data/spec/unit/mutant/loader_spec.rb +1 -1
- data/spec/unit/mutant/mutation_spec.rb +1 -1
- data/spec/unit/mutant/repository/diff_spec.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd93463f0b9eb83512dc15c039e8fd58d7bba5715bbdffc2a39a8a8ad380d317
|
4
|
+
data.tar.gz: b0ed77d675e680fffdf7d90a7c5b8656aa4ba139226d45d3a728d468e5c3c92a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aaa7a56cc2dbdcab8748d7eb07bf7b64c8ad616bff18d51b89018812a88bcb43fb99487e8241ed52fb96ae3a3ed61c0e67b39ec559863f265b66cbf933189dbf
|
7
|
+
data.tar.gz: 0c6884921c5cf564d7155e0e3a8edf6163f637200540ab51fe044d4b5a14e783f083ddcdcd8aafbc71278f737e78a95ea0728389b6162d35e3db24a499d5ca46
|
data/Changelog.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# v0.8.24 2018-12-29
|
2
|
+
|
3
|
+
* Change to always insert mutations with frozen string literals
|
4
|
+
* Fix various invalid AST or source mutations
|
5
|
+
* Handle regexp `regexp_parser` cannot parse but MRI accepts gracefully
|
6
|
+
|
1
7
|
# v0.8.23 2018-12-23
|
2
8
|
|
3
9
|
* Improved isolation error reporting
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mutant (0.8.
|
4
|
+
mutant (0.8.24)
|
5
5
|
abstract_type (~> 0.0.7)
|
6
6
|
adamantium (~> 0.2.0)
|
7
7
|
anima (~> 0.3.0)
|
@@ -16,8 +16,8 @@ PATH
|
|
16
16
|
procto (~> 0.0.2)
|
17
17
|
regexp_parser (~> 1.2)
|
18
18
|
unparser (~> 0.4.2)
|
19
|
-
mutant-rspec (0.8.
|
20
|
-
mutant (~> 0.8.
|
19
|
+
mutant-rspec (0.8.24)
|
20
|
+
mutant (~> 0.8.24)
|
21
21
|
rspec-core (>= 3.4.0, < 4.0.0)
|
22
22
|
|
23
23
|
GEM
|
data/README.md
CHANGED
@@ -93,6 +93,8 @@ Running mutant for the first time on an existing codebase can be a rather dishea
|
|
93
93
|
bundle exec mutant --include lib --require virtus --since master --use rspec Virtus::Attribute#type
|
94
94
|
```
|
95
95
|
|
96
|
+
Note that this feature requires at least git `2.13.0`.
|
97
|
+
|
96
98
|
Presentations
|
97
99
|
-------------
|
98
100
|
|
data/config/rubocop.yml
CHANGED
@@ -150,10 +150,6 @@ SignalException:
|
|
150
150
|
Alias:
|
151
151
|
EnforcedStyle: prefer_alias_method
|
152
152
|
|
153
|
-
# Teaching people to ignore singleton class is pointless
|
154
|
-
RedundantFreeze:
|
155
|
-
Enabled: false
|
156
|
-
|
157
153
|
# Do not waste my horizontal or vertical space
|
158
154
|
IndentArray:
|
159
155
|
Enabled: false
|
data/lib/mutant.rb
CHANGED
@@ -29,10 +29,10 @@ Thread.abort_on_exception = true
|
|
29
29
|
#
|
30
30
|
# @api private
|
31
31
|
module Mutant
|
32
|
-
EMPTY_STRING = ''
|
32
|
+
EMPTY_STRING = ''
|
33
33
|
EMPTY_ARRAY = [].freeze
|
34
34
|
EMPTY_HASH = {}.freeze
|
35
|
-
SCOPE_OPERATOR = '::'
|
35
|
+
SCOPE_OPERATOR = '::'
|
36
36
|
|
37
37
|
# Test if CI is detected via environment
|
38
38
|
#
|
data/lib/mutant/actor.rb
CHANGED
data/lib/mutant/ast/meta/send.rb
CHANGED
data/lib/mutant/ast/regexp.rb
CHANGED
@@ -8,10 +8,15 @@ module Mutant
|
|
8
8
|
#
|
9
9
|
# @param regexp [String]
|
10
10
|
#
|
11
|
-
# @return [Regexp::Expression]
|
11
|
+
# @return [Regexp::Expression, nil]
|
12
|
+
#
|
13
|
+
# rubocop:disable Lint/HandleExceptions
|
12
14
|
def self.parse(regexp)
|
13
15
|
::Regexp::Parser.parse(regexp)
|
16
|
+
# regexp_parser is more strict than MRI
|
17
|
+
rescue ::Regexp::Scanner::PrematureEndError
|
14
18
|
end
|
19
|
+
# rubocop:enable Lint/HandleExceptions
|
15
20
|
|
16
21
|
# Convert expression into ast node
|
17
22
|
#
|
data/lib/mutant/context.rb
CHANGED
data/lib/mutant/diff.rb
CHANGED
@@ -5,9 +5,9 @@ module Mutant
|
|
5
5
|
class Diff
|
6
6
|
include Adamantium::Flat, Concord.new(:old, :new)
|
7
7
|
|
8
|
-
ADDITION = '+'
|
9
|
-
DELETION = '-'
|
10
|
-
NEWLINE = "\n"
|
8
|
+
ADDITION = '+'
|
9
|
+
DELETION = '-'
|
10
|
+
NEWLINE = "\n"
|
11
11
|
|
12
12
|
# Unified source diff between old and new
|
13
13
|
#
|
data/lib/mutant/env.rb
CHANGED
@@ -16,7 +16,7 @@ module Mutant
|
|
16
16
|
|
17
17
|
SEMANTICS_MESSAGE =
|
18
18
|
"Fix your lib to follow normal ruby semantics!\n" \
|
19
|
-
'{Module,Class}#name should return resolvable constant name as String or nil'
|
19
|
+
'{Module,Class}#name should return resolvable constant name as String or nil'
|
20
20
|
|
21
21
|
# Kill mutation
|
22
22
|
#
|
data/lib/mutant/env/bootstrap.rb
CHANGED
@@ -8,13 +8,13 @@ module Mutant
|
|
8
8
|
|
9
9
|
SEMANTICS_MESSAGE_FORMAT =
|
10
10
|
"%<message>s. Fix your lib to follow normal ruby semantics!\n" \
|
11
|
-
'{Module,Class}#name should return resolvable constant name as String or nil'
|
11
|
+
'{Module,Class}#name should return resolvable constant name as String or nil'
|
12
12
|
|
13
13
|
CLASS_NAME_RAISED_EXCEPTION =
|
14
|
-
'%<scope_class>s#name from: %<scope>s raised an error: %<exception>s'
|
14
|
+
'%<scope_class>s#name from: %<scope>s raised an error: %<exception>s'
|
15
15
|
|
16
16
|
CLASS_NAME_TYPE_MISMATCH_FORMAT =
|
17
|
-
'%<scope_class>s#name from: %<scope>s returned %<name>s'
|
17
|
+
'%<scope_class>s#name from: %<scope>s returned %<name>s'
|
18
18
|
|
19
19
|
private_constant(*constants(false))
|
20
20
|
|
data/lib/mutant/expression.rb
CHANGED
@@ -8,7 +8,7 @@ module Mutant
|
|
8
8
|
|
9
9
|
fragment = /[A-Za-z][A-Za-z\d_]*/.freeze
|
10
10
|
SCOPE_NAME_PATTERN = /(?<scope_name>#{fragment}(?:#{SCOPE_OPERATOR}#{fragment})*)/.freeze
|
11
|
-
SCOPE_SYMBOL_PATTERN = '(?<scope_symbol>[.#])'
|
11
|
+
SCOPE_SYMBOL_PATTERN = '(?<scope_symbol>[.#])'
|
12
12
|
|
13
13
|
private_constant(*constants(false))
|
14
14
|
|
data/lib/mutant/loader.rb
CHANGED
@@ -5,6 +5,10 @@ module Mutant
|
|
5
5
|
class Loader
|
6
6
|
include Anima.new(:binding, :kernel, :source, :subject)
|
7
7
|
|
8
|
+
FROZEN_STRING_FORMAT = "# frozen_string_literal: true\n%s"
|
9
|
+
|
10
|
+
private_constant(*constants(false))
|
11
|
+
|
8
12
|
# Call loader
|
9
13
|
#
|
10
14
|
# @return [self]
|
@@ -19,7 +23,7 @@ module Mutant
|
|
19
23
|
# @return [undefined]
|
20
24
|
def call
|
21
25
|
kernel.eval(
|
22
|
-
source,
|
26
|
+
FROZEN_STRING_FORMAT % source,
|
23
27
|
binding,
|
24
28
|
subject.source_path.to_s,
|
25
29
|
subject.source_line
|
@@ -12,11 +12,11 @@ module Mutant
|
|
12
12
|
:subject_filters
|
13
13
|
)
|
14
14
|
|
15
|
-
INSPECT_FORMAT = "#<#{self} %s>"
|
16
|
-
ATTRIBUTE_DELIMITER = ' '
|
17
|
-
ATTRIBUTE_FORMAT = '%s: [%s]'
|
18
|
-
ENUM_DELIMITER = ','
|
19
|
-
EMPTY_ATTRIBUTES = 'empty'
|
15
|
+
INSPECT_FORMAT = "#<#{self} %s>"
|
16
|
+
ATTRIBUTE_DELIMITER = ' '
|
17
|
+
ATTRIBUTE_FORMAT = '%s: [%s]'
|
18
|
+
ENUM_DELIMITER = ','
|
19
|
+
EMPTY_ATTRIBUTES = 'empty'
|
20
20
|
PRESENTATIONS = IceNine.deep_freeze(
|
21
21
|
ignore_expressions: :syntax,
|
22
22
|
match_expressions: :syntax,
|
@@ -13,10 +13,10 @@ module Mutant
|
|
13
13
|
BLACKLIST = %r{\A(kernel/|\(eval\)\z)}.freeze
|
14
14
|
|
15
15
|
SOURCE_LOCATION_WARNING_FORMAT =
|
16
|
-
'%s does not have a valid source location, unable to emit subject'
|
16
|
+
'%s does not have a valid source location, unable to emit subject'
|
17
17
|
|
18
18
|
CLOSURE_WARNING_FORMAT =
|
19
|
-
'%s is dynamically defined in a closure, unable to emit subject'
|
19
|
+
'%s is dynamically defined in a closure, unable to emit subject'
|
20
20
|
|
21
21
|
# Matched subjects
|
22
22
|
#
|
@@ -21,7 +21,7 @@ module Mutant
|
|
21
21
|
SUBJECT_CLASS = Subject::Method::Singleton
|
22
22
|
RECEIVER_INDEX = 0
|
23
23
|
NAME_INDEX = 1
|
24
|
-
RECEIVER_WARNING = 'Can only match :defs on :self or :const got %p unable to match'
|
24
|
+
RECEIVER_WARNING = 'Can only match :defs on :self or :const got %p unable to match'
|
25
25
|
|
26
26
|
private
|
27
27
|
|
data/lib/mutant/mutation.rb
CHANGED
@@ -6,7 +6,7 @@ module Mutant
|
|
6
6
|
include AbstractType, Adamantium::Flat
|
7
7
|
include Concord::Public.new(:subject, :node)
|
8
8
|
|
9
|
-
CODE_DELIMITER = "\0"
|
9
|
+
CODE_DELIMITER = "\0"
|
10
10
|
CODE_RANGE = (0..4).freeze
|
11
11
|
|
12
12
|
# Identification string
|
@@ -86,7 +86,7 @@ module Mutant
|
|
86
86
|
# Evil mutation that should case mutations to fail tests
|
87
87
|
class Evil < self
|
88
88
|
|
89
|
-
SYMBOL = 'evil'
|
89
|
+
SYMBOL = 'evil'
|
90
90
|
TEST_PASS_SUCCESS = false
|
91
91
|
|
92
92
|
end # Evil
|
@@ -94,7 +94,7 @@ module Mutant
|
|
94
94
|
# Neutral mutation that should not cause mutations to fail tests
|
95
95
|
class Neutral < self
|
96
96
|
|
97
|
-
SYMBOL = 'neutral'
|
97
|
+
SYMBOL = 'neutral'
|
98
98
|
TEST_PASS_SUCCESS = true
|
99
99
|
|
100
100
|
end # Neutral
|
@@ -102,7 +102,7 @@ module Mutant
|
|
102
102
|
# Noop mutation, special case of neutral
|
103
103
|
class Noop < Neutral
|
104
104
|
|
105
|
-
SYMBOL = 'noop'
|
105
|
+
SYMBOL = 'noop'
|
106
106
|
TEST_PASS_SUCCESS = true
|
107
107
|
|
108
108
|
end # Noop
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Mutant
|
4
4
|
class Mutator
|
5
5
|
class Node
|
6
|
-
# Emitter for mutations on 19 blocks
|
7
6
|
class Block < self
|
8
7
|
|
9
8
|
handle(:block)
|
@@ -18,7 +17,7 @@ module Mutant
|
|
18
17
|
def dispatch
|
19
18
|
emit_singletons
|
20
19
|
emit(send) unless n_lambda?(send)
|
21
|
-
emit_send_mutations(&method(:
|
20
|
+
emit_send_mutations(&method(:valid_send_mutation?))
|
22
21
|
emit_arguments_mutations
|
23
22
|
|
24
23
|
mutate_body
|
@@ -32,23 +31,43 @@ module Mutant
|
|
32
31
|
emit_body(N_RAISE)
|
33
32
|
|
34
33
|
return unless body
|
35
|
-
emit(body)
|
34
|
+
emit(body) unless body_has_control?
|
36
35
|
emit_body_mutations
|
37
36
|
|
38
37
|
mutate_body_receiver
|
39
38
|
end
|
40
39
|
|
40
|
+
# Test if body has control structures
|
41
|
+
#
|
42
|
+
# @return [Boolean]
|
43
|
+
def body_has_control?
|
44
|
+
AST.find_last_path(body) do |node|
|
45
|
+
n_break?(node) || n_next?(node)
|
46
|
+
end.any?
|
47
|
+
end
|
48
|
+
|
41
49
|
# Mutate method send in body scope of `send`
|
42
50
|
#
|
43
51
|
# @return [undefined]
|
44
52
|
def mutate_body_receiver
|
45
|
-
return
|
53
|
+
return if n_lambda?(send) || !n_send?(body)
|
46
54
|
|
47
55
|
body_meta = AST::Meta::Send.new(body)
|
48
56
|
|
49
57
|
emit(s(:send, send, body_meta.selector, *body_meta.arguments))
|
50
58
|
end
|
51
59
|
|
60
|
+
# Test for valid send mutations
|
61
|
+
#
|
62
|
+
# @return [true, false, nil]
|
63
|
+
def valid_send_mutation?(node)
|
64
|
+
return unless n_send?(node)
|
65
|
+
|
66
|
+
last = AST::Meta::Send.new(node).arguments.last
|
67
|
+
|
68
|
+
!last&.type.equal?(:block_pass)
|
69
|
+
end
|
70
|
+
|
52
71
|
end # Block
|
53
72
|
end # Node
|
54
73
|
end # Mutator
|
@@ -9,6 +9,8 @@ module Mutant
|
|
9
9
|
|
10
10
|
handle(:array)
|
11
11
|
|
12
|
+
children :first
|
13
|
+
|
12
14
|
private
|
13
15
|
|
14
16
|
# Emit mutations
|
@@ -19,7 +21,7 @@ module Mutant
|
|
19
21
|
emit_type
|
20
22
|
mutate_body
|
21
23
|
return unless children.one?
|
22
|
-
emit(
|
24
|
+
emit(first) unless n_splat?(first)
|
23
25
|
end
|
24
26
|
|
25
27
|
# Mutate body
|
@@ -10,7 +10,7 @@ module Mutant
|
|
10
10
|
handle(:regexp)
|
11
11
|
|
12
12
|
# No input can ever be matched with this
|
13
|
-
NULL_REGEXP_SOURCE = 'nomatch\A'
|
13
|
+
NULL_REGEXP_SOURCE = 'nomatch\A'
|
14
14
|
|
15
15
|
private
|
16
16
|
|
@@ -42,7 +42,7 @@ module Mutant
|
|
42
42
|
#
|
43
43
|
# @return [undefined]
|
44
44
|
def mutate_body
|
45
|
-
return unless body.all?(&method(:n_str?))
|
45
|
+
return unless body.all?(&method(:n_str?)) && body_ast
|
46
46
|
|
47
47
|
Mutator.mutate(body_ast).each do |mutation|
|
48
48
|
source = AST::Regexp.to_expression(mutation).to_s
|
@@ -52,14 +52,14 @@ module Mutant
|
|
52
52
|
|
53
53
|
# AST representation of regexp body
|
54
54
|
#
|
55
|
-
# @return [Parser::AST::Node]
|
55
|
+
# @return [Parser::AST::Node, nil]
|
56
56
|
def body_ast
|
57
|
-
AST::Regexp.to_ast(body_expression)
|
57
|
+
body_expression and AST::Regexp.to_ast(body_expression)
|
58
58
|
end
|
59
59
|
|
60
60
|
# Expression representation of regexp body
|
61
61
|
#
|
62
|
-
# @return [Regexp::Expression]
|
62
|
+
# @return [Regexp::Expression, nil]
|
63
63
|
def body_expression
|
64
64
|
AST::Regexp.parse(body.map(&:children).join)
|
65
65
|
end
|
@@ -6,7 +6,7 @@ module Mutant
|
|
6
6
|
class Printer
|
7
7
|
# Reporter for progressive output format on scheduler Status objects
|
8
8
|
class StatusProgressive < self
|
9
|
-
FORMAT = '(%02d/%02d) %3d%% - killtime: %0.02fs runtime: %0.02fs overhead: %0.02fs'
|
9
|
+
FORMAT = '(%02d/%02d) %3d%% - killtime: %0.02fs runtime: %0.02fs overhead: %0.02fs'
|
10
10
|
|
11
11
|
delegate(
|
12
12
|
:coverage,
|
@@ -6,7 +6,7 @@ module Mutant
|
|
6
6
|
class Printer
|
7
7
|
# Reporter for subject progress
|
8
8
|
class SubjectProgress < self
|
9
|
-
FORMAT = '(%02d/%02d) %3d%% - killtime: %0.02fs runtime: %0.02fs overhead: %0.02fs'
|
9
|
+
FORMAT = '(%02d/%02d) %3d%% - killtime: %0.02fs runtime: %0.02fs overhead: %0.02fs'
|
10
10
|
|
11
11
|
delegate(
|
12
12
|
:tests,
|
@@ -9,9 +9,9 @@ module Mutant
|
|
9
9
|
|
10
10
|
delegate :tests, :runtime
|
11
11
|
|
12
|
-
STATUS_FORMAT = '- %d @ runtime: %s'
|
13
|
-
OUTPUT_HEADER = 'Test Output:'
|
14
|
-
TEST_FORMAT = ' - %s'
|
12
|
+
STATUS_FORMAT = '- %d @ runtime: %s'
|
13
|
+
OUTPUT_HEADER = 'Test Output:'
|
14
|
+
TEST_FORMAT = ' - %s'
|
15
15
|
|
16
16
|
# Run test result reporter
|
17
17
|
#
|
data/lib/mutant/repository.rb
CHANGED
@@ -24,7 +24,7 @@ module Mutant
|
|
24
24
|
class Diff
|
25
25
|
include Adamantium, Anima.new(:config, :from, :to)
|
26
26
|
|
27
|
-
HEAD = 'HEAD'
|
27
|
+
HEAD = 'HEAD'
|
28
28
|
|
29
29
|
# Test if diff changes file at line range
|
30
30
|
#
|
@@ -41,6 +41,7 @@ module Mutant
|
|
41
41
|
command = %W[
|
42
42
|
git log
|
43
43
|
#{from}...#{to}
|
44
|
+
--ignore-all-space
|
44
45
|
-L #{line_range.begin},#{line_range.end}:#{path}
|
45
46
|
]
|
46
47
|
|
data/lib/mutant/version.rb
CHANGED
data/meta/block.rb
CHANGED
@@ -121,3 +121,84 @@ Mutant::Meta::Example.add :block do
|
|
121
121
|
mutation 'foo { }'
|
122
122
|
mutation 'foo'
|
123
123
|
end
|
124
|
+
|
125
|
+
Mutant::Meta::Example.add :block do
|
126
|
+
source 'foo { next if true }'
|
127
|
+
|
128
|
+
singleton_mutations
|
129
|
+
mutation 'foo'
|
130
|
+
mutation 'foo { }'
|
131
|
+
mutation 'foo { self }'
|
132
|
+
mutation 'foo { nil }'
|
133
|
+
mutation 'foo { raise }'
|
134
|
+
mutation 'foo { self if true }'
|
135
|
+
mutation 'foo { nil if true }'
|
136
|
+
mutation 'foo { break if true }'
|
137
|
+
mutation 'foo { next if !true }'
|
138
|
+
mutation 'foo { next if false }'
|
139
|
+
mutation 'foo { next if nil }'
|
140
|
+
mutation 'foo { next }'
|
141
|
+
end
|
142
|
+
|
143
|
+
Mutant::Meta::Example.add :block do
|
144
|
+
source 'foo { next }'
|
145
|
+
|
146
|
+
singleton_mutations
|
147
|
+
mutation 'foo { nil }'
|
148
|
+
mutation 'foo { raise }'
|
149
|
+
mutation 'foo { self }'
|
150
|
+
mutation 'foo { break }'
|
151
|
+
mutation 'foo { }'
|
152
|
+
mutation 'foo'
|
153
|
+
end
|
154
|
+
|
155
|
+
Mutant::Meta::Example.add :block do
|
156
|
+
source 'foo { break if true }'
|
157
|
+
|
158
|
+
singleton_mutations
|
159
|
+
mutation 'foo'
|
160
|
+
mutation 'foo { }'
|
161
|
+
mutation 'foo { self }'
|
162
|
+
mutation 'foo { nil }'
|
163
|
+
mutation 'foo { raise }'
|
164
|
+
mutation 'foo { self if true }'
|
165
|
+
mutation 'foo { nil if true }'
|
166
|
+
mutation 'foo { break if !true }'
|
167
|
+
mutation 'foo { break if false }'
|
168
|
+
mutation 'foo { break if nil }'
|
169
|
+
mutation 'foo { break }'
|
170
|
+
end
|
171
|
+
|
172
|
+
Mutant::Meta::Example.add :block do
|
173
|
+
source 'foo { break }'
|
174
|
+
|
175
|
+
singleton_mutations
|
176
|
+
mutation 'foo { nil }'
|
177
|
+
mutation 'foo { raise }'
|
178
|
+
mutation 'foo { self }'
|
179
|
+
mutation 'foo { }'
|
180
|
+
mutation 'foo'
|
181
|
+
end
|
182
|
+
|
183
|
+
Mutant::Meta::Example.add :block do
|
184
|
+
source 'foo(&:bar).baz {}'
|
185
|
+
|
186
|
+
singleton_mutations
|
187
|
+
|
188
|
+
mutation 'foo(&:bar).baz { raise }'
|
189
|
+
mutation 'foo.baz { }'
|
190
|
+
mutation 'foo(&:bar).baz'
|
191
|
+
mutation 'self.baz {}'
|
192
|
+
end
|
193
|
+
|
194
|
+
Mutant::Meta::Example.add :block do
|
195
|
+
source 'foo(nil, &:bar).baz {}'
|
196
|
+
|
197
|
+
singleton_mutations
|
198
|
+
mutation 'foo(nil, &:bar).baz { raise }'
|
199
|
+
mutation 'foo(&:bar).baz { }'
|
200
|
+
mutation 'foo(nil).baz { }'
|
201
|
+
mutation 'foo.baz { }'
|
202
|
+
mutation 'self.baz { }'
|
203
|
+
mutation 'foo(nil, &:bar).baz'
|
204
|
+
end
|
data/meta/file.rb
ADDED
data/meta/lambda.rb
CHANGED
@@ -7,3 +7,17 @@ Mutant::Meta::Example.add :block, :lambda do
|
|
7
7
|
|
8
8
|
mutation '->() { raise }'
|
9
9
|
end
|
10
|
+
|
11
|
+
Mutant::Meta::Example.add :block, :lambda do
|
12
|
+
source '->() { foo.bar }'
|
13
|
+
|
14
|
+
singleton_mutations
|
15
|
+
|
16
|
+
mutation '->() { }'
|
17
|
+
mutation '->() { self }'
|
18
|
+
mutation '->() { nil }'
|
19
|
+
mutation '->() { raise }'
|
20
|
+
mutation '->() { self.bar }'
|
21
|
+
mutation '->() { foo }'
|
22
|
+
mutation 'foo.bar'
|
23
|
+
end
|
data/meta/line.rb
ADDED
data/meta/lvasgn.rb
CHANGED
@@ -8,3 +8,18 @@ Mutant::Meta::Example.add :lvasgn do
|
|
8
8
|
mutation 'a = false'
|
9
9
|
mutation 'a = nil'
|
10
10
|
end
|
11
|
+
|
12
|
+
Mutant::Meta::Example.add :array, :lvasgn do
|
13
|
+
source 'a = *b'
|
14
|
+
|
15
|
+
singleton_mutations
|
16
|
+
mutation 'a__mutant__ = *b'
|
17
|
+
mutation 'a = nil'
|
18
|
+
mutation 'a = self'
|
19
|
+
mutation 'a = []'
|
20
|
+
mutation 'a = [nil]'
|
21
|
+
mutation 'a = [self]'
|
22
|
+
mutation 'a = [*self]'
|
23
|
+
mutation 'a = [*nil]'
|
24
|
+
mutation 'a = [b]'
|
25
|
+
end
|
data/meta/regexp.rb
CHANGED
@@ -76,6 +76,15 @@ Mutant::Meta::Example.add :regexp do
|
|
76
76
|
mutation '/(?(1)(foo)(?:bar))/'
|
77
77
|
end
|
78
78
|
|
79
|
+
# Case where MRI would accept an expression but regexp_parser not.
|
80
|
+
Mutant::Meta::Example.add :regexp do
|
81
|
+
source '/u{/'
|
82
|
+
|
83
|
+
singleton_mutations
|
84
|
+
mutation '//'
|
85
|
+
mutation '/nomatch\A/'
|
86
|
+
end
|
87
|
+
|
79
88
|
Pathname
|
80
89
|
.glob(Pathname.new(__dir__).join('regexp', '*.rb'))
|
81
90
|
.sort
|
data/spec/integrations.yml
CHANGED
@@ -8,14 +8,9 @@
|
|
8
8
|
mutation_coverage: false
|
9
9
|
mutation_generation: true
|
10
10
|
expected_errors:
|
11
|
-
"#<
|
12
|
-
|
13
|
-
|
14
|
-
- language/regexp/escapes_spec.rb
|
15
|
-
"#<Regexp::Scanner::PrematureEndError: Premature end of pattern at #{str}>":
|
16
|
-
- language/regexp/interpolation_spec.rb
|
17
|
-
'#<Regexp::Scanner::PrematureEndError: Premature end of pattern at \xA>':
|
18
|
-
- language/regexp/escapes_spec.rb
|
11
|
+
"#<ArgumentError: No valid target found for '?' >":
|
12
|
+
- core/matchdata/begin_spec.rb
|
13
|
+
- core/matchdata/end_spec.rb
|
19
14
|
exclude:
|
20
15
|
- core/string/casecmp_spec.rb
|
21
16
|
- core/symbol/casecmp_spec.rb
|
data/spec/support/corpus.rb
CHANGED
@@ -14,7 +14,7 @@ module MutantSpec
|
|
14
14
|
# rubocop:disable MethodLength
|
15
15
|
module Corpus
|
16
16
|
TMP = ROOT.join('tmp').freeze
|
17
|
-
EXCLUDE_GLOB_FORMAT = '{%s}'
|
17
|
+
EXCLUDE_GLOB_FORMAT = '{%s}'
|
18
18
|
|
19
19
|
# Not in the docs. Number from chatting with their support.
|
20
20
|
# 2 processors allocated per container, 4 processes works well.
|
@@ -27,9 +27,9 @@ module MutantSpec
|
|
27
27
|
class Project
|
28
28
|
MUTEX = Mutex.new
|
29
29
|
|
30
|
-
MUTATION_GENERATION_MESSAGE = 'Total Mutations/Time/Parse-Errors: %s/%0.2fs - %0.2f/s'
|
31
|
-
START_MESSAGE = 'Starting - %s'
|
32
|
-
FINISH_MESSAGE = 'Mutations - %4i - %s'
|
30
|
+
MUTATION_GENERATION_MESSAGE = 'Total Mutations/Time/Parse-Errors: %s/%0.2fs - %0.2f/s'
|
31
|
+
START_MESSAGE = 'Starting - %s'
|
32
|
+
FINISH_MESSAGE = 'Mutations - %4i - %s'
|
33
33
|
|
34
34
|
DEFAULT_MUTATION_COUNT = 0
|
35
35
|
|
@@ -272,7 +272,7 @@ module MutantSpec
|
|
272
272
|
# Mapping of files which we expect to cause errors during mutation generation
|
273
273
|
class ErrorWhitelist
|
274
274
|
class UnnecessaryExpectation < StandardError
|
275
|
-
MESSAGE = 'Expected to encounter %s while mutating "%s"'
|
275
|
+
MESSAGE = 'Expected to encounter %s while mutating "%s"'
|
276
276
|
|
277
277
|
def initialize(*error_info)
|
278
278
|
super(MESSAGE % error_info)
|
data/spec/support/warning.rb
CHANGED
@@ -1,7 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe Mutant::AST::Regexp, '.parse' do
|
4
|
-
|
5
|
-
|
4
|
+
def apply(input)
|
5
|
+
described_class.parse(input)
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'on regexp regexp_parser does accept' do
|
9
|
+
it 'parses using minor ruby version' do
|
10
|
+
expect(apply(/foo/).to_re).to eql(/foo/)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'on regexp regexp_parser does not accept' do
|
15
|
+
it 'returns nil' do
|
16
|
+
expect(apply(/u{/)).to be(nil)
|
17
|
+
end
|
6
18
|
end
|
7
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mutant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Schirp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: abstract_type
|
@@ -464,6 +464,7 @@ files:
|
|
464
464
|
- meta/dsym.rb
|
465
465
|
- meta/ensure.rb
|
466
466
|
- meta/false.rb
|
467
|
+
- meta/file.rb
|
467
468
|
- meta/float.rb
|
468
469
|
- meta/gvar.rb
|
469
470
|
- meta/gvasgn.rb
|
@@ -478,6 +479,7 @@ files:
|
|
478
479
|
- meta/kwbegin.rb
|
479
480
|
- meta/kwoptarg.rb
|
480
481
|
- meta/lambda.rb
|
482
|
+
- meta/line.rb
|
481
483
|
- meta/lvar.rb
|
482
484
|
- meta/lvasgn.rb
|
483
485
|
- meta/masgn.rb
|