mutant 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +9 -0
- data/Gemfile +4 -6
- data/Gemfile.devtools +65 -0
- data/Rakefile +2 -2
- data/config/devtools.yml +2 -0
- data/config/flay.yml +1 -1
- data/config/rubocop.yml +8 -9
- data/lib/mutant.rb +26 -3
- data/lib/mutant/cli/builder.rb +0 -11
- data/lib/mutant/constants.rb +12 -18
- data/lib/mutant/loader.rb +7 -16
- data/lib/mutant/mutation.rb +1 -1
- data/lib/mutant/mutator/node/binary.rb +58 -0
- data/lib/mutant/mutator/node/{while.rb → conditional_loop.rb} +2 -2
- data/lib/mutant/mutator/node/generic.rb +2 -1
- data/lib/mutant/node_helpers.rb +1 -1
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/zombifier.rb +2 -1
- data/mutant.gemspec +4 -3
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +1 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/mutant/cli/classifier/method_spec.rb +1 -1
- data/spec/unit/mutant/cli/classifier/namespace/flat_spec.rb +2 -2
- data/spec/unit/mutant/cli/classifier/namespace/recursive_spec.rb +2 -2
- data/spec/unit/mutant/differ_spec.rb +42 -0
- data/spec/unit/mutant/killer/{rspec/class_methods/new_spec.rb → rspec_spec.rb} +0 -0
- data/spec/unit/mutant/loader/{eval/class_methods/run_spec.rb → eval_spec.rb} +2 -2
- data/spec/unit/mutant/matcher/chain_spec.rb +57 -0
- data/spec/unit/mutant/matcher/method/instance_spec.rb +155 -0
- data/spec/unit/mutant/matcher/method/{singleton/each_spec.rb → singleton_spec.rb} +0 -0
- data/spec/unit/mutant/matcher/methods/{instance/each_spec.rb → instance_spec.rb} +0 -0
- data/spec/unit/mutant/matcher/methods/{singleton/each_spec.rb → singleton_spec.rb} +0 -0
- data/spec/unit/mutant/matcher/{namespace/each_spec.rb → namespace_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{and_asgn/mutation_spec.rb → and_asgn_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{begin/mutation_spec.rb → begin_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{connective/binary/mutation_spec.rb → binary_spec.rb} +1 -1
- data/spec/unit/mutant/mutator/node/{block_pass/mutation_spec.rb → block_pass_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{block/mutation_spec.rb → block_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{blockarg/mutation_spec.rb → blockarg_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{case/mutation_spec.rb → case_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{cbase/mutation_spec.rb → cbase_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/conditional_loop_spec.rb +42 -0
- data/spec/unit/mutant/mutator/node/{const/mutation_spec.rb → const_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{define/mutation_spec.rb → define_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{defined_predicate/mutation_spec.rb → defined_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{dstr/mutation_spec.rb → dstr_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{dsym/mutation_spec.rb → dsym_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{ensure/mutation_spec.rb → ensure_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{if/mutation_spec.rb → if_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{kwbegin/mutation_spec.rb → kwbegin_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/literal/{boolean/mutation_spec.rb → boolean_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{masgn/mutation_spec.rb → masgn_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{match_current_line/mutation_spec.rb → match_current_line_spec.rb} +1 -1
- data/spec/unit/mutant/mutator/node/named_value/{access/mutation_spec.rb → access_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/named_value/{constant_assignment/mutation_spec.rb → constant_assignment_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/named_value/{variable_assignment/mutation_spec.rb → variable_assignment_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{nthref/mutation_spec.rb → nthref_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{op_assgn/mutation_spec.rb → op_assgn_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{or_asgn/mutation_spec.rb → or_asgn_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{redo/mutation_spec.rb → redo_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{rescue/mutation_spec.rb → rescue_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{restarg/mutation_spec.rb → restarg_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{return/mutation_spec.rb → return_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{send/mutation_spec.rb → send_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{super/mutation_spec.rb → super_spec.rb} +0 -0
- data/spec/unit/mutant/mutator/node/{yield/mutation_spec.rb → yield_spec.rb} +0 -0
- data/spec/unit/mutant/mutator_spec.rb +29 -0
- data/spec/unit/mutant/runner/config_spec.rb +88 -0
- data/spec/unit/mutant/runner/{subject/success_predicate_spec.rb → subject_spec.rb} +0 -0
- data/spec/unit/mutant_spec.rb +43 -0
- data/test_app/Gemfile.devtools +65 -0
- metadata +119 -119
- data/lib/mutant/mutator/node/connective/binary.rb +0 -61
- data/lib/mutant/support/method_object.rb +0 -34
- data/spec/unit/mutant/class_methods/singleton_subclass_instance_spec.rb +0 -41
- data/spec/unit/mutant/differ/class_methods/build_spec.rb +0 -14
- data/spec/unit/mutant/differ/class_methods/colorize_line_spec.rb +0 -27
- data/spec/unit/mutant/matcher/chain/each_spec.rb +0 -43
- data/spec/unit/mutant/matcher/chain/matchers_spec.rb +0 -14
- data/spec/unit/mutant/matcher/each_spec.rb +0 -21
- data/spec/unit/mutant/matcher/method/instance/class_methods/build_spec.rb +0 -42
- data/spec/unit/mutant/matcher/method/instance/each_spec.rb +0 -114
- data/spec/unit/mutant/mutator/each_spec.rb +0 -27
- data/spec/unit/mutant/mutator/emit_new_spec.rb +0 -59
- data/spec/unit/mutant/mutator/emit_spec.rb +0 -55
- data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +0 -24
- data/spec/unit/mutant/node_helpers/n_not_spec.rb +0 -14
- data/spec/unit/mutant/runner/config/subjects_spec.rb +0 -52
- data/spec/unit/mutant/runner/config/success_predicate_spec.rb +0 -57
data/mutant.gemspec
CHANGED
@@ -18,12 +18,13 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.extra_rdoc_files = %w[TODO LICENSE]
|
19
19
|
gem.executables = %w[mutant]
|
20
20
|
|
21
|
-
gem.add_runtime_dependency('parser', '~> 2.
|
21
|
+
gem.add_runtime_dependency('parser', '~> 2.1.0')
|
22
|
+
gem.add_runtime_dependency('procto', '~> 0.0.2')
|
22
23
|
gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
|
23
|
-
gem.add_runtime_dependency('unparser', '~> 0.1.
|
24
|
+
gem.add_runtime_dependency('unparser', '~> 0.1.6')
|
24
25
|
gem.add_runtime_dependency('ice_nine', '~> 0.9')
|
25
26
|
gem.add_runtime_dependency('descendants_tracker', '~> 0.0.1')
|
26
|
-
gem.add_runtime_dependency('adamantium', '~> 0.1
|
27
|
+
gem.add_runtime_dependency('adamantium', '~> 0.1')
|
27
28
|
gem.add_runtime_dependency('equalizer', '~> 0.0.7')
|
28
29
|
gem.add_runtime_dependency('inflecto', '~> 0.0.2')
|
29
30
|
gem.add_runtime_dependency('anima', '~> 0.1.1')
|
data/spec/spec_helper.rb
CHANGED
@@ -11,7 +11,7 @@ describe Mutant::CLI::Classifier::Method, '#each' do
|
|
11
11
|
let(:unknown_method) { '::TestApp::Literal#unknown' }
|
12
12
|
|
13
13
|
context 'with a block' do
|
14
|
-
subject { object.each {
|
14
|
+
subject { object.each {} }
|
15
15
|
|
16
16
|
context 'with an instance method name' do
|
17
17
|
let(:input) { instance_method }
|
@@ -9,7 +9,7 @@ describe Mutant::CLI::Classifier::Namespace::Flat, '#each' do
|
|
9
9
|
let(:unknown_namespace) { '::TestApp::Object' }
|
10
10
|
|
11
11
|
context 'with a block' do
|
12
|
-
subject { object.each {
|
12
|
+
subject { object.each {} }
|
13
13
|
|
14
14
|
context 'with a known namespace' do
|
15
15
|
let(:input) { known_namespace }
|
@@ -51,7 +51,7 @@ describe Mutant::CLI::Classifier::Namespace::Flat, '#each' do
|
|
51
51
|
let(:input) { unknown_namespace }
|
52
52
|
|
53
53
|
it 'raises an exception when #each is called' do
|
54
|
-
expect { subject.each {
|
54
|
+
expect { subject.each {} }.to raise_error(NameError)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -9,7 +9,7 @@ describe Mutant::CLI::Classifier::Namespace::Recursive, '#each' do
|
|
9
9
|
let(:unknown_namespace) { '::TestApp::Object' }
|
10
10
|
|
11
11
|
context 'with a block' do
|
12
|
-
subject { object.each {
|
12
|
+
subject { object.each {} }
|
13
13
|
|
14
14
|
context 'with a known namespace' do
|
15
15
|
let(:input) { known_namespace }
|
@@ -51,7 +51,7 @@ describe Mutant::CLI::Classifier::Namespace::Recursive, '#each' do
|
|
51
51
|
let(:input) { unknown_namespace }
|
52
52
|
|
53
53
|
it 'raises an exception when #each is called' do
|
54
|
-
expect { subject.each {
|
54
|
+
expect { subject.each {} }.to raise_error(NameError)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Mutant::Differ do
|
6
|
+
let(:object) { described_class }
|
7
|
+
|
8
|
+
describe '.build' do
|
9
|
+
|
10
|
+
subject { object.build(old_string, new_string) }
|
11
|
+
|
12
|
+
let(:old_string) { "foo\nbar" }
|
13
|
+
let(:new_string) { "bar\nbaz" }
|
14
|
+
|
15
|
+
it { should eql(Mutant::Differ.new(%w(foo bar), %w(bar baz))) }
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.colorize_line' do
|
20
|
+
let(:object) { described_class }
|
21
|
+
|
22
|
+
subject { object.colorize_line(line) }
|
23
|
+
|
24
|
+
context 'line beginning with "+"' do
|
25
|
+
let(:line) { '+line' }
|
26
|
+
|
27
|
+
it { should eql(Mutant::Color::GREEN.format(line)) }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'line beginning with "-"' do
|
31
|
+
let(:line) { '-line' }
|
32
|
+
|
33
|
+
it { should eql(Mutant::Color::RED.format(line)) }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'line beginning in other char' do
|
37
|
+
let(:line) { ' line' }
|
38
|
+
|
39
|
+
it { should eql(line) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
File without changes
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Mutant::Loader::Eval, '.
|
5
|
+
describe Mutant::Loader::Eval, '.call' do
|
6
6
|
|
7
|
-
subject { object.
|
7
|
+
subject { object.call(node, mutation_subject) }
|
8
8
|
|
9
9
|
let(:object) { described_class }
|
10
10
|
let(:path) { __FILE__ }
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Mutant::Matcher::Chain do
|
6
|
+
|
7
|
+
let(:object) { described_class.new(matchers) }
|
8
|
+
|
9
|
+
describe '#each' do
|
10
|
+
subject { object.each { |entry| yields << entry } }
|
11
|
+
|
12
|
+
let(:matchers) { [matcher_a, matcher_b] }
|
13
|
+
|
14
|
+
let(:matcher_a) { double('Matcher A') }
|
15
|
+
let(:matcher_b) { double('Matcher B') }
|
16
|
+
|
17
|
+
let(:subject_a) { double('Subject A') }
|
18
|
+
let(:subject_b) { double('Subject B') }
|
19
|
+
|
20
|
+
before do
|
21
|
+
matcher_a.stub(:each).and_yield(subject_a).and_return(matcher_a)
|
22
|
+
matcher_b.stub(:each).and_yield(subject_b).and_return(matcher_b)
|
23
|
+
end
|
24
|
+
|
25
|
+
# it_should_behave_like 'an #each method'
|
26
|
+
context 'with no block' do
|
27
|
+
subject { object.each }
|
28
|
+
|
29
|
+
it { should be_instance_of(to_enum.class) }
|
30
|
+
|
31
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
32
|
+
pending 'FIX RBX rspec? BUG HERE'
|
33
|
+
else
|
34
|
+
it 'yields the expected values' do
|
35
|
+
subject.to_a.should eql(object.to_a)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:yields) { [] }
|
41
|
+
|
42
|
+
it 'should yield subjects' do
|
43
|
+
expect { subject }.to change { yields }.from([]).to([subject_a, subject_b])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#matchers' do
|
48
|
+
subject { object.matchers }
|
49
|
+
|
50
|
+
let(:matchers) { double('Matchers') }
|
51
|
+
|
52
|
+
it { should be(matchers) }
|
53
|
+
|
54
|
+
it_should_behave_like 'an idempotent method'
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Mutant::Matcher::Method::Instance do
|
6
|
+
|
7
|
+
let(:cache) { Fixtures::AST_CACHE }
|
8
|
+
|
9
|
+
describe '#each' do
|
10
|
+
subject { object.each { |subject| yields << subject } }
|
11
|
+
|
12
|
+
let(:object) { described_class.new(cache, scope, method) }
|
13
|
+
let(:method) { scope.instance_method(method_name) }
|
14
|
+
let(:yields) { [] }
|
15
|
+
let(:namespace) { self.class }
|
16
|
+
let(:scope) { self.class::Foo }
|
17
|
+
let(:type) { :def }
|
18
|
+
let(:method_name) { :bar }
|
19
|
+
let(:method_arity) { 0 }
|
20
|
+
|
21
|
+
def name
|
22
|
+
node.children[0]
|
23
|
+
end
|
24
|
+
|
25
|
+
def arguments
|
26
|
+
node.children[1]
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when method is defined once' do
|
30
|
+
let(:base) { __LINE__ }
|
31
|
+
class self::Foo
|
32
|
+
def bar; end
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:method_line) { 2 }
|
36
|
+
|
37
|
+
it_should_behave_like 'a method matcher'
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when method is defined multiple times' do
|
41
|
+
context 'on differend lines' do
|
42
|
+
let(:base) { __LINE__ }
|
43
|
+
class self::Foo
|
44
|
+
def bar
|
45
|
+
end
|
46
|
+
|
47
|
+
def bar(arg)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:method_line) { 5 }
|
52
|
+
let(:method_arity) { 1 }
|
53
|
+
|
54
|
+
it_should_behave_like 'a method matcher'
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'on the same line' do
|
58
|
+
let(:base) { __LINE__ }
|
59
|
+
class self::Foo
|
60
|
+
def bar; end; def bar(arg); end
|
61
|
+
end
|
62
|
+
|
63
|
+
let(:method_line) { 2 }
|
64
|
+
let(:method_arity) { 1 }
|
65
|
+
|
66
|
+
it_should_behave_like 'a method matcher'
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'on the same line with differend scope' do
|
70
|
+
let(:base) { __LINE__ }
|
71
|
+
class self::Foo
|
72
|
+
def self.bar; end; def bar(arg); end
|
73
|
+
end
|
74
|
+
|
75
|
+
let(:method_line) { 2 }
|
76
|
+
let(:method_arity) { 1 }
|
77
|
+
|
78
|
+
it_should_behave_like 'a method matcher'
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when nested' do
|
82
|
+
let(:pattern) { 'Foo::Bar#baz' }
|
83
|
+
|
84
|
+
context 'in class' do
|
85
|
+
let(:base) { __LINE__ }
|
86
|
+
class self::Foo
|
87
|
+
class Bar
|
88
|
+
def baz
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:method_line) { 3 }
|
94
|
+
let(:method_name) { :baz }
|
95
|
+
let(:scope) { self.class::Foo::Bar }
|
96
|
+
|
97
|
+
it_should_behave_like 'a method matcher'
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'in module' do
|
101
|
+
let(:base) { __LINE__ }
|
102
|
+
module self::Foo
|
103
|
+
class Bar
|
104
|
+
def baz
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
let(:method_line) { 3 }
|
110
|
+
let(:method_name) { :baz }
|
111
|
+
let(:scope) { self.class::Foo::Bar }
|
112
|
+
|
113
|
+
it_should_behave_like 'a method matcher'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '.build' do
|
120
|
+
let(:object) { described_class }
|
121
|
+
|
122
|
+
subject { object.build(cache, scope, method) }
|
123
|
+
|
124
|
+
let(:scope) do
|
125
|
+
Class.new do
|
126
|
+
include Adamantium
|
127
|
+
|
128
|
+
def foo
|
129
|
+
end
|
130
|
+
memoize :foo
|
131
|
+
|
132
|
+
def bar
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
let(:method) do
|
138
|
+
scope.instance_method(method_name)
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'with adamantium infected scope' do
|
142
|
+
context 'with unmemoized method' do
|
143
|
+
let(:method_name) { :bar }
|
144
|
+
|
145
|
+
it { should eql(described_class.new(cache, scope, method)) }
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with memoized method' do
|
149
|
+
let(:method_name) { :foo }
|
150
|
+
|
151
|
+
it { should eql(described_class::Memoized.new(cache, scope, method)) }
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Mutant::Mutator::Node::ConditionalLoop do
|
6
|
+
|
7
|
+
context 'with while statement' do
|
8
|
+
let(:source) { 'while true; foo; bar; end' }
|
9
|
+
|
10
|
+
let(:mutations) do
|
11
|
+
mutations = []
|
12
|
+
mutations << 'while true; bar; end'
|
13
|
+
mutations << 'while true; foo; end'
|
14
|
+
mutations << 'while true; end'
|
15
|
+
mutations << 'while false; foo; bar; end'
|
16
|
+
mutations << 'while nil; foo; bar; end'
|
17
|
+
mutations << 'while true; foo; nil; end'
|
18
|
+
mutations << 'while true; nil; bar; end'
|
19
|
+
mutations << 'nil'
|
20
|
+
end
|
21
|
+
|
22
|
+
it_should_behave_like 'a mutator'
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with until statement' do
|
26
|
+
let(:source) { 'until true; foo; bar; end' }
|
27
|
+
|
28
|
+
let(:mutations) do
|
29
|
+
mutations = []
|
30
|
+
mutations << 'until true; bar; end'
|
31
|
+
mutations << 'until true; foo; end'
|
32
|
+
mutations << 'until true; end'
|
33
|
+
mutations << 'until false; foo; bar; end'
|
34
|
+
mutations << 'until nil; foo; bar; end'
|
35
|
+
mutations << 'until true; foo; nil; end'
|
36
|
+
mutations << 'until true; nil; bar; end'
|
37
|
+
mutations << 'nil'
|
38
|
+
end
|
39
|
+
|
40
|
+
it_should_behave_like 'a mutator'
|
41
|
+
end
|
42
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|