mutant 0.3.0.beta21 → 0.3.0.beta22
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/.gitignore +37 -6
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.travis.yml +13 -7
- data/Gemfile +8 -3
- data/Gemfile.devtools +2 -6
- data/Guardfile +22 -8
- data/README.md +3 -1
- data/Rakefile +3 -0
- data/bin/mutant +4 -3
- data/config/devtools.yml +1 -1
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/reek.yml +7 -6
- data/config/rubocop.yml +55 -0
- data/lib/mutant.rb +3 -1
- data/lib/mutant/cache.rb +2 -0
- data/lib/mutant/cli.rb +14 -10
- data/lib/mutant/cli/classifier.rb +22 -10
- data/lib/mutant/cli/classifier/method.rb +14 -15
- data/lib/mutant/cli/classifier/namespace.rb +6 -2
- data/lib/mutant/cli/classifier/scope.rb +3 -1
- data/lib/mutant/color.rb +7 -3
- data/lib/mutant/config.rb +2 -0
- data/lib/mutant/constants.rb +5 -4
- data/lib/mutant/context.rb +2 -0
- data/lib/mutant/context/scope.rb +3 -1
- data/lib/mutant/differ.rb +10 -2
- data/lib/mutant/killer.rb +4 -1
- data/lib/mutant/killer/forked.rb +2 -0
- data/lib/mutant/killer/forking.rb +2 -0
- data/lib/mutant/killer/rspec.rb +19 -3
- data/lib/mutant/killer/static.rb +2 -0
- data/lib/mutant/loader.rb +8 -1
- data/lib/mutant/matcher.rb +2 -0
- data/lib/mutant/matcher/chain.rb +2 -0
- data/lib/mutant/matcher/method.rb +15 -3
- data/lib/mutant/matcher/method/finder.rb +2 -0
- data/lib/mutant/matcher/method/instance.rb +4 -1
- data/lib/mutant/matcher/method/singleton.rb +7 -1
- data/lib/mutant/matcher/methods.rb +3 -1
- data/lib/mutant/matcher/namespace.rb +4 -2
- data/lib/mutant/matcher/scope.rb +2 -0
- data/lib/mutant/mutation.rb +19 -5
- data/lib/mutant/mutation/evil.rb +12 -0
- data/lib/mutant/mutation/filter.rb +2 -0
- data/lib/mutant/mutation/filter/code.rb +3 -1
- data/lib/mutant/mutation/filter/regexp.rb +2 -0
- data/lib/mutant/mutation/filter/whitelist.rb +2 -0
- data/lib/mutant/mutation/neutral.rb +25 -0
- data/lib/mutant/mutator.rb +4 -6
- data/lib/mutant/mutator/node.rb +5 -1
- data/lib/mutant/mutator/node/argument.rb +2 -0
- data/lib/mutant/mutator/node/arguments.rb +2 -0
- data/lib/mutant/mutator/node/begin.rb +2 -0
- data/lib/mutant/mutator/node/block.rb +2 -0
- data/lib/mutant/mutator/node/case.rb +3 -1
- data/lib/mutant/mutator/node/connective/binary.rb +3 -1
- data/lib/mutant/mutator/node/const.rb +2 -0
- data/lib/mutant/mutator/node/define.rb +2 -0
- data/lib/mutant/mutator/node/generic.rb +4 -3
- data/lib/mutant/mutator/node/if.rb +2 -0
- data/lib/mutant/mutator/node/literal.rb +2 -0
- data/lib/mutant/mutator/node/literal/array.rb +2 -0
- data/lib/mutant/mutator/node/literal/boolean.rb +2 -0
- data/lib/mutant/mutator/node/literal/dynamic.rb +2 -0
- data/lib/mutant/mutator/node/literal/fixnum.rb +3 -1
- data/lib/mutant/mutator/node/literal/float.rb +2 -0
- data/lib/mutant/mutator/node/literal/hash.rb +2 -0
- data/lib/mutant/mutator/node/literal/nil.rb +2 -0
- data/lib/mutant/mutator/node/literal/range.rb +2 -1
- data/lib/mutant/mutator/node/literal/regex.rb +2 -0
- data/lib/mutant/mutator/node/literal/string.rb +2 -0
- data/lib/mutant/mutator/node/literal/symbol.rb +5 -1
- data/lib/mutant/mutator/node/masgn.rb +2 -0
- data/lib/mutant/mutator/node/mlhs.rb +2 -0
- data/lib/mutant/mutator/node/named_value/access.rb +2 -0
- data/lib/mutant/mutator/node/named_value/constant_assignment.rb +2 -0
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +3 -1
- data/lib/mutant/mutator/node/{cbase.rb → noop.rb} +7 -5
- data/lib/mutant/mutator/node/return.rb +2 -0
- data/lib/mutant/mutator/node/send.rb +2 -0
- data/lib/mutant/mutator/node/send/binary.rb +2 -0
- data/lib/mutant/mutator/node/splat.rb +2 -0
- data/lib/mutant/mutator/node/super.rb +2 -0
- data/lib/mutant/mutator/node/when.rb +3 -1
- data/lib/mutant/mutator/node/while.rb +2 -0
- data/lib/mutant/mutator/node/zsuper.rb +2 -0
- data/lib/mutant/mutator/registry.rb +55 -13
- data/lib/mutant/mutator/util.rb +2 -0
- data/lib/mutant/mutator/util/array.rb +3 -1
- data/lib/mutant/mutator/util/symbol.rb +2 -0
- data/lib/mutant/node_helpers.rb +10 -4
- data/lib/mutant/random.rb +2 -0
- data/lib/mutant/reporter.rb +2 -0
- data/lib/mutant/reporter/cli.rb +2 -0
- data/lib/mutant/reporter/cli/printer.rb +2 -0
- data/lib/mutant/reporter/cli/printer/config.rb +5 -2
- data/lib/mutant/reporter/cli/printer/killer.rb +2 -0
- data/lib/mutant/reporter/cli/printer/mutation.rb +13 -6
- data/lib/mutant/reporter/cli/printer/subject.rb +5 -1
- data/lib/mutant/reporter/null.rb +2 -0
- data/lib/mutant/runner.rb +2 -0
- data/lib/mutant/runner/config.rb +2 -0
- data/lib/mutant/runner/mutation.rb +2 -0
- data/lib/mutant/runner/subject.rb +2 -0
- data/lib/mutant/singleton_methods.rb +5 -3
- data/lib/mutant/strategy.rb +2 -0
- data/lib/mutant/strategy/method_expansion.rb +2 -0
- data/lib/mutant/strategy/rspec.rb +2 -0
- data/lib/mutant/strategy/rspec/dm2.rb +2 -0
- data/lib/mutant/strategy/rspec/dm2/lookup.rb +4 -2
- data/lib/mutant/strategy/rspec/dm2/lookup/method.rb +2 -0
- data/lib/mutant/strategy/static.rb +2 -0
- data/lib/mutant/subject.rb +4 -1
- data/lib/mutant/subject/method.rb +2 -0
- data/lib/mutant/subject/method/instance.rb +2 -0
- data/lib/mutant/subject/method/singleton.rb +2 -0
- data/lib/mutant/support/method_object.rb +2 -0
- data/lib/mutant/zombifier.rb +10 -6
- data/mutant.gemspec +11 -10
- data/spec/integration/mutant/rspec_killer_spec.rb +9 -4
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +3 -1
- data/spec/integration/mutant/zombie_spec.rb +2 -0
- data/spec/shared/method_matcher_behavior.rb +2 -0
- data/spec/shared/mutator_behavior.rb +16 -7
- data/spec/spec_helper.rb +26 -5
- data/spec/support/compress_helper.rb +5 -5
- data/spec/support/ice_nine_config.rb +2 -0
- data/spec/support/rspec.rb +2 -0
- data/spec/support/test_app.rb +2 -0
- data/spec/unit/mutant/class_methods/singleton_subclass_instance_spec.rb +2 -0
- data/spec/unit/mutant/cli/class_methods/new_spec.rb +17 -8
- data/spec/unit/mutant/cli/class_methods/run_spec.rb +10 -2
- data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +4 -1
- data/spec/unit/mutant/cli/classifier/method/each_spec.rb +89 -0
- data/spec/unit/mutant/cli/classifier/namespace/flat/each_spec.rb +58 -0
- data/spec/unit/mutant/cli/classifier/namespace/recursive/each_spec.rb +58 -0
- data/spec/unit/mutant/cli/classifier/scope/each_spec.rb +33 -0
- data/spec/unit/mutant/context/root_spec.rb +5 -1
- data/spec/unit/mutant/context/scope/root_spec.rb +2 -0
- data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +2 -0
- data/spec/unit/mutant/differ/class_methods/build_spec.rb +2 -0
- data/spec/unit/mutant/differ/class_methods/colorize_line_spec.rb +2 -0
- data/spec/unit/mutant/differ/diff_spec.rb +67 -5
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +21 -4
- data/spec/unit/mutant/killer/success_predicate_spec.rb +2 -0
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +12 -5
- data/spec/unit/mutant/matcher/chain/each_spec.rb +2 -0
- data/spec/unit/mutant/matcher/chain/matchers_spec.rb +2 -0
- data/spec/unit/mutant/matcher/each_spec.rb +8 -1
- data/spec/unit/mutant/matcher/method/instance/class_methods/build_spec.rb +4 -2
- data/spec/unit/mutant/matcher/method/instance/each_spec.rb +21 -20
- data/spec/unit/mutant/matcher/method/singleton/each_spec.rb +22 -19
- data/spec/unit/mutant/matcher/methods/instance/each_spec.rb +8 -3
- data/spec/unit/mutant/matcher/methods/singleton/each_spec.rb +8 -3
- data/spec/unit/mutant/matcher/namespace/each_spec.rb +8 -2
- data/spec/unit/mutant/mutator/each_spec.rb +2 -0
- data/spec/unit/mutant/mutator/emit_new_spec.rb +10 -3
- data/spec/unit/mutant/mutator/emit_spec.rb +4 -2
- data/spec/unit/mutant/mutator/node/and_asgn/mutation_spec.rb +26 -0
- data/spec/unit/mutant/mutator/node/begin/mutation_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +4 -2
- data/spec/unit/mutant/mutator/node/block_pass/mutation_spec.rb +14 -0
- data/spec/unit/mutant/mutator/node/break/mutation_spec.rb +15 -0
- data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/cbase/mutation_spec.rb +3 -6
- data/spec/unit/mutant/mutator/node/connective/binary/mutation_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/const/mutation_spec.rb +3 -6
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +2 -1
- data/spec/unit/mutant/mutator/node/defined_predicate/mutation_spec.rb +10 -0
- data/spec/unit/mutant/mutator/node/dstr/mutation_spec.rb +21 -0
- data/spec/unit/mutant/mutator/node/dsym/mutation_spec.rb +21 -0
- data/spec/unit/mutant/mutator/node/ensure/mutation_spec.rb +15 -0
- data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +2 -1
- data/spec/unit/mutant/mutator/node/literal/array_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/literal/boolean/mutation_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/literal/float_spec.rb +4 -2
- data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +4 -5
- data/spec/unit/mutant/mutator/node/literal/range_spec.rb +8 -8
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/literal/string_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/masgn/mutation_spec.rb +4 -10
- data/spec/unit/mutant/mutator/node/match_current_line/mutation_spec.rb +20 -0
- data/spec/unit/mutant/mutator/node/named_value/access/mutation_spec.rb +3 -2
- data/spec/unit/mutant/mutator/node/named_value/constant_assignment/mutation_spec.rb +3 -2
- data/spec/unit/mutant/mutator/node/named_value/variable_assignment/mutation_spec.rb +3 -2
- data/spec/unit/mutant/mutator/node/next/mutation_spec.rb +15 -0
- data/spec/unit/mutant/mutator/node/op_assgn/mutation_spec.rb +26 -0
- data/spec/unit/mutant/mutator/node/or_asgn/mutation_spec.rb +26 -0
- data/spec/unit/mutant/mutator/node/redo/mutation_spec.rb +10 -0
- data/spec/unit/mutant/mutator/node/rescue/mutation_spec.rb +24 -0
- data/spec/unit/mutant/mutator/node/restarg/mutation_spec.rb +16 -0
- data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +3 -1
- data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +2 -0
- data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +3 -1
- data/spec/unit/mutant/mutator/node/yield/mutation_spec.rb +15 -0
- data/spec/unit/mutant/node_helpers/n_not_spec.rb +2 -0
- data/spec/unit/mutant/runner/config/subjects_spec.rb +6 -2
- data/spec/unit/mutant/runner/config/success_predicate_spec.rb +15 -6
- data/spec/unit/mutant/runner/mutation/killer_spec.rb +3 -1
- data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +15 -8
- data/spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb +2 -0
- data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb +32 -11
- data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb +31 -11
- data/spec/unit/mutant/subject/context_spec.rb +2 -0
- data/spec/unit/mutant/subject/mutations_spec.rb +2 -0
- data/spec/unit/mutant/subject/node_spec.rb +2 -0
- data/test_app/lib/test_app.rb +2 -0
- data/test_app/lib/test_app/literal.rb +2 -0
- data/test_app/spec/shared/method_filter_parse_behavior.rb +5 -1
- data/test_app/spec/shared/method_match_behavior.rb +2 -0
- data/test_app/spec/spec_helper.rb +3 -1
- data/test_app/spec/unit/test_app/literal/command_spec.rb +2 -0
- data/test_app/spec/unit/test_app/literal/string_spec.rb +3 -1
- metadata +66 -18
- data/bin/zombie +0 -18
- data/test_app/spec/shared/mutator_behavior.rb +0 -44
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
class CLI
|
|
3
5
|
# A classifier for input strings
|
|
@@ -6,13 +8,19 @@ module Mutant
|
|
|
6
8
|
|
|
7
9
|
include Equalizer.new(:identifier)
|
|
8
10
|
|
|
9
|
-
SCOPE_NAME_PATTERN
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
SCOPE_NAME_PATTERN = /[A-Za-z][A-Za-z\d_]*/.freeze
|
|
12
|
+
SCOPE_OPERATOR = '::'.freeze
|
|
13
|
+
CBASE_PATTERN = /\A#{SCOPE_OPERATOR}/.freeze
|
|
14
|
+
|
|
15
|
+
METHOD_NAME_PATTERN = Regexp.union(
|
|
16
|
+
/[A-Za-z_][A-Za-z\d_]*[!?=]?/,
|
|
17
|
+
*OPERATOR_METHODS.map(&:to_s)
|
|
18
|
+
).freeze
|
|
19
|
+
|
|
20
|
+
SCOPE_PATTERN = /
|
|
21
|
+
(?:#{SCOPE_OPERATOR})?#{SCOPE_NAME_PATTERN}
|
|
22
|
+
(?:#{SCOPE_OPERATOR}#{SCOPE_NAME_PATTERN})*
|
|
23
|
+
/x.freeze
|
|
16
24
|
|
|
17
25
|
REGISTRY = []
|
|
18
26
|
|
|
@@ -36,9 +44,12 @@ module Mutant
|
|
|
36
44
|
# @api private
|
|
37
45
|
#
|
|
38
46
|
def self.constant_lookup(location)
|
|
39
|
-
location
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
location
|
|
48
|
+
.sub(CBASE_PATTERN, EMPTY_STRING)
|
|
49
|
+
.split(SCOPE_OPERATOR)
|
|
50
|
+
.reduce(Object) do |parent, name|
|
|
51
|
+
parent.const_get(name, nil)
|
|
52
|
+
end
|
|
42
53
|
end
|
|
43
54
|
|
|
44
55
|
# Return matchers for input
|
|
@@ -119,6 +130,7 @@ module Mutant
|
|
|
119
130
|
# @api private
|
|
120
131
|
#
|
|
121
132
|
abstract_method :matcher
|
|
133
|
+
private :matcher
|
|
122
134
|
|
|
123
135
|
end # Classifier
|
|
124
136
|
end # CLI
|
|
@@ -1,22 +1,33 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
class CLI
|
|
3
5
|
class Classifier
|
|
6
|
+
|
|
4
7
|
# Explicit method classifier
|
|
5
8
|
class Method < self
|
|
6
9
|
register
|
|
7
10
|
|
|
8
11
|
TABLE = {
|
|
9
12
|
'.' => Matcher::Methods::Singleton,
|
|
10
|
-
'#' => Matcher::Methods::Instance
|
|
13
|
+
'#' => Matcher::Methods::Instance,
|
|
11
14
|
}.freeze
|
|
12
15
|
|
|
13
|
-
REGEXP =
|
|
16
|
+
REGEXP = /
|
|
17
|
+
\A
|
|
18
|
+
(#{SCOPE_PATTERN})
|
|
19
|
+
([.#])
|
|
20
|
+
(#{METHOD_NAME_PATTERN})
|
|
21
|
+
\z
|
|
22
|
+
/x.freeze
|
|
14
23
|
|
|
15
24
|
# Positions of captured regexp groups
|
|
16
25
|
SCOPE_NAME_POSITION = 1
|
|
17
26
|
SCOPE_SYMBOL_POSITION = 2
|
|
18
27
|
METHOD_NAME_POSITION = 3
|
|
19
28
|
|
|
29
|
+
private
|
|
30
|
+
|
|
20
31
|
# Return method matcher
|
|
21
32
|
#
|
|
22
33
|
# @return [Matcher::Method]
|
|
@@ -28,18 +39,6 @@ module Mutant
|
|
|
28
39
|
end
|
|
29
40
|
memoize :matcher
|
|
30
41
|
|
|
31
|
-
# Return identification
|
|
32
|
-
#
|
|
33
|
-
# @return [String]
|
|
34
|
-
#
|
|
35
|
-
# @api private
|
|
36
|
-
#
|
|
37
|
-
def identification
|
|
38
|
-
match.to_s
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
42
|
# Return method
|
|
44
43
|
#
|
|
45
44
|
# @return [Method, UnboundMethod]
|
|
@@ -49,7 +48,7 @@ module Mutant
|
|
|
49
48
|
def method
|
|
50
49
|
methods_matcher.methods.detect do |method|
|
|
51
50
|
method.name == method_name
|
|
52
|
-
end or raise
|
|
51
|
+
end or raise NameError, "Cannot find method #{identifier}"
|
|
53
52
|
end
|
|
54
53
|
memoize :method, :freezer => :noop
|
|
55
54
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
class CLI
|
|
3
5
|
class Classifier
|
|
@@ -29,15 +31,17 @@ module Mutant
|
|
|
29
31
|
|
|
30
32
|
# Recursive namespace classifier
|
|
31
33
|
class Recursive < self
|
|
32
|
-
REGEXP
|
|
34
|
+
REGEXP = /\A(#{SCOPE_PATTERN})\*\z/.freeze
|
|
33
35
|
MATCHER = Matcher::Namespace
|
|
36
|
+
|
|
34
37
|
register
|
|
35
38
|
end # Recursive
|
|
36
39
|
|
|
37
40
|
# Recursive namespace classifier
|
|
38
41
|
class Flat < self
|
|
39
|
-
REGEXP
|
|
42
|
+
REGEXP = /\A(#{SCOPE_PATTERN})\z/.freeze
|
|
40
43
|
MATCHER = Matcher::Scope
|
|
44
|
+
|
|
41
45
|
register
|
|
42
46
|
end # Flat
|
|
43
47
|
|
data/lib/mutant/color.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
# Class to colorize strings
|
|
3
5
|
class Color
|
|
@@ -27,7 +29,8 @@ module Mutant
|
|
|
27
29
|
"\e[#{@code}m#{text}\e[0m"
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
NONE
|
|
32
|
+
Mutant.singleton_subclass_instance('NONE', self) do
|
|
33
|
+
|
|
31
34
|
# Format null color
|
|
32
35
|
#
|
|
33
36
|
# @param [String] text
|
|
@@ -49,13 +52,14 @@ module Mutant
|
|
|
49
52
|
#
|
|
50
53
|
# @api private
|
|
51
54
|
#
|
|
52
|
-
def initialize
|
|
55
|
+
def initialize
|
|
53
56
|
end
|
|
54
57
|
|
|
55
|
-
end
|
|
58
|
+
end
|
|
56
59
|
|
|
57
60
|
RED = Color.new(31)
|
|
58
61
|
GREEN = Color.new(32)
|
|
59
62
|
BLUE = Color.new(34)
|
|
63
|
+
|
|
60
64
|
end # Color
|
|
61
65
|
end # Mutant
|
data/lib/mutant/config.rb
CHANGED
data/lib/mutant/constants.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
|
|
3
5
|
METHOD_POSTFIX_EXPANSIONS = {
|
|
@@ -17,8 +19,7 @@ module Mutant
|
|
|
17
19
|
].to_set.freeze
|
|
18
20
|
|
|
19
21
|
# Set of node types that are not valid when emitted standalone
|
|
20
|
-
NOT_STANDALONE = [
|
|
21
|
-
|
|
22
|
+
NOT_STANDALONE = [:splat, :restarg, :block_pass].to_set.freeze
|
|
22
23
|
|
|
23
24
|
OPERATOR_EXPANSIONS = {
|
|
24
25
|
:<=> => :spaceship_operator,
|
|
@@ -50,7 +51,7 @@ module Mutant
|
|
|
50
51
|
:'!' => :negation_operator
|
|
51
52
|
}.freeze
|
|
52
53
|
|
|
53
|
-
INDEX_OPERATORS = [
|
|
54
|
+
INDEX_OPERATORS = [:[], :[]=].freeze
|
|
54
55
|
|
|
55
56
|
UNARY_METHOD_OPERATORS = [
|
|
56
57
|
:~@, :+@, :-@, :'!'
|
|
@@ -78,7 +79,7 @@ module Mutant
|
|
|
78
79
|
:xstr, :def, :defs, :case, :when, :ivar, :lvar, :cvar, :gvar,
|
|
79
80
|
:back_ref, :const, :nth_ref, :class, :sclass, :yield,
|
|
80
81
|
:match_with_lvasgn, :match_current_line, :irange, :erange,
|
|
81
|
-
:or_asgn, :kwbegin, :and_asgn
|
|
82
|
+
:or_asgn, :kwbegin, :and_asgn, :while
|
|
82
83
|
].to_set.freeze
|
|
83
84
|
|
|
84
85
|
end # Mutant
|
data/lib/mutant/context.rb
CHANGED
data/lib/mutant/context/scope.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
class Context
|
|
3
5
|
# Scope context for mutation (Class or Module)
|
|
@@ -12,7 +14,7 @@ module Mutant
|
|
|
12
14
|
# @api private
|
|
13
15
|
#
|
|
14
16
|
def root(node)
|
|
15
|
-
nesting.reverse.
|
|
17
|
+
nesting.reverse.reduce(node) do |current, scope|
|
|
16
18
|
self.class.wrap(scope, current)
|
|
17
19
|
end
|
|
18
20
|
end
|
data/lib/mutant/differ.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
# Class to create diffs from source code
|
|
3
5
|
class Differ
|
|
@@ -19,10 +21,16 @@ module Mutant
|
|
|
19
21
|
when 0
|
|
20
22
|
nil
|
|
21
23
|
when 1
|
|
22
|
-
output =
|
|
24
|
+
output =
|
|
25
|
+
Diff::LCS::Hunk.new(
|
|
26
|
+
old, new, diffs.first, max_length, 0
|
|
27
|
+
).diff(:unified)
|
|
23
28
|
output << "\n"
|
|
24
29
|
else
|
|
25
|
-
$stderr.puts
|
|
30
|
+
$stderr.puts(
|
|
31
|
+
'Mutation resulted in more than one diff, should not happen! ' +
|
|
32
|
+
'PLS report a bug!'
|
|
33
|
+
)
|
|
26
34
|
nil
|
|
27
35
|
end
|
|
28
36
|
end
|
data/lib/mutant/killer.rb
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
# Abstract base class for mutant killers
|
|
3
5
|
class Killer
|
|
4
|
-
include Adamantium::Flat, AbstractType
|
|
6
|
+
include Adamantium::Flat, AbstractType
|
|
7
|
+
include Equalizer.new(:strategy, :mutation, :killed?)
|
|
5
8
|
|
|
6
9
|
# Return strategy
|
|
7
10
|
#
|
data/lib/mutant/killer/forked.rb
CHANGED
data/lib/mutant/killer/rspec.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
class Killer
|
|
3
5
|
# Runner for rspec tests
|
|
@@ -19,8 +21,22 @@ module Mutant
|
|
|
19
21
|
mutation.insert
|
|
20
22
|
# TODO: replace with real streams from configuration
|
|
21
23
|
require 'stringio'
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
# Note: We assume interesting output from a failed rspec run is stderr.
|
|
25
|
+
rspec_err = StringIO.new
|
|
26
|
+
|
|
27
|
+
exit_code = ::RSpec::Core::Runner.run(cli_arguments, nil, rspec_err)
|
|
28
|
+
|
|
29
|
+
killed = !exit_code.zero?
|
|
30
|
+
|
|
31
|
+
if killed and mutation.should_survive?
|
|
32
|
+
rspec_err.rewind
|
|
33
|
+
|
|
34
|
+
puts "#{mutation.class} test failed."
|
|
35
|
+
puts 'RSpec stderr:'
|
|
36
|
+
puts rspec_err.read
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
killed
|
|
24
40
|
end
|
|
25
41
|
|
|
26
42
|
# Return command line arguments
|
|
@@ -29,7 +45,7 @@ module Mutant
|
|
|
29
45
|
#
|
|
30
46
|
# @api private
|
|
31
47
|
#
|
|
32
|
-
def
|
|
48
|
+
def cli_arguments
|
|
33
49
|
%W(
|
|
34
50
|
--fail-fast
|
|
35
51
|
) + strategy.spec_files(mutation.subject)
|
data/lib/mutant/killer/static.rb
CHANGED
data/lib/mutant/loader.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
# Base class for code loaders
|
|
3
5
|
class Loader
|
|
@@ -40,7 +42,12 @@ module Mutant
|
|
|
40
42
|
# @api private
|
|
41
43
|
#
|
|
42
44
|
def run
|
|
43
|
-
eval(
|
|
45
|
+
eval(
|
|
46
|
+
source,
|
|
47
|
+
TOPLEVEL_BINDING,
|
|
48
|
+
@subject.source_path.to_s,
|
|
49
|
+
@subject.source_line
|
|
50
|
+
)
|
|
44
51
|
end
|
|
45
52
|
|
|
46
53
|
# Return source
|
data/lib/mutant/matcher.rb
CHANGED
data/lib/mutant/matcher/chain.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
class Matcher
|
|
3
5
|
# Matcher for subjects that are a specific method
|
|
@@ -6,7 +8,8 @@ module Mutant
|
|
|
6
8
|
|
|
7
9
|
# Methods within rbx kernel directory are precompiled and their source
|
|
8
10
|
# cannot be accessed via reading source location
|
|
9
|
-
|
|
11
|
+
SKIP_METHODS = %w[kernel/ (eval)].freeze
|
|
12
|
+
BLACKLIST = /\A#{Regexp.union(*SKIP_METHODS)}/.freeze
|
|
10
13
|
|
|
11
14
|
# Enumerate matches
|
|
12
15
|
#
|
|
@@ -25,7 +28,12 @@ module Mutant
|
|
|
25
28
|
if subject
|
|
26
29
|
yield subject
|
|
27
30
|
else
|
|
28
|
-
|
|
31
|
+
message = sprintf(
|
|
32
|
+
'Cannot find definition of: %s in %s',
|
|
33
|
+
identification,
|
|
34
|
+
source_location.join(':')
|
|
35
|
+
)
|
|
36
|
+
$stderr.puts(message)
|
|
29
37
|
end
|
|
30
38
|
end
|
|
31
39
|
|
|
@@ -47,7 +55,11 @@ module Mutant
|
|
|
47
55
|
def skip?
|
|
48
56
|
location = source_location
|
|
49
57
|
if location.nil? or BLACKLIST.match(location.first)
|
|
50
|
-
|
|
58
|
+
message = sprintf(
|
|
59
|
+
'%s does not have valid source location unable to emit matcher',
|
|
60
|
+
method.inspect
|
|
61
|
+
)
|
|
62
|
+
$stderr.puts(message)
|
|
51
63
|
return true
|
|
52
64
|
end
|
|
53
65
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Mutant
|
|
2
4
|
class Matcher
|
|
3
5
|
class Method
|
|
@@ -16,7 +18,8 @@ module Mutant
|
|
|
16
18
|
# @api private
|
|
17
19
|
#
|
|
18
20
|
def self.build(cache, scope, method)
|
|
19
|
-
|
|
21
|
+
name = method.name
|
|
22
|
+
if scope.ancestors.include?(::Adamantium) and scope.memoized?(name)
|
|
20
23
|
return Memoized.new(cache, scope, method)
|
|
21
24
|
end
|
|
22
25
|
super
|