mutant 0.6.0 → 0.6.2
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 +11 -1
- data/README.md +34 -40
- data/config/flay.yml +1 -1
- data/config/reek.yml +2 -1
- data/lib/mutant/ast.rb +17 -11
- data/lib/mutant/ast/meta.rb +33 -5
- data/lib/mutant/diff.rb +1 -1
- data/lib/mutant/matcher/method.rb +14 -16
- data/lib/mutant/matcher/method/instance.rb +4 -4
- data/lib/mutant/matcher/namespace.rb +1 -1
- data/lib/mutant/meta.rb +2 -1
- data/lib/mutant/meta/example.rb +3 -3
- data/lib/mutant/meta/example/dsl.rb +5 -4
- data/lib/mutant/mutator/node.rb +17 -1
- data/lib/mutant/mutator/node/literal/boolean.rb +1 -1
- data/lib/mutant/mutator/node/rescue.rb +77 -1
- data/lib/mutant/mutator/node/send/index.rb +1 -1
- data/lib/mutant/require_highjack.rb +3 -3
- data/lib/mutant/runner.rb +1 -1
- data/lib/mutant/subject.rb +0 -4
- data/lib/mutant/version.rb +1 -1
- data/meta/def.rb +30 -0
- data/meta/if.rb +1 -1
- data/meta/rescue.rb +5 -0
- data/meta/super.rb +1 -1
- data/mutant.gemspec +1 -1
- data/spec/shared/method_matcher_behavior.rb +1 -1
- data/spec/unit/mutant/ast_spec.rb +38 -0
- data/spec/unit/mutant/matcher/method/instance_spec.rb +39 -69
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +13 -55
- data/test_app/lib/test_app.rb +94 -0
- metadata +18 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 001bd8f243257cdce0da86ebe626d0e1efbef248
|
4
|
+
data.tar.gz: 9b1bc583e1321da8437ec18716a6e9b5911018dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 006d6d7657e04e6e23fdaef408516abf6119ce24c1eaaacda8f2f8d3e20993168c450391adf8f9bda5e78f13d6ca9e765a2a83db04db1fcf4c233389e4585727
|
7
|
+
data.tar.gz: 343f8f579a4db3aa5b49c96b2e16a61cf963f92dc7781a7d1ef514a670885f745912450ec264659a46e96ae471772366f36ae6f92ee4389a428f63d6df92dcd3
|
data/Changelog.md
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
# v0.6.
|
1
|
+
# v0.6.2 2014-08-16
|
2
|
+
|
3
|
+
* Fix matcher to ignore metaprogrammed defines [#254](https://github.com/mbj/mutant/issues/254)
|
4
|
+
* Add rescue resbody body concat-promotion mutation
|
5
|
+
* Add rescue else body concat-promotion mutation #245
|
6
|
+
|
7
|
+
# v0.6.1 2014-08-16
|
8
|
+
|
9
|
+
* Incorrectly released on partial state. Yanked.
|
10
|
+
|
11
|
+
# v0.6.0 2014-08-11
|
2
12
|
|
3
13
|
* Parallel execution / reporting.
|
4
14
|
* Add -j, --jobs flag to control concurrency.
|
data/README.md
CHANGED
@@ -7,19 +7,27 @@ mutant
|
|
7
7
|
[](http://inch-ci.org/github/mbj/mutant)
|
8
8
|
[](https://rubygems.org/gems/mutant)
|
9
9
|
|
10
|
-
Mutant is a mutation testing tool for
|
10
|
+
Mutant is a mutation testing tool for Ruby.
|
11
11
|
|
12
12
|
The idea is that if code can be changed and your tests do not notice, either that code isn't being covered
|
13
13
|
or it does not have a speced side effect.
|
14
14
|
|
15
|
-
Mutant supports MRI and RBX 1.9, 2.0 and 2.1, while support for
|
16
|
-
It should also work under any
|
15
|
+
Mutant supports MRI and RBX 1.9, 2.0 and 2.1, while support for JRuby is planned.
|
16
|
+
It should also work under any Ruby engine that supports POSIX-fork(2) semantics.
|
17
17
|
|
18
|
-
Mutant uses a pure
|
18
|
+
Mutant uses a pure Ruby [parser](https://github.com/whitequark/parser) and an [unparser](https://github.com/mbj/unparser)
|
19
19
|
to do its magic.
|
20
20
|
|
21
21
|
Mutant does not have really good "getting started" documentation currently so please refer to presentations and blog posts below.
|
22
22
|
|
23
|
+
Mutation-Operators:
|
24
|
+
-------------------
|
25
|
+
|
26
|
+
Mutant supports a wide range of mutation operators. An exhaustive list can be found in the [mutant-meta](https://github.com/mbj/mutant/tree/master/meta).
|
27
|
+
The `mutant-meta` is arranged to the AST-Node-Types of parser. Refer to parsers [AST documentation](https://github.com/whitequark/parser/blob/master/doc/AST_FORMAT.md) in doubt.
|
28
|
+
|
29
|
+
There is no easy and universal way to count the number of mutation operators a tool supports.
|
30
|
+
|
23
31
|
Presentations
|
24
32
|
-------------
|
25
33
|
|
@@ -39,7 +47,7 @@ Blog-Posts
|
|
39
47
|
Projects using Mutant
|
40
48
|
---------------------
|
41
49
|
|
42
|
-
The following projects adopted mutant, and aim 100% mutation coverage:
|
50
|
+
The following projects adopted mutant, and aim for 100% mutation coverage:
|
43
51
|
|
44
52
|
* [axiom](https://github.com/dkubb/axiom)
|
45
53
|
* [axiom-types](https://github.com/dkubb/axiom-types)
|
@@ -65,8 +73,8 @@ Install the gem `mutant` via your preferred method.
|
|
65
73
|
gem install mutant
|
66
74
|
```
|
67
75
|
|
68
|
-
If you plan to use the
|
69
|
-
Please add an explicit dependency to `rspec-core` for the
|
76
|
+
If you plan to use the RSpec integration you'll have to install `mutant-rspec` also.
|
77
|
+
Please add an explicit dependency to `rspec-core` for the RSpec version you want to use.
|
70
78
|
|
71
79
|
```ruby
|
72
80
|
gem install mutant-rspec
|
@@ -74,38 +82,6 @@ gem install mutant-rspec
|
|
74
82
|
|
75
83
|
The minitest integration is still in the works.
|
76
84
|
|
77
|
-
Mutations
|
78
|
-
---------
|
79
|
-
|
80
|
-
Mutant supports a very wide range of mutation operators. Listing them all in detail would blow this document up.
|
81
|
-
|
82
|
-
It is planned to parse a list of mutation operators from the source. In the meantime please refer to the
|
83
|
-
[code](https://github.com/mbj/mutant/tree/master/lib/mutant/mutator/node) each subclass of `Mutant::Mutator::Node`
|
84
|
-
emits around 3-6 mutations.
|
85
|
-
|
86
|
-
Currently mutant covers the majority of ruby's complex nodes that often occur in method bodies.
|
87
|
-
|
88
|
-
NOTE: The textbook examples you find on mutation testing are intentionally not implemented. This is subjected to change.
|
89
|
-
|
90
|
-
Some stats from the [axiom](https://github.com/dkubb/axiom) library:
|
91
|
-
|
92
|
-
```
|
93
|
-
Subjects: 424 # Amount of subjects being mutated (currently only methods)
|
94
|
-
Mutations: 6760 # Amount of mutations mutant generated (~13 mutations per method)
|
95
|
-
Kills: 6664 # Amount of successfully killed mutations
|
96
|
-
Runtime: 5123.13s # Total runtime
|
97
|
-
Killtime: 5092.63s # Time spend killing mutations
|
98
|
-
Overhead: 0.60%
|
99
|
-
Coverage: 98.58% # Coverage score
|
100
|
-
Alive: 96 # Amount of alive mutations.
|
101
|
-
```
|
102
|
-
|
103
|
-
|
104
|
-
Nodes still missing a dedicated mutator are handled via the
|
105
|
-
[Generic](https://github.com/mbj/mutant/blob/master/lib/mutant/mutator/node/generic.rb) mutator.
|
106
|
-
The goal is to remove this mutator and have dedicated mutator for every type of node and removing
|
107
|
-
the Generic handler altogether.
|
108
|
-
|
109
85
|
Examples
|
110
86
|
--------
|
111
87
|
|
@@ -139,6 +115,24 @@ Example for a subject like `Foo::Bar#baz` it will run all example groups with de
|
|
139
115
|
`Foo::Bar#baz`, `Foo::Bar` and `Foo`. The order is important, so if mutant finds example groups in the
|
140
116
|
current prefix level, these example groups *must* kill the mutation.
|
141
117
|
|
118
|
+
Rails
|
119
|
+
-------
|
120
|
+
|
121
|
+
Assuming you are using rspec, you can mutation test Rails models by adding the following lines to your Gemfile:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
group :test do
|
125
|
+
gem 'mutant'
|
126
|
+
gem 'mutant-rspec'
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
130
|
+
Next, run bundle and comment out ```require 'rspec/autorun'``` from your spec_helper.rb file. Having done so you should be able to use commands like the following:
|
131
|
+
|
132
|
+
```sh
|
133
|
+
RAILS_ENV=test bundle exec mutant -r ./config/environment --use rspec User
|
134
|
+
```
|
135
|
+
|
142
136
|
Support
|
143
137
|
-------
|
144
138
|
|
@@ -150,7 +144,7 @@ Your options:
|
|
150
144
|
* Ping me on [twitter](https://twitter.com/_m_b_j_)
|
151
145
|
|
152
146
|
There is also the [#mutant] channel on freenode. As my OSS time budged is very limited I cannot
|
153
|
-
join it often. Please prefer to use
|
147
|
+
join it often. Please prefer to use GitHub issues with a 'Question: ' prefix in title.
|
154
148
|
|
155
149
|
Credits
|
156
150
|
-------
|
data/config/flay.yml
CHANGED
data/config/reek.yml
CHANGED
@@ -37,6 +37,7 @@ FeatureEnvy:
|
|
37
37
|
- Mutant::Matcher::Method::Singleton#receiver?
|
38
38
|
- Mutant::Mutation::Evil#success?
|
39
39
|
- Mutant::Mutation::Neutral#success?
|
40
|
+
- Mutant::Mutator::Node#children_indices
|
40
41
|
# False positive, its a utility
|
41
42
|
- Mutant::Meta::Example::Verification#format_mutation
|
42
43
|
- Mutant::Reporter::CLI#subject_results
|
@@ -67,7 +68,7 @@ NestedIterators:
|
|
67
68
|
- Mutant::Mutator::Node::Resbody#mutate_captures
|
68
69
|
- Mutant::Mutator::Node::Arguments#emit_argument_mutations
|
69
70
|
- Mutant::RequireHighjack#infect
|
70
|
-
- Mutant::RequireHighjack#
|
71
|
+
- Mutant::RequireHighjack#disinfect
|
71
72
|
- Mutant::Subject#tests
|
72
73
|
- Parser::Lexer#self.new
|
73
74
|
max_allowed_nesting: 1
|
data/lib/mutant/ast.rb
CHANGED
@@ -4,7 +4,8 @@ module Mutant
|
|
4
4
|
|
5
5
|
# Walk all ast nodes
|
6
6
|
#
|
7
|
-
# @param [Parser::AST::Node]
|
7
|
+
# @param [Parser::AST::Node] root
|
8
|
+
# @param [Array<Parser::AST::Node>] stack
|
8
9
|
#
|
9
10
|
# @yield [Parser::AST::Node]
|
10
11
|
# all nodes recursively including root
|
@@ -13,21 +14,24 @@ module Mutant
|
|
13
14
|
#
|
14
15
|
# @api private
|
15
16
|
#
|
16
|
-
def self.walk(node, &block)
|
17
|
+
def self.walk(node, stack, &block)
|
17
18
|
raise ArgumentError, 'block expected' unless block_given?
|
18
19
|
|
19
|
-
block.call(node)
|
20
|
+
block.call(node, stack)
|
20
21
|
node.children.grep(Parser::AST::Node).each do |child|
|
21
|
-
|
22
|
+
stack.push(child)
|
23
|
+
walk(child, stack, &block)
|
24
|
+
stack.pop
|
22
25
|
end
|
23
26
|
|
24
27
|
self
|
25
28
|
end
|
29
|
+
private_class_method :walk
|
26
30
|
|
27
|
-
# Find last node
|
31
|
+
# Find last node satisfying predicate (as block)
|
28
32
|
#
|
29
33
|
# @return [Parser::AST::Node]
|
30
|
-
# if
|
34
|
+
# if satisfying node is found
|
31
35
|
#
|
32
36
|
# @yield [Parser::AST::Node]
|
33
37
|
#
|
@@ -39,13 +43,15 @@ module Mutant
|
|
39
43
|
#
|
40
44
|
# @api private
|
41
45
|
#
|
42
|
-
def self.
|
46
|
+
def self.find_last_path(node, &predicate)
|
43
47
|
raise ArgumentError, 'block expected' unless block_given?
|
44
|
-
|
45
|
-
walk(node) do |candidate|
|
46
|
-
|
48
|
+
path = []
|
49
|
+
walk(node, [node]) do |candidate, stack|
|
50
|
+
if predicate.call(candidate, &predicate)
|
51
|
+
path = stack.dup
|
52
|
+
end
|
47
53
|
end
|
48
|
-
|
54
|
+
path
|
49
55
|
end
|
50
56
|
|
51
57
|
end # AST
|
data/lib/mutant/ast/meta.rb
CHANGED
@@ -17,14 +17,42 @@ module Mutant
|
|
17
17
|
REGISTRY.fetch(node.type, Generic).new(node)
|
18
18
|
end
|
19
19
|
|
20
|
-
#
|
20
|
+
# Mixin to define meta nodes
|
21
|
+
class Node < Module
|
22
|
+
include Concord.new(:type)
|
23
|
+
|
24
|
+
CONCORD = Concord.new(:node)
|
25
|
+
|
26
|
+
# Hook called when module gets included
|
27
|
+
#
|
28
|
+
# @param [Class, Module] host
|
29
|
+
#
|
30
|
+
# @return [undefined]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
#
|
34
|
+
def included(host)
|
35
|
+
REGISTRY[type] = host
|
36
|
+
host.class_eval do
|
37
|
+
include CONCORD, NamedChildren
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end # Node
|
42
|
+
|
43
|
+
# Metadata for resbody nods
|
44
|
+
class Resbody
|
45
|
+
include Node.new(:resbody)
|
46
|
+
|
47
|
+
children :captures, :assignment, :body
|
48
|
+
end # Resbody
|
49
|
+
|
50
|
+
# Metadata for send nodes
|
21
51
|
class Send
|
22
|
-
include
|
52
|
+
include Node.new(:send)
|
23
53
|
|
24
54
|
children :receiver, :selector
|
25
55
|
|
26
|
-
REGISTRY[:send] = self
|
27
|
-
|
28
56
|
INDEX_ASSIGNMENT_SELECTOR = :[]=
|
29
57
|
ATTRIBUTE_ASSIGNMENT_SELECTOR_SUFFIX = '='.freeze
|
30
58
|
|
@@ -100,7 +128,7 @@ module Mutant
|
|
100
128
|
|
101
129
|
end # Send
|
102
130
|
|
103
|
-
# Generic node
|
131
|
+
# Generic node metadata
|
104
132
|
class Generic
|
105
133
|
include Adamantium, Concord.new(:node)
|
106
134
|
|
data/lib/mutant/diff.rb
CHANGED
@@ -2,8 +2,8 @@ module Mutant
|
|
2
2
|
class Matcher
|
3
3
|
# Matcher for subjects that are a specific method
|
4
4
|
class Method < self
|
5
|
-
include Adamantium::Flat, Concord::Public.new(:env, :scope, :
|
6
|
-
include Equalizer.new(:identification)
|
5
|
+
include Adamantium::Flat, Concord::Public.new(:env, :scope, :target_method)
|
6
|
+
include AST::NodePredicates, Equalizer.new(:identification)
|
7
7
|
|
8
8
|
# Methods within rbx kernel directory are precompiled and their source
|
9
9
|
# cannot be accessed via reading source location. Same for methods created by eval.
|
@@ -40,7 +40,10 @@ module Mutant
|
|
40
40
|
def skip?
|
41
41
|
location = source_location
|
42
42
|
if location.nil? || BLACKLIST.match(location.first)
|
43
|
-
env.warn(format('%s does not have valid source location unable to emit
|
43
|
+
env.warn(format('%s does not have valid source location unable to emit subject', target_method.inspect))
|
44
|
+
true
|
45
|
+
elsif matched_node_path.any?(&method(:n_block?))
|
46
|
+
env.warn(format('%s is defined from a 3rd party lib unable to emit subject', target_method.inspect))
|
44
47
|
true
|
45
48
|
else
|
46
49
|
false
|
@@ -54,7 +57,7 @@ module Mutant
|
|
54
57
|
# @api private
|
55
58
|
#
|
56
59
|
def method_name
|
57
|
-
|
60
|
+
target_method.name
|
58
61
|
end
|
59
62
|
|
60
63
|
# Return context
|
@@ -104,7 +107,7 @@ module Mutant
|
|
104
107
|
# @api private
|
105
108
|
#
|
106
109
|
def source_location
|
107
|
-
|
110
|
+
target_method.source_location
|
108
111
|
end
|
109
112
|
|
110
113
|
# Return subject
|
@@ -118,27 +121,22 @@ module Mutant
|
|
118
121
|
# @api private
|
119
122
|
#
|
120
123
|
def subject
|
121
|
-
node =
|
124
|
+
node = matched_node_path.last
|
122
125
|
return unless node
|
123
126
|
self.class::SUBJECT_CLASS.new(env.config, context, node)
|
124
127
|
end
|
125
128
|
memoize :subject
|
126
129
|
|
127
|
-
# Return matched node
|
128
|
-
#
|
129
|
-
# @return [Parser::AST::Node]
|
130
|
-
# if node could be found
|
130
|
+
# Return matched node path
|
131
131
|
#
|
132
|
-
# @return [
|
133
|
-
# otherwise
|
132
|
+
# @return [Array<Parser::AST::Node>]
|
134
133
|
#
|
135
134
|
# @api private
|
136
135
|
#
|
137
|
-
def
|
138
|
-
AST.
|
139
|
-
match?(node)
|
140
|
-
end
|
136
|
+
def matched_node_path
|
137
|
+
AST.find_last_path(ast, &method(:match?))
|
141
138
|
end
|
139
|
+
memoize :matched_node_path
|
142
140
|
|
143
141
|
end # Method
|
144
142
|
end # Matcher
|
@@ -15,10 +15,10 @@ module Mutant
|
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
#
|
18
|
-
def self.build(env, scope,
|
19
|
-
name =
|
18
|
+
def self.build(env, scope, target_method)
|
19
|
+
name = target_method.name
|
20
20
|
if scope.ancestors.include?(::Memoizable) && scope.memoized?(name)
|
21
|
-
return Memoized.new(env, scope,
|
21
|
+
return Memoized.new(env, scope, target_method)
|
22
22
|
end
|
23
23
|
super
|
24
24
|
end
|
@@ -68,7 +68,7 @@ module Mutant
|
|
68
68
|
# @api private
|
69
69
|
#
|
70
70
|
def source_location
|
71
|
-
scope.unmemoized_instance_method(
|
71
|
+
scope.unmemoized_instance_method(method_name).source_location
|
72
72
|
end
|
73
73
|
|
74
74
|
end # Memoized
|
data/lib/mutant/meta.rb
CHANGED
data/lib/mutant/meta/example.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Mutant
|
2
2
|
module Meta
|
3
3
|
class Example
|
4
|
-
include Adamantium, Concord::Public.new(:node, :mutations)
|
4
|
+
include Adamantium, Concord::Public.new(:file, :node, :mutations)
|
5
5
|
|
6
6
|
# Return a verification instance
|
7
7
|
#
|
@@ -26,7 +26,7 @@ module Mutant
|
|
26
26
|
|
27
27
|
# Return generated mutations
|
28
28
|
#
|
29
|
-
# @return [
|
29
|
+
# @return [Enumerable<Mutant::Mutation>]
|
30
30
|
#
|
31
31
|
# @api private
|
32
32
|
#
|
@@ -97,7 +97,7 @@ module Mutant
|
|
97
97
|
def mutation_report
|
98
98
|
original_node = example.node
|
99
99
|
[
|
100
|
-
|
100
|
+
"#{example.file}, Original-AST:",
|
101
101
|
original_node.inspect,
|
102
102
|
'Original-Source:',
|
103
103
|
example.source,
|
@@ -12,8 +12,8 @@ module Mutant
|
|
12
12
|
#
|
13
13
|
# @api private
|
14
14
|
#
|
15
|
-
def self.run(block)
|
16
|
-
instance = new
|
15
|
+
def self.run(file, block)
|
16
|
+
instance = new(file)
|
17
17
|
instance.instance_eval(&block)
|
18
18
|
instance.example
|
19
19
|
end
|
@@ -24,7 +24,8 @@ module Mutant
|
|
24
24
|
#
|
25
25
|
# @api private
|
26
26
|
#
|
27
|
-
def initialize
|
27
|
+
def initialize(file)
|
28
|
+
@file = file
|
28
29
|
@source = nil
|
29
30
|
@expected = []
|
30
31
|
end
|
@@ -40,7 +41,7 @@ module Mutant
|
|
40
41
|
#
|
41
42
|
def example
|
42
43
|
raise 'source not defined' unless @source
|
43
|
-
Example.new(@source, @expected)
|
44
|
+
Example.new(@file, @source, @expected)
|
44
45
|
end
|
45
46
|
|
46
47
|
private
|
data/lib/mutant/mutator/node.rb
CHANGED
@@ -8,6 +8,8 @@ module Mutant
|
|
8
8
|
include AbstractType, Unparser::Constants
|
9
9
|
include AST::NamedChildren, AST::NodePredicates, AST::Sexp, AST::Nodes
|
10
10
|
|
11
|
+
TAUTOLOGY = ->(_input) { true }
|
12
|
+
|
11
13
|
# Helper to define a named child
|
12
14
|
#
|
13
15
|
# @param [Parser::AST::Node] node
|
@@ -79,7 +81,7 @@ module Mutant
|
|
79
81
|
# @api private
|
80
82
|
#
|
81
83
|
def mutate_child(index, mutator = Mutator, &block)
|
82
|
-
block ||=
|
84
|
+
block ||= TAUTOLOGY
|
83
85
|
child = children.at(index)
|
84
86
|
mutator.each(child, self) do |mutation|
|
85
87
|
next unless block.call(mutation)
|
@@ -211,6 +213,20 @@ module Mutant
|
|
211
213
|
AST::Types::OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
|
212
214
|
end
|
213
215
|
|
216
|
+
# Return children indices
|
217
|
+
#
|
218
|
+
# @param [Range] range
|
219
|
+
#
|
220
|
+
# @return [Enumerable<Fixnum>]
|
221
|
+
#
|
222
|
+
# @api pirvate
|
223
|
+
#
|
224
|
+
def children_indices(range)
|
225
|
+
range_end = range.end
|
226
|
+
last_index = range_end >= 0 ? range_end : children.length + range_end
|
227
|
+
range.begin.upto(last_index)
|
228
|
+
end
|
229
|
+
|
214
230
|
end # Node
|
215
231
|
end # Mutator
|
216
232
|
end # Mutant
|
@@ -2,10 +2,86 @@ module Mutant
|
|
2
2
|
class Mutator
|
3
3
|
class Node
|
4
4
|
# Mutator for rescue nodes
|
5
|
-
class Rescue <
|
5
|
+
class Rescue < self
|
6
6
|
|
7
7
|
handle :rescue
|
8
8
|
|
9
|
+
children :body
|
10
|
+
|
11
|
+
define_named_child(:else_body, -1)
|
12
|
+
|
13
|
+
RESCUE_INDICES = (1..-2).freeze
|
14
|
+
|
15
|
+
# Emit mutations
|
16
|
+
#
|
17
|
+
# @return [undefined]
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
def dispatch
|
22
|
+
mutate_body
|
23
|
+
mutate_rescue_bodies
|
24
|
+
mutate_else_body
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Mutate child by name
|
30
|
+
#
|
31
|
+
# @return [undefined]
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
def mutate_rescue_bodies
|
36
|
+
children_indices(RESCUE_INDICES).each do |index|
|
37
|
+
rescue_body = children.at(index)
|
38
|
+
next unless rescue_body
|
39
|
+
mutate_child(index)
|
40
|
+
resbody_body = AST::Meta.for(rescue_body).body
|
41
|
+
emit_concat(resbody_body) if resbody_body
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Emit concatenation with body
|
46
|
+
#
|
47
|
+
# @param [Parser::AST::Node] child
|
48
|
+
#
|
49
|
+
# @return [undefined]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
#
|
53
|
+
def emit_concat(child)
|
54
|
+
if body
|
55
|
+
emit(s(:begin, body, child))
|
56
|
+
else
|
57
|
+
emit(child)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Emit body mutations
|
62
|
+
#
|
63
|
+
# @return [undefined]
|
64
|
+
#
|
65
|
+
# @api private
|
66
|
+
#
|
67
|
+
def mutate_body
|
68
|
+
return unless body
|
69
|
+
emit_body_mutations
|
70
|
+
emit(body)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Emit else body mutations
|
74
|
+
#
|
75
|
+
# @return [undefined]
|
76
|
+
#
|
77
|
+
# @api private
|
78
|
+
#
|
79
|
+
def mutate_else_body
|
80
|
+
return unless else_body
|
81
|
+
emit_else_body_mutations
|
82
|
+
emit_concat(else_body)
|
83
|
+
end
|
84
|
+
|
9
85
|
end # Rescue
|
10
86
|
end # Node
|
11
87
|
end # Mutator
|
@@ -22,7 +22,7 @@ module Mutant
|
|
22
22
|
yield
|
23
23
|
self
|
24
24
|
ensure
|
25
|
-
|
25
|
+
disinfect
|
26
26
|
end
|
27
27
|
|
28
28
|
# Infect kernel with highjack
|
@@ -43,13 +43,13 @@ module Mutant
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
# Imperfectly
|
46
|
+
# Imperfectly disinfect kernel from highjack
|
47
47
|
#
|
48
48
|
# @return [self]
|
49
49
|
#
|
50
50
|
# @api private
|
51
51
|
#
|
52
|
-
def
|
52
|
+
def disinfect
|
53
53
|
original = @original
|
54
54
|
target.module_eval do
|
55
55
|
undef :require
|
data/lib/mutant/runner.rb
CHANGED
data/lib/mutant/subject.rb
CHANGED
data/lib/mutant/version.rb
CHANGED
data/meta/def.rb
CHANGED
@@ -13,6 +13,36 @@ Mutant::Meta::Example.add do
|
|
13
13
|
mutation 'def foo; nil; rescue; end'
|
14
14
|
mutation 'def foo; self; rescue; end'
|
15
15
|
mutation 'def foo; end'
|
16
|
+
|
17
|
+
# Promote rescue resbody bodies
|
18
|
+
mutation 'def foo; foo; end'
|
19
|
+
end
|
20
|
+
|
21
|
+
Mutant::Meta::Example.add do
|
22
|
+
source 'def a; foo; rescue; bar; else; baz; end'
|
23
|
+
|
24
|
+
# Mutate all bodies
|
25
|
+
mutation 'def a; nil; rescue; bar; else; baz; end'
|
26
|
+
mutation 'def a; self; rescue; bar; else; baz; end'
|
27
|
+
mutation 'def a; foo; rescue; nil; else; baz; end'
|
28
|
+
mutation 'def a; foo; rescue; self; else; baz; end'
|
29
|
+
mutation 'def a; foo; rescue; bar; else; nil; end'
|
30
|
+
mutation 'def a; foo; rescue; bar; else; self; end'
|
31
|
+
|
32
|
+
# Promote and concat rescue resbody bodies
|
33
|
+
mutation 'def a; foo; bar; end'
|
34
|
+
|
35
|
+
# Promote and concat else body
|
36
|
+
mutation 'def a; foo; baz; end'
|
37
|
+
|
38
|
+
# Promote rescue body
|
39
|
+
mutation 'def a; foo; end'
|
40
|
+
|
41
|
+
# Empty body
|
42
|
+
mutation 'def a; end'
|
43
|
+
|
44
|
+
# Failing body
|
45
|
+
mutation 'def a; raise; end'
|
16
46
|
end
|
17
47
|
|
18
48
|
Mutant::Meta::Example.add do
|
data/meta/if.rb
CHANGED
@@ -14,7 +14,7 @@ Mutant::Meta::Example.add do
|
|
14
14
|
# Deleted else branch
|
15
15
|
mutation 'if condition; true end'
|
16
16
|
|
17
|
-
# Deleted if branch
|
17
|
+
# Deleted if branch resulting in unless rendering
|
18
18
|
mutation 'unless condition; false; end'
|
19
19
|
|
20
20
|
# Deleted if branch with promoting else branch to if branch
|
data/meta/rescue.rb
CHANGED
@@ -9,6 +9,8 @@ Mutant::Meta::Example.add do
|
|
9
9
|
mutation 'begin; rescue ExceptionA, self => error; true; end'
|
10
10
|
mutation 'begin; rescue ExceptionA, ExceptionB => error; false; end'
|
11
11
|
mutation 'begin; rescue ExceptionA, ExceptionB => error; nil; end'
|
12
|
+
mutation 'begin; true; end'
|
13
|
+
|
12
14
|
end
|
13
15
|
|
14
16
|
Mutant::Meta::Example.add do
|
@@ -19,6 +21,7 @@ Mutant::Meta::Example.add do
|
|
19
21
|
mutation 'begin; rescue SomeException => error; false; end'
|
20
22
|
mutation 'begin; rescue SomeException => error; nil; end'
|
21
23
|
mutation 'begin; rescue self => error; true; end'
|
24
|
+
mutation 'begin; true; end'
|
22
25
|
end
|
23
26
|
|
24
27
|
Mutant::Meta::Example.add do
|
@@ -28,6 +31,7 @@ Mutant::Meta::Example.add do
|
|
28
31
|
mutation 'begin; rescue => error; false; end'
|
29
32
|
mutation 'begin; rescue => error; nil; end'
|
30
33
|
mutation 'begin; rescue; true; end'
|
34
|
+
mutation 'begin; true; end'
|
31
35
|
end
|
32
36
|
|
33
37
|
Mutant::Meta::Example.add do
|
@@ -36,4 +40,5 @@ Mutant::Meta::Example.add do
|
|
36
40
|
singleton_mutations
|
37
41
|
mutation 'begin; rescue; false; end'
|
38
42
|
mutation 'begin; rescue; nil; end'
|
43
|
+
mutation 'begin; true end'
|
39
44
|
end
|
data/meta/super.rb
CHANGED
data/mutant.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |gem|
|
|
26
26
|
gem.add_runtime_dependency('parser', '~> 2.1')
|
27
27
|
gem.add_runtime_dependency('ast', '~> 2.0')
|
28
28
|
gem.add_runtime_dependency('diff-lcs', '~> 1.2')
|
29
|
+
gem.add_runtime_dependency('parallel', '~> 1.3')
|
29
30
|
gem.add_runtime_dependency('morpher', '~> 0.2.3')
|
30
31
|
gem.add_runtime_dependency('procto', '~> 0.0.2')
|
31
32
|
gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
|
@@ -37,7 +38,6 @@ Gem::Specification.new do |gem|
|
|
37
38
|
gem.add_runtime_dependency('inflecto', '~> 0.0.2')
|
38
39
|
gem.add_runtime_dependency('anima', '~> 0.2.0')
|
39
40
|
gem.add_runtime_dependency('concord', '~> 0.1.5')
|
40
|
-
gem.add_runtime_dependency('parallel', '~> 1.2.0')
|
41
41
|
|
42
42
|
gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
|
43
43
|
end
|
@@ -17,7 +17,7 @@ RSpec.shared_examples_for 'a method matcher' do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'should have correct line number' do
|
20
|
-
expect(node.location.expression.line
|
20
|
+
expect(node.location.expression.line).to eql(method_line)
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'should have correct arity' do
|
@@ -0,0 +1,38 @@
|
|
1
|
+
RSpec.describe Mutant::AST do
|
2
|
+
let(:object) { described_class }
|
3
|
+
|
4
|
+
describe '.find_last_path' do
|
5
|
+
subject { object.find_last_path(root, &block) }
|
6
|
+
|
7
|
+
let(:root) { s(:root, parent) }
|
8
|
+
let(:child_a) { s(:child_a) }
|
9
|
+
let(:child_b) { s(:child_b) }
|
10
|
+
let(:parent) { s(:parent, child_a, child_b) }
|
11
|
+
|
12
|
+
def path
|
13
|
+
subject.map(&:type)
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when no node matches' do
|
17
|
+
let(:block) { ->(_) { false } }
|
18
|
+
|
19
|
+
it { should eql([]) }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when one node matches' do
|
23
|
+
let(:block) { ->(node) { node.equal?(child_a) } }
|
24
|
+
|
25
|
+
it 'returns the full path' do
|
26
|
+
expect(path).to eql([:root, :parent, :child_a])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when two nodes match' do
|
31
|
+
let(:block) { ->(node) { node.equal?(child_a) || node.equal?(child_b) } }
|
32
|
+
|
33
|
+
it 'returns the last full path' do
|
34
|
+
expect(path).to eql([:root, :parent, :child_b])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -11,10 +11,10 @@ RSpec.describe Mutant::Matcher::Method::Instance do
|
|
11
11
|
let(:method) { scope.instance_method(method_name) }
|
12
12
|
let(:yields) { [] }
|
13
13
|
let(:namespace) { self.class }
|
14
|
-
let(:scope) { self.class::Foo }
|
15
14
|
let(:type) { :def }
|
16
|
-
let(:method_name) { :
|
15
|
+
let(:method_name) { :foo }
|
17
16
|
let(:method_arity) { 0 }
|
17
|
+
let(:base) { TestApp::InstanceMethodTests }
|
18
18
|
|
19
19
|
def name
|
20
20
|
node.children[0]
|
@@ -36,109 +36,79 @@ RSpec.describe Mutant::Matcher::Method::Instance do
|
|
36
36
|
it 'does warn' do
|
37
37
|
subject
|
38
38
|
expect(reporter.warn_calls.last).to(
|
39
|
-
eql("#{method.inspect} does not have valid source location unable to emit
|
39
|
+
eql("#{method.inspect} does not have valid source location unable to emit subject")
|
40
40
|
)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
context 'when method is defined once' do
|
45
|
-
let(:
|
46
|
-
|
47
|
-
def bar; end
|
48
|
-
end
|
49
|
-
|
50
|
-
let(:method_line) { 2 }
|
45
|
+
let(:scope) { base::DefinedOnce }
|
46
|
+
let(:method_line) { 7 }
|
51
47
|
|
52
48
|
it_should_behave_like 'a method matcher'
|
53
49
|
end
|
54
50
|
|
55
51
|
context 'when method is defined once with a memoizer' do
|
56
|
-
let(:
|
57
|
-
|
58
|
-
def bar; end
|
59
|
-
include Adamantium
|
60
|
-
memoize :bar
|
61
|
-
end
|
62
|
-
|
63
|
-
let(:method_line) { 2 }
|
52
|
+
let(:scope) { base::WithMemoizer }
|
53
|
+
let(:method_line) { 12 }
|
64
54
|
|
65
55
|
it_should_behave_like 'a method matcher'
|
66
56
|
end
|
67
57
|
|
68
58
|
context 'when method is defined multiple times' do
|
69
59
|
context 'on different lines' do
|
70
|
-
let(:
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
def bar(_arg)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
let(:method_line) { 5 }
|
80
|
-
let(:method_arity) { 1 }
|
60
|
+
let(:scope) { base::DefinedMultipleTimes::DifferentLines }
|
61
|
+
let(:method_line) { 21 }
|
62
|
+
let(:method_arity) { 1 }
|
81
63
|
|
82
64
|
it_should_behave_like 'a method matcher'
|
83
65
|
end
|
84
66
|
|
85
67
|
context 'on the same line' do
|
86
|
-
let(:
|
87
|
-
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
|
-
let(:method_line) { 2 }
|
92
|
-
let(:method_arity) { 1 }
|
68
|
+
let(:scope) { base::DefinedMultipleTimes::SameLineSameScope }
|
69
|
+
let(:method_line) { 26 }
|
70
|
+
let(:method_arity) { 1 }
|
93
71
|
|
94
72
|
it_should_behave_like 'a method matcher'
|
95
73
|
end
|
96
74
|
|
97
75
|
context 'on the same line with different scope' do
|
98
|
-
let(:
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
let(:method_line) { 2 }
|
104
|
-
let(:method_arity) { 1 }
|
76
|
+
let(:scope) { base::DefinedMultipleTimes::SameLineDifferentScope }
|
77
|
+
let(:method_line) { 30 }
|
78
|
+
let(:method_arity) { 1 }
|
105
79
|
|
106
80
|
it_should_behave_like 'a method matcher'
|
107
81
|
end
|
108
82
|
|
109
|
-
context '
|
110
|
-
let(:
|
83
|
+
context 'in module eval' do
|
84
|
+
let(:scope) { base::InModuleEval }
|
111
85
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
def baz
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
let(:method_line) { 3 }
|
122
|
-
let(:method_name) { :baz }
|
123
|
-
let(:scope) { self.class::Foo::Bar }
|
86
|
+
it 'does not emit matcher' do
|
87
|
+
subject
|
88
|
+
expect(yields.length).to be(0)
|
89
|
+
end
|
124
90
|
|
125
|
-
|
91
|
+
it 'does warn' do
|
92
|
+
subject
|
93
|
+
expect(reporter.warn_calls.last).to(
|
94
|
+
eql("#{method.inspect} is defined from a 3rd party lib unable to emit subject")
|
95
|
+
)
|
126
96
|
end
|
97
|
+
end
|
127
98
|
|
128
|
-
|
129
|
-
|
130
|
-
module self::Foo
|
131
|
-
class Bar
|
132
|
-
def baz
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
99
|
+
context 'in class eval' do
|
100
|
+
let(:scope) { base::InClassEval }
|
136
101
|
|
137
|
-
|
138
|
-
|
139
|
-
|
102
|
+
it 'does not emit matcher' do
|
103
|
+
subject
|
104
|
+
expect(yields.length).to be(0)
|
105
|
+
end
|
140
106
|
|
141
|
-
|
107
|
+
it 'does warn' do
|
108
|
+
subject
|
109
|
+
expect(reporter.warn_calls.last).to(
|
110
|
+
eql("#{method.inspect} is defined from a 3rd party lib unable to emit subject")
|
111
|
+
)
|
142
112
|
end
|
143
113
|
end
|
144
114
|
end
|
@@ -6,10 +6,10 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do
|
|
6
6
|
let(:method) { scope.method(method_name) }
|
7
7
|
let(:env) { Fixtures::TEST_ENV }
|
8
8
|
let(:yields) { [] }
|
9
|
-
let(:namespace) { self.class }
|
10
|
-
let(:scope) { self.class::Foo }
|
11
9
|
let(:type) { :defs }
|
10
|
+
let(:method_name) { :foo }
|
12
11
|
let(:method_arity) { 0 }
|
12
|
+
let(:base) { TestApp::SingletonMethodTests }
|
13
13
|
|
14
14
|
def name
|
15
15
|
node.children[1]
|
@@ -22,14 +22,8 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do
|
|
22
22
|
context 'on singleton methods' do
|
23
23
|
|
24
24
|
context 'when also defined on lvar' do
|
25
|
-
let(:
|
26
|
-
|
27
|
-
a = Object.new
|
28
|
-
def a.bar; end; def self.bar; end
|
29
|
-
end
|
30
|
-
|
31
|
-
let(:method_name) { :bar }
|
32
|
-
let(:method_line) { 3 }
|
25
|
+
let(:scope) { base::AlsoDefinedOnLvar }
|
26
|
+
let(:method_line) { 63 }
|
33
27
|
|
34
28
|
it_should_behave_like 'a method matcher'
|
35
29
|
|
@@ -42,13 +36,8 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do
|
|
42
36
|
end
|
43
37
|
|
44
38
|
context 'when defined on self' do
|
45
|
-
let(:
|
46
|
-
|
47
|
-
def self.bar; end
|
48
|
-
end
|
49
|
-
|
50
|
-
let(:method_name) { :bar }
|
51
|
-
let(:method_line) { 2 }
|
39
|
+
let(:scope) { base::DefinedOnSelf }
|
40
|
+
let(:method_line) { 58 }
|
52
41
|
|
53
42
|
it_should_behave_like 'a method matcher'
|
54
43
|
end
|
@@ -56,34 +45,15 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do
|
|
56
45
|
context 'when defined on constant' do
|
57
46
|
|
58
47
|
context 'inside namespace' do
|
59
|
-
let(:
|
60
|
-
|
61
|
-
class Foo
|
62
|
-
def Foo.bar
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
let(:scope) { self.class::Namespace::Foo }
|
68
|
-
let(:method_name) { :bar }
|
69
|
-
let(:method_line) { 3 }
|
48
|
+
let(:scope) { base::DefinedOnConstant::InsideNamespace }
|
49
|
+
let(:method_line) { 68 }
|
70
50
|
|
71
51
|
it_should_behave_like 'a method matcher'
|
72
52
|
end
|
73
53
|
|
74
54
|
context 'outside namespace' do
|
75
|
-
let(:
|
76
|
-
|
77
|
-
class Foo
|
78
|
-
end
|
79
|
-
|
80
|
-
def Foo.bar
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
let(:method_name) { :bar }
|
85
|
-
let(:method_line) { 5 }
|
86
|
-
let(:scope) { self.class::Namespace::Foo }
|
55
|
+
let(:method_line) { 75 }
|
56
|
+
let(:scope) { base::DefinedOnConstant::OutsideNamespace }
|
87
57
|
|
88
58
|
it_should_behave_like 'a method matcher'
|
89
59
|
end
|
@@ -91,21 +61,9 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do
|
|
91
61
|
|
92
62
|
context 'when defined multiple times in the same line' do
|
93
63
|
context 'with method on different scope' do
|
94
|
-
let(:
|
95
|
-
|
96
|
-
|
97
|
-
module Bar
|
98
|
-
def self.baz
|
99
|
-
end
|
100
|
-
def Foo.baz(_arg)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
let(:scope) { self.class::Namespace::Bar }
|
106
|
-
let(:method_name) { :baz }
|
107
|
-
let(:method_line) { 4 }
|
108
|
-
let(:method_arity) { 0 }
|
64
|
+
let(:scope) { base::DefinedMultipleTimes::SameLine::DifferentScope }
|
65
|
+
let(:method_line) { 94 }
|
66
|
+
let(:method_arity) { 1 }
|
109
67
|
|
110
68
|
it_should_behave_like 'a method matcher'
|
111
69
|
end
|
data/test_app/lib/test_app.rb
CHANGED
@@ -2,6 +2,100 @@
|
|
2
2
|
|
3
3
|
# Namespace for test application
|
4
4
|
module TestApp
|
5
|
+
module InstanceMethodTests
|
6
|
+
module DefinedOnce
|
7
|
+
def foo; end
|
8
|
+
end
|
9
|
+
|
10
|
+
class WithMemoizer
|
11
|
+
include Adamantium
|
12
|
+
def foo; end
|
13
|
+
memoize :foo
|
14
|
+
end
|
15
|
+
|
16
|
+
module DefinedMultipleTimes
|
17
|
+
class DifferentLines
|
18
|
+
def foo
|
19
|
+
end
|
20
|
+
|
21
|
+
def foo(_arg)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class SameLineSameScope
|
26
|
+
def foo; end; def foo(_arg); end
|
27
|
+
end
|
28
|
+
|
29
|
+
class SameLineDifferentScope
|
30
|
+
def self.foo; end; def foo(_arg); end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class InClassEval
|
35
|
+
class_eval do
|
36
|
+
def foo
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class InModuleEval
|
42
|
+
module_eval do
|
43
|
+
def foo
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class InInstanceEval
|
49
|
+
module_eval do
|
50
|
+
def foo
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module SingletonMethodTests
|
57
|
+
module DefinedOnSelf
|
58
|
+
def self.foo; end
|
59
|
+
end
|
60
|
+
|
61
|
+
module AlsoDefinedOnLvar
|
62
|
+
a = Object.new
|
63
|
+
def a.foo; end; def self.foo; end
|
64
|
+
end
|
65
|
+
|
66
|
+
module DefinedOnConstant
|
67
|
+
module InsideNamespace
|
68
|
+
def InsideNamespace.foo
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
module OutsideNamespace
|
73
|
+
end
|
74
|
+
|
75
|
+
def OutsideNamespace.foo
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module DefinedMultipleTimes
|
80
|
+
module DifferentLines
|
81
|
+
def self.foo
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.foo(_arg)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
module SameLine
|
89
|
+
module SameScope
|
90
|
+
def self.foo; end; def self.foo(_arg); end;
|
91
|
+
end
|
92
|
+
|
93
|
+
module DifferentScope
|
94
|
+
def self.foo; end; def DifferentScope.foo(_arg); end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
5
99
|
end
|
6
100
|
|
7
101
|
require 'test_app/literal'
|
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.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Schirp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: parallel
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: morpher
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,20 +220,6 @@ dependencies:
|
|
206
220
|
- - "~>"
|
207
221
|
- !ruby/object:Gem::Version
|
208
222
|
version: 0.1.5
|
209
|
-
- !ruby/object:Gem::Dependency
|
210
|
-
name: parallel
|
211
|
-
requirement: !ruby/object:Gem::Requirement
|
212
|
-
requirements:
|
213
|
-
- - "~>"
|
214
|
-
- !ruby/object:Gem::Version
|
215
|
-
version: 1.2.0
|
216
|
-
type: :runtime
|
217
|
-
prerelease: false
|
218
|
-
version_requirements: !ruby/object:Gem::Requirement
|
219
|
-
requirements:
|
220
|
-
- - "~>"
|
221
|
-
- !ruby/object:Gem::Version
|
222
|
-
version: 1.2.0
|
223
223
|
- !ruby/object:Gem::Dependency
|
224
224
|
name: bundler
|
225
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -465,6 +465,7 @@ files:
|
|
465
465
|
- spec/support/mutation_verifier.rb
|
466
466
|
- spec/support/rspec.rb
|
467
467
|
- spec/support/test_app.rb
|
468
|
+
- spec/unit/mutant/ast_spec.rb
|
468
469
|
- spec/unit/mutant/cli_spec.rb
|
469
470
|
- spec/unit/mutant/context/root_spec.rb
|
470
471
|
- spec/unit/mutant/context/scope/root_spec.rb
|
@@ -541,6 +542,7 @@ test_files:
|
|
541
542
|
- spec/integration/mutant/rspec_spec.rb
|
542
543
|
- spec/integration/mutant/test_mutator_handles_types_spec.rb
|
543
544
|
- spec/integration/mutant/zombie_spec.rb
|
545
|
+
- spec/unit/mutant/ast_spec.rb
|
544
546
|
- spec/unit/mutant/cli_spec.rb
|
545
547
|
- spec/unit/mutant/context/root_spec.rb
|
546
548
|
- spec/unit/mutant/context/scope/root_spec.rb
|
@@ -578,4 +580,3 @@ test_files:
|
|
578
580
|
- spec/unit/mutant/warning_expectation.rb
|
579
581
|
- spec/unit/mutant/warning_filter_spec.rb
|
580
582
|
- spec/unit/mutant_spec.rb
|
581
|
-
has_rdoc:
|