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,100 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
# Class to create diffs from source code
|
|
3
|
+
class Differ
|
|
4
|
+
include Adamantium::Flat
|
|
5
|
+
|
|
6
|
+
# Return source diff
|
|
7
|
+
#
|
|
8
|
+
# @return [String]
|
|
9
|
+
#
|
|
10
|
+
# @api private
|
|
11
|
+
#
|
|
12
|
+
def diff
|
|
13
|
+
output = ''
|
|
14
|
+
@diffs.each do |piece|
|
|
15
|
+
hunk = Diff::LCS::Hunk.new(@old, @new, piece, CONTEXT_LINES, length_difference)
|
|
16
|
+
output << hunk.diff(FORMAT)
|
|
17
|
+
output << "\n"
|
|
18
|
+
end
|
|
19
|
+
output
|
|
20
|
+
end
|
|
21
|
+
memoize :diff
|
|
22
|
+
|
|
23
|
+
# Return colorized source diff
|
|
24
|
+
#
|
|
25
|
+
# @return [String]
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
def colorized_diff
|
|
30
|
+
diff.lines.map do |line|
|
|
31
|
+
self.class.colorize_line(line)
|
|
32
|
+
end.join
|
|
33
|
+
end
|
|
34
|
+
memoize :colorized_diff
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
FORMAT = :unified
|
|
39
|
+
CONTEXT_LINES = 3
|
|
40
|
+
|
|
41
|
+
# Initialize differ object
|
|
42
|
+
#
|
|
43
|
+
# @param [String] old
|
|
44
|
+
# @param [String] new
|
|
45
|
+
#
|
|
46
|
+
# @return [undefined]
|
|
47
|
+
#
|
|
48
|
+
# @api private
|
|
49
|
+
#
|
|
50
|
+
def initialize(old, new)
|
|
51
|
+
@old, @new = self.class.lines(old), self.class.lines(new)
|
|
52
|
+
@diffs = Diff::LCS.diff(@old, @new)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Return length difference
|
|
56
|
+
#
|
|
57
|
+
# @return [Fixnum]
|
|
58
|
+
#
|
|
59
|
+
# @api private
|
|
60
|
+
#
|
|
61
|
+
def length_difference
|
|
62
|
+
@new.size - @old.size
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Break up source into lines
|
|
66
|
+
#
|
|
67
|
+
# @param [String] source
|
|
68
|
+
#
|
|
69
|
+
# @return [Array<String>]
|
|
70
|
+
#
|
|
71
|
+
# @api private
|
|
72
|
+
#
|
|
73
|
+
def self.lines(source)
|
|
74
|
+
source.lines.map { |line| line.chomp }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Return colorized diff line
|
|
78
|
+
#
|
|
79
|
+
# @param [String] line
|
|
80
|
+
#
|
|
81
|
+
# @return [String]
|
|
82
|
+
# returns colorized line
|
|
83
|
+
#
|
|
84
|
+
# @api private
|
|
85
|
+
#
|
|
86
|
+
def self.colorize_line(line)
|
|
87
|
+
case line[0].chr
|
|
88
|
+
when '+'
|
|
89
|
+
Color::GREEN
|
|
90
|
+
when '-'
|
|
91
|
+
Color::RED
|
|
92
|
+
when '@'
|
|
93
|
+
line[1].chr == '@' ? Color::BLUE : Color::NONE
|
|
94
|
+
else
|
|
95
|
+
Color::NONE
|
|
96
|
+
end.format(line)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
# Module for support methods
|
|
3
|
+
#
|
|
4
|
+
# They would normally be defined on the root namespace.
|
|
5
|
+
# But it is easier to create the Zombie when there are no
|
|
6
|
+
# References to the root namespace name within the library.
|
|
7
|
+
#
|
|
8
|
+
module Helper
|
|
9
|
+
|
|
10
|
+
# Return deep clone of object
|
|
11
|
+
#
|
|
12
|
+
# @param [Object] object
|
|
13
|
+
#
|
|
14
|
+
# @return [Object] object
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
17
|
+
#
|
|
18
|
+
def self.deep_clone(object)
|
|
19
|
+
Marshal.load(Marshal.dump(object))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Extract option from options hash
|
|
23
|
+
#
|
|
24
|
+
# @param [Hash] options
|
|
25
|
+
# @param [Object] key
|
|
26
|
+
#
|
|
27
|
+
# @return [Object] value
|
|
28
|
+
#
|
|
29
|
+
# @api private
|
|
30
|
+
#
|
|
31
|
+
def self.extract_option(options, key)
|
|
32
|
+
options.fetch(key) do
|
|
33
|
+
raise ArgumentError,"Missing #{key.inspect} in options"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
# Abstract base class for mutant killers
|
|
3
|
+
class Killer
|
|
4
|
+
include Adamantium::Flat, AbstractType
|
|
5
|
+
|
|
6
|
+
# Test for kill failure
|
|
7
|
+
#
|
|
8
|
+
# @return [true]
|
|
9
|
+
# returns true when mutant was killed
|
|
10
|
+
#
|
|
11
|
+
# @return [false]
|
|
12
|
+
# returns false otherwise
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
#
|
|
16
|
+
def fail?
|
|
17
|
+
!@killed
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Return runtime of killer
|
|
21
|
+
#
|
|
22
|
+
# @return [Float]
|
|
23
|
+
#
|
|
24
|
+
# @api private
|
|
25
|
+
#
|
|
26
|
+
attr_reader :runtime
|
|
27
|
+
|
|
28
|
+
# Return original source
|
|
29
|
+
#
|
|
30
|
+
# @return [String]
|
|
31
|
+
#
|
|
32
|
+
# @api private
|
|
33
|
+
#
|
|
34
|
+
def original_source
|
|
35
|
+
mutation.original_source
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Return mutated source
|
|
39
|
+
#
|
|
40
|
+
# @return [String]
|
|
41
|
+
#
|
|
42
|
+
# @api private
|
|
43
|
+
#
|
|
44
|
+
def mutation_source
|
|
45
|
+
mutation.source
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Return strategy
|
|
49
|
+
#
|
|
50
|
+
# @return [Strategy]
|
|
51
|
+
#
|
|
52
|
+
# @api private
|
|
53
|
+
#
|
|
54
|
+
attr_reader :strategy
|
|
55
|
+
|
|
56
|
+
# Return name of killer
|
|
57
|
+
#
|
|
58
|
+
# @return [String]
|
|
59
|
+
#
|
|
60
|
+
# @api private
|
|
61
|
+
#
|
|
62
|
+
def self.type
|
|
63
|
+
self::TYPE
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Return identification
|
|
67
|
+
#
|
|
68
|
+
# @return [String]
|
|
69
|
+
#
|
|
70
|
+
# @api private
|
|
71
|
+
#
|
|
72
|
+
def identification
|
|
73
|
+
"#{type}:#{mutation.identification}".freeze
|
|
74
|
+
end
|
|
75
|
+
memoize :identification
|
|
76
|
+
|
|
77
|
+
# Return mae of killer
|
|
78
|
+
#
|
|
79
|
+
# @return [String]
|
|
80
|
+
#
|
|
81
|
+
# @api private
|
|
82
|
+
#
|
|
83
|
+
def type
|
|
84
|
+
self.class.type
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Return mutation to kill
|
|
88
|
+
#
|
|
89
|
+
# @return [Mutation]
|
|
90
|
+
#
|
|
91
|
+
# @api private
|
|
92
|
+
#
|
|
93
|
+
attr_reader :mutation
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
# Initialize killer object
|
|
98
|
+
#
|
|
99
|
+
# @param [Mutation] mutation
|
|
100
|
+
#
|
|
101
|
+
# @return [undefined]
|
|
102
|
+
#
|
|
103
|
+
# @api private
|
|
104
|
+
#
|
|
105
|
+
def initialize(strategy, mutation)
|
|
106
|
+
@strategy, @mutation = strategy, mutation
|
|
107
|
+
|
|
108
|
+
run_with_benchmark
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Run with taking the time
|
|
112
|
+
#
|
|
113
|
+
# @return [undefined]
|
|
114
|
+
#
|
|
115
|
+
# @api private
|
|
116
|
+
#
|
|
117
|
+
def run_with_benchmark
|
|
118
|
+
start_time = Time.now
|
|
119
|
+
@killed = run
|
|
120
|
+
end_time = Time.now
|
|
121
|
+
@runtime = end_time - start_time
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Run test
|
|
125
|
+
#
|
|
126
|
+
# @return [true]
|
|
127
|
+
# returns true when mutant was killed
|
|
128
|
+
#
|
|
129
|
+
# @return [false]
|
|
130
|
+
# returns false otherwise
|
|
131
|
+
#
|
|
132
|
+
# @api private
|
|
133
|
+
#
|
|
134
|
+
abstract_method :run
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Killer
|
|
3
|
+
|
|
4
|
+
class Forked < self
|
|
5
|
+
def initialize(killer, strategy, mutation)
|
|
6
|
+
@killer = killer
|
|
7
|
+
super(strategy, mutation)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def type
|
|
11
|
+
@killer.type
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run
|
|
15
|
+
fork do
|
|
16
|
+
killer = @killer.new(strategy, mutation)
|
|
17
|
+
Kernel.exit(killer.fail? ? 1 : 0)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
status = Process.wait2.last
|
|
21
|
+
status.exitstatus.zero?
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class Forking < self
|
|
26
|
+
include Equalizer.new(:killer)
|
|
27
|
+
|
|
28
|
+
attr_reader :killer
|
|
29
|
+
|
|
30
|
+
def initialize(killer)
|
|
31
|
+
@killer = killer
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def new(strategy, mutation)
|
|
35
|
+
Forked.new(killer, strategy, mutation)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Killer
|
|
3
|
+
# Runner for rspec tests
|
|
4
|
+
class Rspec < self
|
|
5
|
+
TYPE = 'rspec'.freeze
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# Initialize rspec runner
|
|
10
|
+
#
|
|
11
|
+
# @return [undefined]
|
|
12
|
+
#
|
|
13
|
+
# @api private
|
|
14
|
+
#
|
|
15
|
+
def initialize(*)
|
|
16
|
+
@error_stream, @output_stream = StringIO.new, StringIO.new
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Run rspec test
|
|
21
|
+
#
|
|
22
|
+
# @return [true]
|
|
23
|
+
# returns true when test is NOT successful and the mutant was killed
|
|
24
|
+
#
|
|
25
|
+
# @return [false]
|
|
26
|
+
# returns false otherwise
|
|
27
|
+
#
|
|
28
|
+
# @api private
|
|
29
|
+
#
|
|
30
|
+
def run
|
|
31
|
+
mutation.insert
|
|
32
|
+
!::RSpec::Core::Runner.run(command_line_arguments, @error_stream, @output_stream).zero?
|
|
33
|
+
end
|
|
34
|
+
memoize :run
|
|
35
|
+
|
|
36
|
+
# Return command line arguments
|
|
37
|
+
#
|
|
38
|
+
# @return [Array]
|
|
39
|
+
#
|
|
40
|
+
# @api private
|
|
41
|
+
#
|
|
42
|
+
def command_line_arguments
|
|
43
|
+
%W(
|
|
44
|
+
--fail-fast
|
|
45
|
+
) + strategy.spec_files(mutation)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Killer
|
|
3
|
+
class Static < self
|
|
4
|
+
def run
|
|
5
|
+
self.class::RESULT
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class Success < self
|
|
9
|
+
TYPE = 'success'.freeze
|
|
10
|
+
RESULT = true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class Fail < self
|
|
14
|
+
TYPE = 'fail'.freeze
|
|
15
|
+
RESULT = false
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
# Base class for code loaders
|
|
3
|
+
class Loader
|
|
4
|
+
include AbstractType
|
|
5
|
+
extend MethodObject
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# Run the loader
|
|
10
|
+
#
|
|
11
|
+
# @return [undefined]
|
|
12
|
+
#
|
|
13
|
+
# @api private
|
|
14
|
+
#
|
|
15
|
+
abstract_method :run
|
|
16
|
+
|
|
17
|
+
# Initialize and insert mutation into vm
|
|
18
|
+
#
|
|
19
|
+
# @param [Rubinius::AST::Script] root
|
|
20
|
+
#
|
|
21
|
+
# @return [undefined]
|
|
22
|
+
#
|
|
23
|
+
# @api private
|
|
24
|
+
#
|
|
25
|
+
def initialize(root)
|
|
26
|
+
@root = Helper.deep_clone(root)
|
|
27
|
+
run
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Eval based loader
|
|
31
|
+
class Eval < self
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# Run loader
|
|
35
|
+
#
|
|
36
|
+
# @return [undefined]
|
|
37
|
+
#
|
|
38
|
+
# @api private
|
|
39
|
+
#
|
|
40
|
+
def run
|
|
41
|
+
eval(source, TOPLEVEL_BINDING)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Return source
|
|
45
|
+
#
|
|
46
|
+
# @return [String]
|
|
47
|
+
#
|
|
48
|
+
# @api private
|
|
49
|
+
#
|
|
50
|
+
def source
|
|
51
|
+
ToSource.to_source(@root)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Rubinius script node based loaded
|
|
56
|
+
class Rubinius < self
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
# Run loader
|
|
60
|
+
#
|
|
61
|
+
# @return [undefined]
|
|
62
|
+
#
|
|
63
|
+
# @api private
|
|
64
|
+
#
|
|
65
|
+
def run(root)
|
|
66
|
+
Rubinius.run_script(compiled_code)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Return compiled code
|
|
70
|
+
#
|
|
71
|
+
# @return [Rubinius::CompiledCode]
|
|
72
|
+
#
|
|
73
|
+
# @api private
|
|
74
|
+
#
|
|
75
|
+
# FIXME: rbx on travis is older than on my devbox.
|
|
76
|
+
#
|
|
77
|
+
def compiled_code
|
|
78
|
+
_script = script
|
|
79
|
+
_script.respond_to?(:compiled_code) ? _script.compiled_code : _script.compiled_method
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Return code script
|
|
83
|
+
#
|
|
84
|
+
# @return [Rubinius::CompiledCode::Script]
|
|
85
|
+
#
|
|
86
|
+
# @api private
|
|
87
|
+
#
|
|
88
|
+
def script
|
|
89
|
+
compiled_code_raw.create_script
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Return compiled code for node
|
|
93
|
+
#
|
|
94
|
+
# @return [Rubinius::CompiledCode]
|
|
95
|
+
#
|
|
96
|
+
# @api private
|
|
97
|
+
#
|
|
98
|
+
def compiled_code_raw
|
|
99
|
+
compiler.run
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Return compiler loaded with mutated ast
|
|
103
|
+
#
|
|
104
|
+
# @return [Rubinius::Compiler]
|
|
105
|
+
#
|
|
106
|
+
# @api private
|
|
107
|
+
#
|
|
108
|
+
def compiler
|
|
109
|
+
Rubinius::Compiler.new(:bytecode, :compiled_method).tap do |compiler|
|
|
110
|
+
compiler.generator.input(@root)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Return script node
|
|
115
|
+
#
|
|
116
|
+
# @param [Rubinius::AST::Node] node
|
|
117
|
+
#
|
|
118
|
+
# @return [Rubinius::AST::Script]
|
|
119
|
+
#
|
|
120
|
+
# @api private
|
|
121
|
+
#
|
|
122
|
+
def script(node)
|
|
123
|
+
Rubinius::AST::Script.new(node).tap do |script|
|
|
124
|
+
script.file = source_path
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|