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,141 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Matcher
|
|
3
|
+
class Method
|
|
4
|
+
# Matcher for singleton methods
|
|
5
|
+
class Singleton < self
|
|
6
|
+
|
|
7
|
+
# Return identification
|
|
8
|
+
#
|
|
9
|
+
# @return [String]
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
#
|
|
13
|
+
def identification
|
|
14
|
+
"#{scope.name}.#{method_name}"
|
|
15
|
+
end
|
|
16
|
+
memoize :identification
|
|
17
|
+
|
|
18
|
+
# Test if method is public
|
|
19
|
+
#
|
|
20
|
+
# @return [true]
|
|
21
|
+
# if method is public
|
|
22
|
+
#
|
|
23
|
+
# @return [false]
|
|
24
|
+
# otherwise
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
#
|
|
28
|
+
def public?
|
|
29
|
+
scope.singleton_class.public_method_defined?(method_name)
|
|
30
|
+
end
|
|
31
|
+
memoize :public?
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# Return method instance
|
|
37
|
+
#
|
|
38
|
+
# @return [UnboundMethod]
|
|
39
|
+
#
|
|
40
|
+
# @api private
|
|
41
|
+
#
|
|
42
|
+
def method
|
|
43
|
+
scope.method(method_name)
|
|
44
|
+
end
|
|
45
|
+
memoize :method, :freezer => :noop
|
|
46
|
+
|
|
47
|
+
# Test for node match
|
|
48
|
+
#
|
|
49
|
+
# @param [Rubinius::AST::Node] node
|
|
50
|
+
#
|
|
51
|
+
# @return [true]
|
|
52
|
+
# returns true if node matches method
|
|
53
|
+
#
|
|
54
|
+
# @return [false]
|
|
55
|
+
# returns false if node NOT matches method
|
|
56
|
+
#
|
|
57
|
+
# @api private
|
|
58
|
+
#
|
|
59
|
+
def match?(node)
|
|
60
|
+
node.class == Rubinius::AST::DefineSingleton &&
|
|
61
|
+
line?(node) &&
|
|
62
|
+
name?(node) &&
|
|
63
|
+
receiver?(node)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Test for line match
|
|
67
|
+
#
|
|
68
|
+
# @param [Rubinius::AST::Node] node
|
|
69
|
+
#
|
|
70
|
+
# @return [true]
|
|
71
|
+
# returns true if node matches source line
|
|
72
|
+
#
|
|
73
|
+
# @return [false]
|
|
74
|
+
# returns false otherwise
|
|
75
|
+
#
|
|
76
|
+
# @api private
|
|
77
|
+
#
|
|
78
|
+
def line?(node)
|
|
79
|
+
node.line == source_line
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Test for name match
|
|
83
|
+
#
|
|
84
|
+
# @param [Rubinius::AST::DefineSingleton] node
|
|
85
|
+
#
|
|
86
|
+
# @return [true]
|
|
87
|
+
# returns true if node name matches
|
|
88
|
+
#
|
|
89
|
+
# @return [false]
|
|
90
|
+
# returns false otherwise
|
|
91
|
+
#
|
|
92
|
+
# @api private
|
|
93
|
+
#
|
|
94
|
+
def name?(node)
|
|
95
|
+
node.body.name == method_name
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Test for receiver match
|
|
99
|
+
#
|
|
100
|
+
# @param [Rubinius::AST::DefineSingleton] node
|
|
101
|
+
#
|
|
102
|
+
# @return [true]
|
|
103
|
+
# returns true when receiver is self or scope from pattern
|
|
104
|
+
#
|
|
105
|
+
# @return [false]
|
|
106
|
+
# returns false otherwise
|
|
107
|
+
#
|
|
108
|
+
# @api private
|
|
109
|
+
#
|
|
110
|
+
def receiver?(node)
|
|
111
|
+
receiver = node.receiver
|
|
112
|
+
case receiver
|
|
113
|
+
when Rubinius::AST::Self
|
|
114
|
+
true
|
|
115
|
+
when Rubinius::AST::ConstantAccess
|
|
116
|
+
receiver_name?(receiver)
|
|
117
|
+
else
|
|
118
|
+
raise 'Can only match receiver on Rubinius::AST::Self or Rubinius::AST::ConstantAccess'
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Test if reciver name matches context
|
|
123
|
+
#
|
|
124
|
+
# @param [Rubinius::AST::Node] node
|
|
125
|
+
#
|
|
126
|
+
# @return [true]
|
|
127
|
+
# returns true when node name matches unqualified scope name
|
|
128
|
+
#
|
|
129
|
+
# @return [false]
|
|
130
|
+
# returns false otherwise
|
|
131
|
+
#
|
|
132
|
+
# @api private
|
|
133
|
+
#
|
|
134
|
+
def receiver_name?(node)
|
|
135
|
+
node.name.to_s == context.unqualified_name
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Matcher
|
|
3
|
+
# Matcher against object space
|
|
4
|
+
class ObjectSpace < self
|
|
5
|
+
include Equalizer.new(:scope_name_pattern)
|
|
6
|
+
|
|
7
|
+
PATTERN = %r(\A::(.+)\z)
|
|
8
|
+
|
|
9
|
+
# Parse matcher
|
|
10
|
+
#
|
|
11
|
+
# @param [String] input
|
|
12
|
+
#
|
|
13
|
+
# @return [Matcher::ObjectSpace]
|
|
14
|
+
# returns object space matcher if successful
|
|
15
|
+
#
|
|
16
|
+
# @return [nil]
|
|
17
|
+
# returns nil otherwise
|
|
18
|
+
#
|
|
19
|
+
# @api private
|
|
20
|
+
#
|
|
21
|
+
def self.parse(input)
|
|
22
|
+
match = PATTERN.match(input)
|
|
23
|
+
return unless match
|
|
24
|
+
|
|
25
|
+
new(%r(\A#{Regexp.escape(match[1])}(\z|::)))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Enumerate subjects
|
|
29
|
+
#
|
|
30
|
+
# @return [Enumerator<Subject>]
|
|
31
|
+
# returns subject enumerator when no block given
|
|
32
|
+
#
|
|
33
|
+
# @return [self]
|
|
34
|
+
# returns self otherwise
|
|
35
|
+
#
|
|
36
|
+
# @api private
|
|
37
|
+
#
|
|
38
|
+
def each(&block)
|
|
39
|
+
return to_enum unless block_given?
|
|
40
|
+
|
|
41
|
+
scopes.each do |scope|
|
|
42
|
+
emit_scope_matches(scope, &block)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Return scope name pattern
|
|
49
|
+
#
|
|
50
|
+
# @return [Regexp]
|
|
51
|
+
#
|
|
52
|
+
# @api private
|
|
53
|
+
#
|
|
54
|
+
def scope_name_pattern; @scope_name_pattern; end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# Initialize object space matcher
|
|
59
|
+
#
|
|
60
|
+
# @param [Regexp] scope_name_pattern
|
|
61
|
+
# @param [Enumerable<#each(scope)>] matchers
|
|
62
|
+
#
|
|
63
|
+
# @return [undefined]
|
|
64
|
+
#
|
|
65
|
+
# @api private
|
|
66
|
+
#
|
|
67
|
+
def initialize(scope_name_pattern, matchers = [Matcher::ScopeMethods::Singleton, Matcher::ScopeMethods::Instance])
|
|
68
|
+
@scope_name_pattern, @matchers = scope_name_pattern, @matchers = matchers #[Method::Singleton, Method::Instance]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Yield matchers for scope
|
|
72
|
+
#
|
|
73
|
+
# @param [::Class,::Module] scope
|
|
74
|
+
#
|
|
75
|
+
# @return [undefined]
|
|
76
|
+
#
|
|
77
|
+
# @api private
|
|
78
|
+
#
|
|
79
|
+
def emit_scope_matches(scope, &block)
|
|
80
|
+
@matchers.each do |matcher|
|
|
81
|
+
matcher.new(scope).each(&block)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Return scope enumerator
|
|
86
|
+
#
|
|
87
|
+
# @return [Enumerable<Object>]
|
|
88
|
+
#
|
|
89
|
+
# @api private
|
|
90
|
+
#
|
|
91
|
+
def scopes(&block)
|
|
92
|
+
return to_enum(__method__) unless block_given?
|
|
93
|
+
|
|
94
|
+
::ObjectSpace.each_object(Module) do |scope|
|
|
95
|
+
emit_scope(scope, &block)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Yield scope if name matches pattern
|
|
100
|
+
#
|
|
101
|
+
# @param [::Module,::Class]
|
|
102
|
+
#
|
|
103
|
+
# @return [undefined]
|
|
104
|
+
#
|
|
105
|
+
# @api private
|
|
106
|
+
#
|
|
107
|
+
def emit_scope(scope)
|
|
108
|
+
if [::Module, ::Class].include?(scope.class) and @scope_name_pattern =~ scope.name
|
|
109
|
+
yield scope
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Matcher
|
|
3
|
+
# Abstract base class for matcher that returns subjects extracted from scope methods
|
|
4
|
+
class ScopeMethods < self
|
|
5
|
+
include AbstractType
|
|
6
|
+
|
|
7
|
+
# Return scope
|
|
8
|
+
#
|
|
9
|
+
# @return [Class,Model]
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
#
|
|
13
|
+
attr_reader :scope
|
|
14
|
+
|
|
15
|
+
# Enumerate subjects
|
|
16
|
+
#
|
|
17
|
+
# @return [self]
|
|
18
|
+
# if block given
|
|
19
|
+
#
|
|
20
|
+
# @return [Enumerator<Subject>]
|
|
21
|
+
# otherwise
|
|
22
|
+
#
|
|
23
|
+
# @api private
|
|
24
|
+
#
|
|
25
|
+
def each(&block)
|
|
26
|
+
return to_enum unless block_given?
|
|
27
|
+
methods.each do |method|
|
|
28
|
+
emit_matches(method, &block)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# Initialize object
|
|
37
|
+
#
|
|
38
|
+
# @param [Class,Module] scope
|
|
39
|
+
#
|
|
40
|
+
# @return [undefined]
|
|
41
|
+
#
|
|
42
|
+
# @api private
|
|
43
|
+
#
|
|
44
|
+
def initialize(scope)
|
|
45
|
+
@scope = scope
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Emit matches for method
|
|
49
|
+
#
|
|
50
|
+
# @param [UnboundMethod] method
|
|
51
|
+
#
|
|
52
|
+
# @return [undefined]
|
|
53
|
+
#
|
|
54
|
+
# @api private
|
|
55
|
+
#
|
|
56
|
+
def emit_matches(method)
|
|
57
|
+
matcher.new(scope, method).each do |subject|
|
|
58
|
+
yield subject
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
abstract_method :methods
|
|
64
|
+
|
|
65
|
+
# Return method matcher class
|
|
66
|
+
#
|
|
67
|
+
# @return [Class:Matcher::Method]
|
|
68
|
+
#
|
|
69
|
+
# @api private
|
|
70
|
+
#
|
|
71
|
+
def matcher
|
|
72
|
+
self.class::MATCHER
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class Singleton < self
|
|
76
|
+
MATCHER = Mutant::Matcher::Method::Singleton
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
# Return singleton methods defined on scope
|
|
81
|
+
#
|
|
82
|
+
# @param [Class|Module] scope
|
|
83
|
+
#
|
|
84
|
+
# @return [Enumerable<Symbol>]
|
|
85
|
+
#
|
|
86
|
+
# @api private
|
|
87
|
+
#
|
|
88
|
+
def methods
|
|
89
|
+
singleton_class = scope.singleton_class
|
|
90
|
+
|
|
91
|
+
names =
|
|
92
|
+
singleton_class.public_instance_methods(false) +
|
|
93
|
+
singleton_class.private_instance_methods(false) +
|
|
94
|
+
singleton_class.protected_instance_methods(false)
|
|
95
|
+
|
|
96
|
+
names.map(&:to_sym).sort.reject do |name|
|
|
97
|
+
name.to_sym == :__class_init__
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class Instance < self
|
|
103
|
+
MATCHER = Mutant::Matcher::Method::Instance
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
# Return instance methods names of scope
|
|
108
|
+
#
|
|
109
|
+
# @param [Class|Module] scope
|
|
110
|
+
#
|
|
111
|
+
# @return [Enumerable<Symbol>]
|
|
112
|
+
#
|
|
113
|
+
def methods
|
|
114
|
+
scope = self.scope
|
|
115
|
+
return [] unless scope.kind_of?(Module)
|
|
116
|
+
|
|
117
|
+
names =
|
|
118
|
+
scope.public_instance_methods(false) +
|
|
119
|
+
scope.private_instance_methods(false) +
|
|
120
|
+
scope.protected_instance_methods(false)
|
|
121
|
+
|
|
122
|
+
names.uniq.map(&:to_sym).sort
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
data/lib/mutant/mutation.rb
CHANGED
|
@@ -1,24 +1,113 @@
|
|
|
1
1
|
module Mutant
|
|
2
|
+
# Represent a mutated node with its subject
|
|
2
3
|
class Mutation
|
|
3
|
-
|
|
4
|
+
include Adamantium::Flat, Equalizer.new(:sha1)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
# Return mutation subject
|
|
7
|
+
#
|
|
8
|
+
# @return [Subject]
|
|
9
|
+
#
|
|
10
|
+
# @api private
|
|
11
|
+
#
|
|
12
|
+
attr_reader :subject
|
|
6
13
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
# Return mutated node
|
|
15
|
+
#
|
|
16
|
+
# @return [Rubinius::AST::Node]
|
|
17
|
+
#
|
|
18
|
+
# @api private
|
|
19
|
+
#
|
|
20
|
+
attr_reader :node
|
|
21
|
+
|
|
22
|
+
# Return mutated root node
|
|
23
|
+
#
|
|
24
|
+
# @return [Rubinius::AST::Node]
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
#
|
|
28
|
+
def root
|
|
29
|
+
subject.root(node)
|
|
30
|
+
end
|
|
31
|
+
memoize :root
|
|
32
|
+
|
|
33
|
+
# Insert mutated node
|
|
34
|
+
#
|
|
35
|
+
# @return [self]
|
|
36
|
+
#
|
|
37
|
+
# @api private
|
|
38
|
+
#
|
|
39
|
+
def insert
|
|
40
|
+
Loader::Eval.run(root)
|
|
41
|
+
self
|
|
11
42
|
end
|
|
12
43
|
|
|
13
|
-
|
|
44
|
+
# Return identification
|
|
45
|
+
#
|
|
46
|
+
# @return [String]
|
|
47
|
+
#
|
|
48
|
+
# @api private
|
|
49
|
+
#
|
|
50
|
+
def identification
|
|
51
|
+
"#{subject.identification}:#{code}"
|
|
52
|
+
end
|
|
53
|
+
memoize :identification
|
|
54
|
+
|
|
55
|
+
# Return mutation code
|
|
56
|
+
#
|
|
57
|
+
# @return [String]
|
|
58
|
+
#
|
|
59
|
+
# @api private
|
|
60
|
+
#
|
|
61
|
+
def code
|
|
62
|
+
sha1[0..4]
|
|
63
|
+
end
|
|
64
|
+
memoize :code
|
|
14
65
|
|
|
15
|
-
|
|
16
|
-
|
|
66
|
+
# Return sha1 sum of source and subject identification
|
|
67
|
+
#
|
|
68
|
+
# @return [String]
|
|
69
|
+
#
|
|
70
|
+
# @api private
|
|
71
|
+
#
|
|
72
|
+
def sha1
|
|
73
|
+
Digest::SHA1.hexdigest(subject.identification + source)
|
|
17
74
|
end
|
|
75
|
+
memoize :sha1
|
|
76
|
+
|
|
77
|
+
# Return source
|
|
78
|
+
#
|
|
79
|
+
# @return [String]
|
|
80
|
+
#
|
|
81
|
+
# @api private
|
|
82
|
+
#
|
|
83
|
+
def source
|
|
84
|
+
ToSource.to_source(node)
|
|
85
|
+
end
|
|
86
|
+
memoize :source
|
|
87
|
+
|
|
88
|
+
# Return original source
|
|
89
|
+
#
|
|
90
|
+
# @return [String]
|
|
91
|
+
#
|
|
92
|
+
# @api private
|
|
93
|
+
#
|
|
94
|
+
def original_source
|
|
95
|
+
subject.source
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
18
99
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
100
|
+
# Initialize mutation object
|
|
101
|
+
#
|
|
102
|
+
# @param [Subject] subject
|
|
103
|
+
# @param [Rubinius::Node::AST] node
|
|
104
|
+
#
|
|
105
|
+
# @return [undefined]
|
|
106
|
+
#
|
|
107
|
+
# @api private
|
|
108
|
+
#
|
|
109
|
+
def initialize(subject, node)
|
|
110
|
+
@subject, @node = subject, node
|
|
22
111
|
end
|
|
23
112
|
end
|
|
24
113
|
end
|