mutant 0.1.1 → 0.2.0
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.
- data/.gitignore +5 -11
- data/.rspec +0 -1
- data/.travis.yml +14 -3
- data/Changelog.md +3 -0
- data/Gemfile +5 -1
- data/Gemfile.devtools +49 -0
- data/Guardfile +18 -0
- data/README.md +67 -0
- data/Rakefile +4 -1
- data/TODO +13 -0
- data/bin/mutant +14 -0
- data/bin/zombie +14 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/roodi.yml +26 -0
- data/config/site.reek +93 -0
- data/config/yardstick.yml +2 -0
- data/lib/inflector.rb +7 -0
- data/lib/inflector/defaults.rb +62 -0
- data/lib/inflector/inflections.rb +209 -0
- data/lib/inflector/methods.rb +149 -0
- data/lib/inflector/version.rb +3 -0
- data/lib/mutant.rb +96 -21
- data/lib/mutant/cli.rb +309 -0
- data/lib/mutant/color.rb +61 -0
- data/lib/mutant/context.rb +36 -0
- data/lib/mutant/context/scope.rb +138 -0
- data/lib/mutant/differ.rb +100 -0
- data/lib/mutant/helper.rb +38 -0
- data/lib/mutant/killer.rb +136 -0
- data/lib/mutant/killer/forking.rb +41 -0
- data/lib/mutant/killer/rspec.rb +49 -0
- data/lib/mutant/killer/static.rb +19 -0
- data/lib/mutant/loader.rb +129 -0
- data/lib/mutant/matcher.rb +55 -0
- data/lib/mutant/matcher/chain.rb +66 -0
- data/lib/mutant/matcher/method.rb +173 -0
- data/lib/mutant/matcher/method/classifier.rb +126 -0
- data/lib/mutant/matcher/method/instance.rb +67 -0
- data/lib/mutant/matcher/method/singleton.rb +141 -0
- data/lib/mutant/matcher/object_space.rb +114 -0
- data/lib/mutant/matcher/scope_methods.rb +127 -0
- data/lib/mutant/mutation.rb +101 -12
- data/lib/mutant/mutation/filter.rb +75 -0
- data/lib/mutant/mutation/filter/code.rb +68 -0
- data/lib/mutant/mutation/filter/regexp.rb +39 -0
- data/lib/mutant/mutation/filter/whitelist.rb +47 -0
- data/lib/mutant/mutator.rb +134 -30
- data/lib/mutant/mutator/node.rb +163 -0
- data/lib/mutant/mutator/node/arguments.rb +24 -0
- data/lib/mutant/mutator/node/block.rb +24 -0
- data/lib/mutant/mutator/node/define.rb +24 -0
- data/lib/mutant/mutator/node/if_statement.rb +93 -0
- data/lib/mutant/mutator/node/literal.rb +54 -0
- data/lib/mutant/mutator/node/literal/array.rb +28 -0
- data/lib/mutant/mutator/node/literal/boolean.rb +49 -0
- data/lib/mutant/mutator/node/literal/dynamic.rb +24 -0
- data/lib/mutant/mutator/node/literal/empty_array.rb +26 -0
- data/lib/mutant/mutator/node/literal/fixnum.rb +37 -0
- data/lib/mutant/mutator/node/literal/float.rb +48 -0
- data/lib/mutant/mutator/node/literal/hash.rb +89 -0
- data/lib/mutant/mutator/node/literal/nil.rb +25 -0
- data/lib/mutant/mutator/node/literal/range.rb +94 -0
- data/lib/mutant/mutator/node/literal/regex.rb +43 -0
- data/lib/mutant/mutator/node/literal/string.rb +26 -0
- data/lib/mutant/mutator/node/literal/symbol.rb +26 -0
- data/lib/mutant/mutator/node/noop.rb +55 -0
- data/lib/mutant/mutator/node/receiver_case.rb +140 -0
- data/lib/mutant/mutator/node/return.rb +31 -0
- data/lib/mutant/mutator/node/send.rb +112 -0
- data/lib/mutant/mutator/registry.rb +48 -0
- data/lib/mutant/mutator/util.rb +87 -0
- data/lib/mutant/random.rb +24 -27
- data/lib/mutant/reporter.rb +48 -30
- data/lib/mutant/reporter/cli.rb +221 -0
- data/lib/mutant/reporter/null.rb +42 -0
- data/lib/mutant/reporter/stats.rb +64 -0
- data/lib/mutant/runner.rb +112 -0
- data/lib/mutant/strategy.rb +42 -0
- data/lib/mutant/strategy/rspec.rb +59 -0
- data/lib/mutant/strategy/rspec/example_lookup.rb +122 -0
- data/lib/mutant/subject.rb +115 -0
- data/lib/mutant/support/method_object.rb +31 -0
- data/locator.rb +87 -0
- data/mutant.gemspec +21 -21
- data/spec/integration/mutant/differ_spec.rb +15 -0
- data/spec/integration/mutant/loader_spec.rb +21 -0
- data/spec/integration/mutant/method_matching_spec.rb +269 -0
- data/spec/integration/mutant/rspec_killer_spec.rb +24 -0
- data/spec/integration/mutant/runner_spec.rb +26 -0
- data/spec/integration/mutant/zombie_spec.rb +8 -0
- data/spec/rcov.opts +7 -0
- data/spec/shared/command_method_behavior.rb +7 -0
- data/spec/shared/each_method_behaviour.rb +15 -0
- data/spec/shared/hash_method_behavior.rb +17 -0
- data/spec/shared/idempotent_method_behavior.rb +7 -0
- data/spec/shared/invertible_method_behaviour.rb +9 -0
- data/spec/shared/method_filter_parse_behavior.rb +16 -0
- data/spec/shared/method_match_behavior.rb +39 -0
- data/spec/shared/mutator_behavior.rb +46 -0
- data/spec/spec_helper.rb +11 -14
- data/spec/support/compress_helper.rb +10 -0
- data/spec/support/rspec.rb +22 -0
- data/spec/support/test_app.rb +5 -0
- data/spec/support/zombie.rb +141 -0
- data/spec/unit/mutant/cli/class_methods/new_spec.rb +87 -0
- data/spec/unit/mutant/cli/class_methods/run_spec.rb +38 -0
- data/spec/unit/mutant/context/root_spec.rb +11 -0
- data/spec/unit/mutant/context/scope/class_methods/build_spec.rb +29 -0
- data/spec/unit/mutant/context/scope/root_spec.rb +22 -0
- data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +27 -0
- data/spec/unit/mutant/killer/fail_ques_spec.rb +39 -0
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +32 -0
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +33 -0
- data/spec/unit/mutant/loader/rubinius/class_methods/run_spec.rb +42 -0
- data/spec/unit/mutant/matcher/chain/each_spec.rb +37 -0
- data/spec/unit/mutant/matcher/chain/matchers_spec.rb +12 -0
- data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +49 -0
- data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +12 -0
- data/spec/unit/mutant/matcher/each_spec.rb +14 -0
- data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +21 -0
- data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +34 -0
- data/spec/unit/mutant/matcher/method/method_spec.rb +11 -0
- data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +24 -0
- data/spec/unit/mutant/matcher/object_space/each_spec.rb +31 -0
- data/spec/unit/mutant/mutator/each_spec.rb +25 -0
- data/spec/unit/mutant/mutator/emit_new_spec.rb +51 -0
- data/spec/unit/mutant/mutator/emit_spec.rb +52 -0
- data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +36 -0
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +47 -0
- data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +30 -0
- data/spec/unit/mutant/mutator/node/literal/array_spec.rb +30 -0
- data/spec/unit/mutant/mutator/node/literal/boolean/mutation_spec.rb +23 -0
- data/spec/unit/mutant/mutator/node/literal/empty_array_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/float_spec.rb +25 -0
- data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +34 -0
- data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +13 -0
- data/spec/unit/mutant/mutator/node/literal/range_spec.rb +35 -0
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +23 -0
- data/spec/unit/mutant/mutator/node/literal/string_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +27 -0
- data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +21 -0
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +78 -0
- data/spec/unit/mutant/mutator/self_spec.rb +7 -0
- data/spec/unit/mutant/subject/class_methods/new_spec.rb +13 -0
- data/spec/unit/mutant/subject/context_spec.rb +14 -0
- data/spec/unit/mutant/subject/each_spec.rb +35 -0
- data/spec/unit/mutant/subject/node_spec.rb +13 -0
- data/tasks/metrics/ci.rake +7 -0
- data/tasks/metrics/flay.rake +41 -0
- data/tasks/metrics/flog.rake +43 -0
- data/tasks/metrics/heckle.rake +216 -0
- data/tasks/metrics/metric_fu.rake +31 -0
- data/tasks/metrics/reek.rake +15 -0
- data/tasks/metrics/roodi.rake +15 -0
- data/tasks/metrics/yardstick.rake +23 -0
- data/tasks/spec.rake +45 -0
- data/tasks/yard.rake +9 -0
- data/test_app/.rspec +1 -0
- data/test_app/lib/test_app.rb +5 -0
- data/test_app/lib/test_app/literal.rb +32 -0
- data/test_app/spec/shared/command_method_behavior.rb +7 -0
- data/test_app/spec/shared/each_method_behaviour.rb +15 -0
- data/test_app/spec/shared/hash_method_behavior.rb +17 -0
- data/test_app/spec/shared/idempotent_method_behavior.rb +7 -0
- data/test_app/spec/shared/invertible_method_behaviour.rb +9 -0
- data/test_app/spec/shared/method_filter_parse_behavior.rb +16 -0
- data/test_app/spec/shared/method_match_behavior.rb +39 -0
- data/test_app/spec/shared/mutator_behavior.rb +44 -0
- data/test_app/spec/spec_helper.rb +7 -0
- data/test_app/spec/unit/test_app/literal/command_spec.rb +9 -0
- data/test_app/spec/unit/test_app/literal/string_spec.rb +9 -0
- metadata +346 -124
- data/.rvmrc +0 -1
- data/Readme.md +0 -13
- data/exe/mutate +0 -6
- data/lib/mutant/extensions.rb +0 -8
- data/lib/mutant/formatter.rb +0 -19
- data/lib/mutant/implementation.rb +0 -70
- data/lib/mutant/literal.rb +0 -147
- data/lib/mutant/method.rb +0 -31
- data/lib/mutant/mutatee.rb +0 -61
- data/lib/mutant/node.rb +0 -26
- data/lib/mutant/runners/rspec.rb +0 -34
- data/lib/mutant/version.rb +0 -3
- data/spec/functional/class_spec.rb +0 -46
- data/spec/functional/instance_method/array_spec.rb +0 -53
- data/spec/functional/instance_method/boolean_spec.rb +0 -101
- data/spec/functional/instance_method/call_spec.rb +0 -161
- data/spec/functional/instance_method/fixnum_spec.rb +0 -53
- data/spec/functional/instance_method/float_spec.rb +0 -53
- data/spec/functional/instance_method/hash_spec.rb +0 -53
- data/spec/functional/instance_method/if_spec.rb +0 -57
- data/spec/functional/instance_method/ivar_assign_spec.rb +0 -62
- data/spec/functional/instance_method/range_spec.rb +0 -53
- data/spec/functional/instance_method/regex_spec.rb +0 -55
- data/spec/functional/instance_method/string_spec.rb +0 -53
- data/spec/functional/instance_method/symbol_spec.rb +0 -53
- data/spec/functional/reporter/method_loaded_spec.rb +0 -62
- data/spec/functional/reporter/running_mutations_spec.rb +0 -60
- data/spec/functional/runners/rspec_spec.rb +0 -26
- data/spec/functional/singleton_method/array_spec.rb +0 -53
- data/spec/functional/singleton_method/boolean_spec.rb +0 -101
- data/spec/functional/singleton_method/call_spec.rb +0 -161
- data/spec/functional/singleton_method/fixnum_spec.rb +0 -53
- data/spec/functional/singleton_method/float_spec.rb +0 -53
- data/spec/functional/singleton_method/hash_spec.rb +0 -53
- data/spec/functional/singleton_method/if_spec.rb +0 -57
- data/spec/functional/singleton_method/ivar_assign_spec.rb +0 -60
- data/spec/functional/singleton_method/range_spec.rb +0 -53
- data/spec/functional/singleton_method/regex_spec.rb +0 -55
- data/spec/functional/singleton_method/string_spec.rb +0 -53
- data/spec/functional/singleton_method/symbol_spec.rb +0 -53
- data/spec/mutant/extensions_spec.rb +0 -13
- data/spec/mutant/implementation_spec.rb +0 -223
- data/spec/mutant/literal_spec.rb +0 -129
- data/spec/mutant/mutatee_spec.rb +0 -28
- data/spec/mutant/node_spec.rb +0 -41
- data/spec/mutant/random_spec.rb +0 -33
- data/spec/mutant/reporter_spec.rb +0 -17
- data/spec/mutant_spec.rb +0 -28
- data/spec/support/example_group_helpers.rb +0 -11
- data/spec/support/example_helpers.rb +0 -5
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mutant,'rspec integration' do
|
|
4
|
+
|
|
5
|
+
around do |example|
|
|
6
|
+
Dir.chdir(TestApp.root) do
|
|
7
|
+
example.run
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:strategy) { Mutant::Strategy::Rspec::DM2 }
|
|
12
|
+
|
|
13
|
+
specify 'allows to kill mutations' do
|
|
14
|
+
Kernel.system("bundle exec mutant -I lib -r test_app --rspec-dm2 ::TestApp::Literal#string").should be(true)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
specify 'fails to kill mutations when they are not covered' do
|
|
18
|
+
Kernel.system("bundle exec mutant -I lib -r test_app --rspec-dm2 ::TestApp::Literal#uncovered_string").should be(false)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
specify 'fails when some mutations when are not covered' do
|
|
22
|
+
Kernel.system("bundle exec mutant -I lib -r test_app --rspec-dm2 ::TestApp::Literal").should be(false)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Mutant, 'runner' do
|
|
4
|
+
before do
|
|
5
|
+
pending
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
around do |example|
|
|
9
|
+
Dir.chdir(TestApp.root) do
|
|
10
|
+
example.run
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'allows to run mutant over a project' do
|
|
15
|
+
output = StringIO.new
|
|
16
|
+
runner = Mutant::Runner.run(
|
|
17
|
+
:killer => Mutant::Killer::Rspec,
|
|
18
|
+
:matcher => Mutant::Matcher::ObjectSpace.new(/\ATestApp::/),
|
|
19
|
+
:reporter => Mutant::Reporter::CLI.new(output)
|
|
20
|
+
)
|
|
21
|
+
runner.fail?.should be(true)
|
|
22
|
+
runner.errors.size.should be(22)
|
|
23
|
+
output.rewind
|
|
24
|
+
output.lines.grep(/Mutant alive:/).size.should be(22)
|
|
25
|
+
end
|
|
26
|
+
end
|
data/spec/rcov.opts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
shared_examples_for 'an #each method' do
|
|
4
|
+
it_should_behave_like 'a command method'
|
|
5
|
+
|
|
6
|
+
context 'with no block' do
|
|
7
|
+
subject { object.each }
|
|
8
|
+
|
|
9
|
+
it { should be_instance_of(to_enum.class) }
|
|
10
|
+
|
|
11
|
+
it 'yields the expected values' do
|
|
12
|
+
subject.to_a.should eql(object.to_a)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
shared_examples_for 'a hash method' do
|
|
4
|
+
it_should_behave_like 'an idempotent method'
|
|
5
|
+
|
|
6
|
+
specification = proc do
|
|
7
|
+
should be_instance_of(Fixnum)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'is a fixnum' do
|
|
11
|
+
instance_eval(&specification)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'memoizes the hash code' do
|
|
15
|
+
subject.should eql(object.memoized(:hash))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
shared_examples_for 'a method filter parse result' do
|
|
2
|
+
before do
|
|
3
|
+
expected_class.stub(:new => response)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
let(:response) { mock('Response') }
|
|
7
|
+
|
|
8
|
+
it { should be(response) }
|
|
9
|
+
|
|
10
|
+
it 'should initialize method filter with correct arguments' do
|
|
11
|
+
expected_class.should_receive(:new).with(TestApp::Literal, :string).and_return(response)
|
|
12
|
+
subject
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
shared_examples_for 'a method match' do
|
|
2
|
+
subject { Mutant::Matcher::Method.parse(pattern).to_a }
|
|
3
|
+
|
|
4
|
+
let(:values) { defaults.merge(expectation) }
|
|
5
|
+
|
|
6
|
+
let(:method_name) { values.fetch(:method_name) }
|
|
7
|
+
let(:method_line) { values.fetch(:method_line) }
|
|
8
|
+
let(:method_arity) { values.fetch(:method_arity) }
|
|
9
|
+
let(:scope) { values.fetch(:scope) }
|
|
10
|
+
let(:node_class) { values.fetch(:node_class) }
|
|
11
|
+
|
|
12
|
+
let(:node) { mutation_subject.node }
|
|
13
|
+
let(:context) { mutation_subject.context }
|
|
14
|
+
let(:mutation_subject) { subject.first }
|
|
15
|
+
|
|
16
|
+
it 'should return one subject' do
|
|
17
|
+
subject.size.should be(1)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should have correct method name' do
|
|
21
|
+
name(node).should eql(method_name)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'should have correct line number' do
|
|
25
|
+
node.line.should eql(method_line)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should have correct arity' do
|
|
29
|
+
arguments(node).required.length.should eql(method_arity)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'should have correct scope in context' do
|
|
33
|
+
context.send(:scope).should eql(scope)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'should have the correct node class' do
|
|
37
|
+
node.should be_a(node_class)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
shared_examples_for 'a mutator' do
|
|
2
|
+
subject { object.each(node) { |item| yields << item } }
|
|
3
|
+
|
|
4
|
+
let(:yields) { [] }
|
|
5
|
+
let(:object) { described_class }
|
|
6
|
+
|
|
7
|
+
unless instance_methods.map(&:to_s).include?('node')
|
|
8
|
+
let(:node) { source.to_ast }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it_should_behave_like 'a command method'
|
|
12
|
+
|
|
13
|
+
context 'with no block' do
|
|
14
|
+
subject { object.each(node) }
|
|
15
|
+
|
|
16
|
+
it { should be_instance_of(to_enum.class) }
|
|
17
|
+
|
|
18
|
+
let(:expected_mutations) do
|
|
19
|
+
mutations.map do |mutation|
|
|
20
|
+
if mutation.respond_to?(:to_ast)
|
|
21
|
+
mutation.to_ast.to_sexp
|
|
22
|
+
else
|
|
23
|
+
mutation
|
|
24
|
+
end
|
|
25
|
+
end.to_set
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'generates the expected mutations' do
|
|
29
|
+
generated = self.subject.map(&:to_sexp).to_set
|
|
30
|
+
|
|
31
|
+
missing = (expected_mutations - generated).to_a
|
|
32
|
+
unexpected = (generated - expected_mutations).to_a
|
|
33
|
+
|
|
34
|
+
unless generated == expected_mutations
|
|
35
|
+
message = "Missing mutations: %s\nUnexpected mutations: %s" % [missing, unexpected].map(&:inspect)
|
|
36
|
+
fail message
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
shared_examples_for 'a noop mutator' do
|
|
43
|
+
let(:mutations) { [] }
|
|
44
|
+
|
|
45
|
+
it_should_behave_like 'a mutator'
|
|
46
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
require 'aruba/api'
|
|
1
|
+
# encoding: utf-8
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
require 'rspec'
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
config.extend ExampleGroupHelpers
|
|
11
|
-
config.include ExampleHelpers
|
|
5
|
+
# require spec support files and shared behavior
|
|
6
|
+
Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each { |f| require(f) }
|
|
7
|
+
|
|
8
|
+
$: << File.join(TestApp.root,'lib')
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
require 'test_app'
|
|
11
|
+
require 'mutant'
|
|
12
|
+
|
|
13
|
+
RSpec.configure do |config|
|
|
14
|
+
config.include(CompressHelper)
|
|
18
15
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Patch rspec to allow nested execution
|
|
2
|
+
module Rspec
|
|
3
|
+
# Run block in clean rspec environment
|
|
4
|
+
#
|
|
5
|
+
# @return [Object]
|
|
6
|
+
# returns the value of block
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
#
|
|
10
|
+
def self.nest
|
|
11
|
+
original_world, original_configuration =
|
|
12
|
+
::RSpec.instance_variable_get(:@world),
|
|
13
|
+
::RSpec.instance_variable_get(:@configuration)
|
|
14
|
+
|
|
15
|
+
::RSpec.reset
|
|
16
|
+
|
|
17
|
+
yield
|
|
18
|
+
ensure
|
|
19
|
+
::RSpec.instance_variable_set(:@world, original_world)
|
|
20
|
+
::RSpec.instance_variable_set(:@configuration, original_configuration)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
module Zombie
|
|
2
|
+
# Setup zombie
|
|
3
|
+
#
|
|
4
|
+
# @return [self]
|
|
5
|
+
#
|
|
6
|
+
# @api private
|
|
7
|
+
#
|
|
8
|
+
def self.setup
|
|
9
|
+
files.each do |path|
|
|
10
|
+
path = "#{File.expand_path(path, root)}.rb"
|
|
11
|
+
ast = File.read(path).to_ast
|
|
12
|
+
zombify(ast, path)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
self
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Return library root directory
|
|
19
|
+
#
|
|
20
|
+
# @return [String]
|
|
21
|
+
#
|
|
22
|
+
# @api private
|
|
23
|
+
#
|
|
24
|
+
def self.root
|
|
25
|
+
File.expand_path('../../../lib',__FILE__)
|
|
26
|
+
end
|
|
27
|
+
private_class_method :root
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Replace Mutant with Zombie namespace
|
|
31
|
+
#
|
|
32
|
+
# @param [Rubinius::AST::Node]
|
|
33
|
+
#
|
|
34
|
+
# @api private
|
|
35
|
+
#
|
|
36
|
+
# @return [undefined]
|
|
37
|
+
#
|
|
38
|
+
def self.zombify(root, path)
|
|
39
|
+
node = find_mutant(root)
|
|
40
|
+
unless node
|
|
41
|
+
raise "unable to find mutant in AST from: #{path.inspect}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
name = node.name
|
|
45
|
+
|
|
46
|
+
node.name = Rubinius::AST::ModuleName.new(name.line, :Zombie)
|
|
47
|
+
|
|
48
|
+
scope = node.body
|
|
49
|
+
|
|
50
|
+
unless scope.kind_of?(Rubinius::AST::EmptyBody)
|
|
51
|
+
node.body = Rubinius::AST::ModuleScope.new(scope.line, node.name, scope.body)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
::Mutant::Loader::Eval.run(root)
|
|
55
|
+
end
|
|
56
|
+
private_class_method :zombify
|
|
57
|
+
|
|
58
|
+
# Find mutant module in AST
|
|
59
|
+
#
|
|
60
|
+
# @param [Rubinius::AST::Node]
|
|
61
|
+
#
|
|
62
|
+
# @return [Rubinius::AST::Node]
|
|
63
|
+
#
|
|
64
|
+
def self.find_mutant(root)
|
|
65
|
+
if is_mutant?(root)
|
|
66
|
+
return root
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
unless root.kind_of?(Rubinius::AST::Block)
|
|
70
|
+
raise "Cannot find mutant in: #{root.class}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
root.array.each do |node|
|
|
74
|
+
return node if is_mutant?(node)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
nil
|
|
78
|
+
end
|
|
79
|
+
private_class_method :find_mutant
|
|
80
|
+
|
|
81
|
+
# Test if node is mutant module
|
|
82
|
+
#
|
|
83
|
+
# @param [Rubinius::AST::Node]
|
|
84
|
+
#
|
|
85
|
+
# @return [true]
|
|
86
|
+
# returns true if node is the mutant module
|
|
87
|
+
#
|
|
88
|
+
# @return [false]
|
|
89
|
+
# returns false otherwise
|
|
90
|
+
#
|
|
91
|
+
# @api private
|
|
92
|
+
#
|
|
93
|
+
def self.is_mutant?(node)
|
|
94
|
+
node.kind_of?(Rubinius::AST::Module) && is_mutant_name?(node.name)
|
|
95
|
+
end
|
|
96
|
+
private_class_method :is_mutant?
|
|
97
|
+
|
|
98
|
+
# Test if node is mutant module name
|
|
99
|
+
#
|
|
100
|
+
# @param [Rubinius::AST::ModuleName]
|
|
101
|
+
#
|
|
102
|
+
# @return [true]
|
|
103
|
+
# returns true if node is the mutant module name
|
|
104
|
+
#
|
|
105
|
+
# @return [false]
|
|
106
|
+
# returns false otherwise
|
|
107
|
+
#
|
|
108
|
+
# @api private
|
|
109
|
+
#
|
|
110
|
+
def self.is_mutant_name?(node)
|
|
111
|
+
node.name == :Mutant
|
|
112
|
+
end
|
|
113
|
+
private_class_method :is_mutant_name?
|
|
114
|
+
|
|
115
|
+
# Return all library files the mutant is made of.
|
|
116
|
+
#
|
|
117
|
+
# @return [Array<String>]
|
|
118
|
+
#
|
|
119
|
+
# @api private
|
|
120
|
+
#
|
|
121
|
+
# FIXME:
|
|
122
|
+
# Yeah looks very ugly but im currently to exited to do a cleanup.
|
|
123
|
+
#
|
|
124
|
+
def self.files
|
|
125
|
+
block = File.read("lib/mutant.rb").to_ast
|
|
126
|
+
files = block.array.select do |node|
|
|
127
|
+
node.class == Rubinius::AST::SendWithArguments &&
|
|
128
|
+
node.receiver.class == Rubinius::AST::Self &&
|
|
129
|
+
node.name == :require
|
|
130
|
+
end.map do |node|
|
|
131
|
+
arguments = node.arguments.array
|
|
132
|
+
raise unless arguments.one?
|
|
133
|
+
argument = arguments.first
|
|
134
|
+
raise unless argument.class == Rubinius::AST::StringLiteral
|
|
135
|
+
argument.string
|
|
136
|
+
end.select do |file|
|
|
137
|
+
file =~ /\Amutant/
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
private_class_method :files
|
|
141
|
+
end
|