mutant 0.3.0.rc1 → 0.3.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +0 -1
- data/.travis.yml +5 -4
- data/Gemfile.devtools +4 -4
- data/Guardfile +7 -5
- data/README.md +8 -8
- data/config/flay.yml +2 -2
- data/config/reek.yml +1 -0
- data/config/rubocop.yml +0 -4
- data/lib/mutant/cli/builder.rb +177 -0
- data/lib/mutant/cli/classifier/method.rb +10 -14
- data/lib/mutant/cli/classifier/namespace.rb +7 -9
- data/lib/mutant/cli/classifier.rb +29 -31
- data/lib/mutant/cli.rb +34 -96
- data/lib/mutant/color.rb +1 -1
- data/lib/mutant/config.rb +9 -3
- data/lib/mutant/constants.rb +1 -1
- data/lib/mutant/context/scope.rb +2 -2
- data/lib/mutant/differ.rb +0 -1
- data/lib/mutant/killer/rspec.rb +3 -8
- data/lib/mutant/killer.rb +1 -22
- data/lib/mutant/matcher/chain.rb +2 -2
- data/lib/mutant/matcher/filter.rb +32 -0
- data/lib/mutant/matcher/method/instance.rb +2 -2
- data/lib/mutant/matcher/method.rb +3 -3
- data/lib/mutant/matcher/methods.rb +1 -1
- data/lib/mutant/matcher.rb +1 -0
- data/lib/mutant/mutation/evil.rb +0 -10
- data/lib/mutant/mutation/neutral.rb +0 -23
- data/lib/mutant/mutation.rb +13 -23
- data/lib/mutant/mutator/node/begin.rb +12 -10
- data/lib/mutant/mutator/node/block.rb +1 -0
- data/lib/mutant/mutator/node/blockarg.rb +15 -0
- data/lib/mutant/mutator/node/case.rb +1 -0
- data/lib/mutant/mutator/node/connective/binary.rb +2 -2
- data/lib/mutant/mutator/node/const.rb +2 -1
- data/lib/mutant/mutator/node/dstr.rb +28 -0
- data/lib/mutant/mutator/node/dsym.rb +28 -0
- data/lib/mutant/mutator/node/generic.rb +3 -4
- data/lib/mutant/mutator/node/if.rb +1 -0
- data/lib/mutant/mutator/node/literal/boolean.rb +2 -2
- data/lib/mutant/mutator/node/literal/range.rb +8 -6
- data/lib/mutant/mutator/node/literal.rb +0 -17
- data/lib/mutant/mutator/node/masgn.rb +1 -1
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +5 -4
- data/lib/mutant/mutator/node/op_asgn.rb +30 -0
- data/lib/mutant/mutator/node/restarg.rb +15 -0
- data/lib/mutant/mutator/node/return.rb +1 -2
- data/lib/mutant/mutator/node/send.rb +6 -5
- data/lib/mutant/mutator/node/super.rb +1 -0
- data/lib/mutant/mutator/node/while.rb +1 -0
- data/lib/mutant/mutator/node.rb +11 -1
- data/lib/mutant/node_helpers.rb +3 -3
- data/lib/mutant/predicate/attribute.rb +85 -0
- data/lib/mutant/predicate/blacklist.rb +27 -0
- data/lib/mutant/predicate/matcher.rb +36 -0
- data/lib/mutant/predicate/whitelist.rb +28 -0
- data/lib/mutant/predicate.rb +91 -0
- data/lib/mutant/reporter/cli/printer/config.rb +3 -3
- data/lib/mutant/reporter/cli/printer/killer.rb +1 -1
- data/lib/mutant/reporter/cli/printer/mutation.rb +12 -14
- data/lib/mutant/reporter/cli/printer/subject.rb +1 -3
- data/lib/mutant/reporter/cli/printer.rb +31 -7
- data/lib/mutant/runner/mutation.rb +9 -1
- data/lib/mutant/runner/subject.rb +9 -1
- data/lib/mutant/runner.rb +5 -6
- data/lib/mutant/strategy/rspec.rb +4 -4
- data/lib/mutant/strategy.rb +2 -0
- data/lib/mutant/support/method_object.rb +0 -1
- data/lib/mutant/version.rb +1 -2
- data/lib/mutant/zombifier.rb +6 -3
- data/lib/mutant.rb +12 -4
- data/mutant.gemspec +7 -7
- data/spec/integration/mutant/rspec_spec.rb +12 -5
- data/spec/shared/mutator_behavior.rb +2 -1
- data/spec/spec_helper.rb +11 -9
- data/spec/unit/mutant/cli/builder/rspec_spec.rb +38 -0
- data/spec/unit/mutant/cli/classifier/{method/each_spec.rb → method_spec.rb} +2 -14
- data/spec/unit/mutant/cli/classifier/namespace/{flat/each_spec.rb → flat_spec.rb} +1 -1
- data/spec/unit/mutant/cli/classifier/namespace/{recursive/each_spec.rb → recursive_spec.rb} +1 -1
- data/spec/unit/mutant/cli/classifier_spec.rb +59 -0
- data/spec/unit/mutant/{cli/class_methods/new_spec.rb → cli_new_spec.rb} +22 -23
- data/spec/unit/mutant/{cli/class_methods/run_spec.rb → cli_run_spec.rb} +8 -8
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +6 -6
- data/spec/unit/mutant/killer/success_predicate_spec.rb +5 -5
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +1 -1
- data/spec/unit/mutant/matcher/filter_spec.rb +19 -0
- data/spec/unit/mutant/matcher/namespace/each_spec.rb +5 -5
- data/spec/unit/mutant/mutation_spec.rb +42 -0
- data/spec/unit/mutant/mutator/each_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/and_asgn/mutation_spec.rb +3 -2
- data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +7 -2
- data/spec/unit/mutant/mutator/node/block_pass/mutation_spec.rb +1 -0
- data/spec/unit/mutant/mutator/node/blockarg/mutation_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +5 -1
- data/spec/unit/mutant/mutator/node/cbase/mutation_spec.rb +1 -0
- data/spec/unit/mutant/mutator/node/const/mutation_spec.rb +3 -2
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +3 -3
- data/spec/unit/mutant/mutator/node/defined_predicate/mutation_spec.rb +6 -2
- data/spec/unit/mutant/mutator/node/dstr/mutation_spec.rb +4 -2
- data/spec/unit/mutant/mutator/node/dsym/mutation_spec.rb +4 -2
- data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +6 -1
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/literal/float_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/literal/range_spec.rb +31 -0
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +4 -2
- data/spec/unit/mutant/mutator/node/literal/string_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/masgn/mutation_spec.rb +6 -2
- data/spec/unit/mutant/mutator/node/match_current_line/mutation_spec.rb +1 -0
- data/spec/unit/mutant/mutator/node/named_value/access/mutation_spec.rb +5 -1
- data/spec/unit/mutant/mutator/node/named_value/constant_assignment/mutation_spec.rb +1 -2
- data/spec/unit/mutant/mutator/node/named_value/variable_assignment/mutation_spec.rb +5 -5
- data/spec/unit/mutant/mutator/node/op_assgn/mutation_spec.rb +3 -2
- data/spec/unit/mutant/mutator/node/or_asgn/mutation_spec.rb +3 -2
- data/spec/unit/mutant/mutator/node/rescue/mutation_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/restarg/mutation_spec.rb +3 -1
- data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +7 -3
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +37 -2
- data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +4 -0
- data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +3 -0
- data/spec/unit/mutant/predicate_spec.rb +135 -0
- data/spec/unit/mutant/runner/config/subjects_spec.rb +11 -11
- data/spec/unit/mutant/runner/config/success_predicate_spec.rb +6 -6
- data/spec/unit/mutant/runner/mutation/killer_spec.rb +11 -11
- data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +9 -9
- data/spec/unit/mutant/strategy_spec.rb +21 -0
- data/spec/unit/mutant/subject_spec.rb +39 -0
- data/test_app/spec/shared/method_filter_parse_behavior.rb +1 -1
- metadata +54 -36
- data/lib/mutant/cli/classifier/scope.rb +0 -37
- data/lib/mutant/mutation/filter/code.rb +0 -49
- data/lib/mutant/mutation/filter/regexp.rb +0 -29
- data/lib/mutant/mutation/filter/whitelist.rb +0 -52
- data/lib/mutant/mutation/filter.rb +0 -78
- data/lib/mutant/strategy/static.rb +0 -20
- data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +0 -48
- data/spec/unit/mutant/cli/classifier/scope/each_spec.rb +0 -33
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Mutator
|
5
|
+
class Node
|
6
|
+
|
7
|
+
# Dstr mutator
|
8
|
+
class Dstr < Generic
|
9
|
+
|
10
|
+
handle(:dstr)
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# Emit mutations
|
15
|
+
#
|
16
|
+
# @return [undefined]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
def dispatch
|
21
|
+
super
|
22
|
+
emit_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
end # Dstr
|
26
|
+
end # Node
|
27
|
+
end # Mutator
|
28
|
+
end # Mutant
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Mutator
|
5
|
+
class Node
|
6
|
+
|
7
|
+
# Dsym mutator
|
8
|
+
class Dsym < Generic
|
9
|
+
|
10
|
+
handle(:dsym)
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# Emit mutations
|
15
|
+
#
|
16
|
+
# @return [undefined]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
def dispatch
|
21
|
+
super
|
22
|
+
emit_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
end # Dsym
|
26
|
+
end # Node
|
27
|
+
end # Mutator
|
28
|
+
end # Mutant
|
@@ -11,12 +11,11 @@ module Mutant
|
|
11
11
|
# your contribution is that close!
|
12
12
|
handle(
|
13
13
|
:next, :break, :ensure,
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:regopt, :restarg, :resbody, :retry, :arg_expr,
|
14
|
+
:yield, :rescue, :redo, :defined?,
|
15
|
+
:regopt, :resbody, :retry, :arg_expr,
|
17
16
|
:kwrestarg, :kwoptarg, :kwarg, :undef, :module, :empty,
|
18
17
|
:alias, :for, :xstr, :back_ref, :class,
|
19
|
-
:sclass, :match_with_lvasgn, :match_current_line, :
|
18
|
+
:sclass, :match_with_lvasgn, :match_current_line, :kwbegin
|
20
19
|
)
|
21
20
|
|
22
21
|
private
|
@@ -10,8 +10,8 @@ module Mutant
|
|
10
10
|
include AbstractType
|
11
11
|
|
12
12
|
MAP = {
|
13
|
-
:
|
14
|
-
:
|
13
|
+
irange: :erange,
|
14
|
+
erange: :irange
|
15
15
|
}.freeze
|
16
16
|
|
17
17
|
children :start, :_end
|
@@ -29,8 +29,8 @@ module Mutant
|
|
29
29
|
def dispatch
|
30
30
|
emit_nil
|
31
31
|
emit_inverse
|
32
|
-
|
33
|
-
|
32
|
+
emit_lower_bound_mutations
|
33
|
+
emit_upper_bound_mutations
|
34
34
|
end
|
35
35
|
|
36
36
|
# Return inverse node
|
@@ -49,7 +49,8 @@ module Mutant
|
|
49
49
|
#
|
50
50
|
# @api private
|
51
51
|
#
|
52
|
-
def
|
52
|
+
def emit_upper_bound_mutations
|
53
|
+
emit__end_mutations
|
53
54
|
emit_self(NAN, _end)
|
54
55
|
end
|
55
56
|
|
@@ -59,7 +60,8 @@ module Mutant
|
|
59
60
|
#
|
60
61
|
# @api private
|
61
62
|
#
|
62
|
-
def
|
63
|
+
def emit_lower_bound_mutations
|
64
|
+
emit_start_mutations
|
63
65
|
emit_self(start, INFINITY)
|
64
66
|
emit_self(start, NAN)
|
65
67
|
end
|
@@ -6,23 +6,6 @@ module Mutant
|
|
6
6
|
# Abstract mutator for literal AST nodes
|
7
7
|
class Literal < self
|
8
8
|
include AbstractType
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
# Emit a new node with wrapping class for each entry in values
|
13
|
-
#
|
14
|
-
# @param [Array] values
|
15
|
-
#
|
16
|
-
# @return [undefined]
|
17
|
-
#
|
18
|
-
# @api private
|
19
|
-
#
|
20
|
-
def emit_values(values)
|
21
|
-
values.each do |value|
|
22
|
-
emit_self(value)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
9
|
end # Literal
|
27
10
|
end # Node
|
28
11
|
end # Mutator
|
@@ -11,10 +11,10 @@ module Mutant
|
|
11
11
|
children :name, :value
|
12
12
|
|
13
13
|
MAP = IceNine.deep_freeze(
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
14
|
+
gvasgn: '$',
|
15
|
+
cvasgn: '@@',
|
16
|
+
ivasgn: '@',
|
17
|
+
lvasgn: ''
|
18
18
|
)
|
19
19
|
|
20
20
|
handle(*MAP.keys)
|
@@ -30,6 +30,7 @@ module Mutant
|
|
30
30
|
def dispatch
|
31
31
|
mutate_name
|
32
32
|
emit_value_mutations if value # mlhs!
|
33
|
+
emit_nil
|
33
34
|
end
|
34
35
|
|
35
36
|
# Emit name mutations
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Mutator
|
5
|
+
class Node
|
6
|
+
|
7
|
+
# OpAsgn mutator
|
8
|
+
class OpAsgn < Generic
|
9
|
+
|
10
|
+
handle(:op_asgn, :or_asgn, :and_asgn)
|
11
|
+
|
12
|
+
children :left, :right
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# Emit mutations
|
17
|
+
#
|
18
|
+
# @return [undefined]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
#
|
22
|
+
def dispatch
|
23
|
+
super
|
24
|
+
emit_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
end # OpAsgn
|
28
|
+
end # Node
|
29
|
+
end # Mutator
|
30
|
+
end # Mutant
|
@@ -12,8 +12,8 @@ module Mutant
|
|
12
12
|
children :receiver, :selector
|
13
13
|
|
14
14
|
SELECTOR_REPLACEMENTS = {
|
15
|
-
:
|
16
|
-
:
|
15
|
+
send: :public_send,
|
16
|
+
gsub: :sub
|
17
17
|
}.freeze
|
18
18
|
|
19
19
|
INDEX_REFERENCE = :[]
|
@@ -71,6 +71,7 @@ module Mutant
|
|
71
71
|
else
|
72
72
|
non_index_dispatch
|
73
73
|
end
|
74
|
+
emit_nil
|
74
75
|
end
|
75
76
|
|
76
77
|
# Perform non index dispatch
|
@@ -103,19 +104,19 @@ module Mutant
|
|
103
104
|
#
|
104
105
|
def normal_dispatch
|
105
106
|
emit_naked_receiver
|
106
|
-
|
107
|
+
emit_selector_replacement
|
107
108
|
mutate_receiver
|
108
109
|
emit_argument_propagation
|
109
110
|
mutate_arguments
|
110
111
|
end
|
111
112
|
|
112
|
-
# Emit selector
|
113
|
+
# Emit selector replacement
|
113
114
|
#
|
114
115
|
# @return [undefined]
|
115
116
|
#
|
116
117
|
# @api private
|
117
118
|
#
|
118
|
-
def
|
119
|
+
def emit_selector_replacement
|
119
120
|
replacement = SELECTOR_REPLACEMENTS.fetch(selector) { return }
|
120
121
|
emit_selector(replacement)
|
121
122
|
end
|
data/lib/mutant/mutator/node.rb
CHANGED
@@ -181,7 +181,7 @@ module Mutant
|
|
181
181
|
# @api private
|
182
182
|
#
|
183
183
|
def emit_nil
|
184
|
-
emit(N_NIL)
|
184
|
+
emit(N_NIL) unless agsn_left?
|
185
185
|
end
|
186
186
|
|
187
187
|
# Return new self typed child
|
@@ -222,6 +222,16 @@ module Mutant
|
|
222
222
|
parent && parent.node.type
|
223
223
|
end
|
224
224
|
|
225
|
+
# Test if the node is the left of an or_asgn or op_asgn
|
226
|
+
#
|
227
|
+
# @return [Boolean]
|
228
|
+
#
|
229
|
+
# @api private
|
230
|
+
#
|
231
|
+
def agsn_left?
|
232
|
+
OP_ASSIGN.include?(parent_type) && parent.left.equal?(node)
|
233
|
+
end
|
234
|
+
|
225
235
|
end # Node
|
226
236
|
end # Mutator
|
227
237
|
end # Mutant
|
data/lib/mutant/node_helpers.rb
CHANGED
@@ -18,13 +18,13 @@ module Mutant
|
|
18
18
|
module_function :s
|
19
19
|
|
20
20
|
NAN =
|
21
|
-
s(:
|
21
|
+
s(:send, s(:float, 0.0), :/, s(:args, s(:float, 0.0)))
|
22
22
|
INFINITY =
|
23
|
-
s(:
|
23
|
+
s(:send, s(:float, 1.0), :/, s(:args, s(:float, 0.0)))
|
24
24
|
NEW_OBJECT =
|
25
25
|
s(:send, s(:const, s(:cbase), :Object), :new)
|
26
26
|
NEGATIVE_INFINITY =
|
27
|
-
s(:
|
27
|
+
s(:send, s(:float, -1.0), :/, s(:args, s(:float, 0.0)))
|
28
28
|
|
29
29
|
RAISE = s(:send, nil, :raise)
|
30
30
|
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Predicate
|
5
|
+
# Base class for predicates on object attributes
|
6
|
+
class Attribute < self
|
7
|
+
include Concord.new(:attribute_name, :expectation)
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# Return value for object
|
12
|
+
#
|
13
|
+
# @param [Object] object
|
14
|
+
#
|
15
|
+
# @return [Object]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
def value(object)
|
20
|
+
object.public_send(attribute_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Regexp based attribute predicate
|
24
|
+
class Regexp < self
|
25
|
+
|
26
|
+
# Test for match
|
27
|
+
#
|
28
|
+
# @param [Object] object
|
29
|
+
#
|
30
|
+
# @return [true]
|
31
|
+
# if attribute value matches expectation
|
32
|
+
#
|
33
|
+
# @return [false]
|
34
|
+
# otherwise
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
#
|
38
|
+
def match?(object)
|
39
|
+
!!(expectation =~ value(object))
|
40
|
+
end
|
41
|
+
|
42
|
+
end # Regexp
|
43
|
+
|
44
|
+
# Equality based attribute predicate
|
45
|
+
class Equality < self
|
46
|
+
|
47
|
+
PATTERN = /\Acode:(?<code>[[:xdigit:]]{1,6})\z/.freeze
|
48
|
+
|
49
|
+
# Test if class handles string
|
50
|
+
#
|
51
|
+
# @param [String] notation
|
52
|
+
#
|
53
|
+
# @return [Filter]
|
54
|
+
# if notation matches pattern
|
55
|
+
#
|
56
|
+
# @return [nil]
|
57
|
+
# otherwise
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
#
|
61
|
+
def self.handle(notation)
|
62
|
+
match = PATTERN.match(notation)
|
63
|
+
new(:code, match[:code]) if match
|
64
|
+
end
|
65
|
+
|
66
|
+
# Test for match
|
67
|
+
#
|
68
|
+
# @param [Object] object
|
69
|
+
#
|
70
|
+
# @return [true]
|
71
|
+
# if attribute value matches expectation
|
72
|
+
#
|
73
|
+
# @return [false]
|
74
|
+
# otherwise
|
75
|
+
#
|
76
|
+
# @api private
|
77
|
+
#
|
78
|
+
def match?(object)
|
79
|
+
expectation.eql?(value(object))
|
80
|
+
end
|
81
|
+
|
82
|
+
end # Equality
|
83
|
+
end # Attribute
|
84
|
+
end # Filter
|
85
|
+
end # Mutant
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Predicate
|
5
|
+
# Blacklist predicate
|
6
|
+
class Blacklist < self
|
7
|
+
include Adamantium::Flat, Concord.new(:blacklist)
|
8
|
+
|
9
|
+
# Test for match
|
10
|
+
#
|
11
|
+
# @param [Object] object
|
12
|
+
#
|
13
|
+
# @return [true]
|
14
|
+
# if object matches blacklist
|
15
|
+
#
|
16
|
+
# @return [false]
|
17
|
+
# otherwise
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
def match?(object)
|
22
|
+
blacklist.none? { |predicate| predicate.match?(object) }
|
23
|
+
end
|
24
|
+
|
25
|
+
end # Whitelist
|
26
|
+
end # Filter
|
27
|
+
end # Mutant
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Mutant
|
2
|
+
class Predicate
|
3
|
+
# Return matcher
|
4
|
+
class Matcher < self
|
5
|
+
include Concord.new(:matcher)
|
6
|
+
|
7
|
+
# Test if subject matches
|
8
|
+
#
|
9
|
+
# @param [Subject] subject
|
10
|
+
#
|
11
|
+
# @return [true]
|
12
|
+
# if subject is handled by matcher
|
13
|
+
#
|
14
|
+
# @return [false]
|
15
|
+
# otherwise
|
16
|
+
#
|
17
|
+
def match?(subject)
|
18
|
+
subjects.include?(subject)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# Return subjects matched by matcher
|
24
|
+
#
|
25
|
+
# @return [Set<Subject>]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
def subjects
|
30
|
+
matcher.to_a.to_set
|
31
|
+
end
|
32
|
+
memoize :subjects
|
33
|
+
|
34
|
+
end # Matcher
|
35
|
+
end # Predicate
|
36
|
+
end # Mutant
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Predicate
|
5
|
+
|
6
|
+
# Whiltelist filter
|
7
|
+
class Whitelist < self
|
8
|
+
include Adamantium::Flat, Concord.new(:whitelist)
|
9
|
+
|
10
|
+
# Test for match
|
11
|
+
#
|
12
|
+
# @param [Object] object
|
13
|
+
#
|
14
|
+
# @return [true]
|
15
|
+
# if mutation matches whitelist
|
16
|
+
#
|
17
|
+
# @return [false]
|
18
|
+
# otherwise
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
#
|
22
|
+
def match?(object)
|
23
|
+
whitelist.any? { |filter| filter.match?(object) }
|
24
|
+
end
|
25
|
+
|
26
|
+
end # Whitelist
|
27
|
+
end # Predicate
|
28
|
+
end # Mutant
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
# Abstract base class for predicates used to filter subjects / mutations
|
5
|
+
class Predicate
|
6
|
+
include Adamantium::Flat, AbstractType
|
7
|
+
extend DescendantsTracker
|
8
|
+
|
9
|
+
# Check for match
|
10
|
+
#
|
11
|
+
# @param [Object] object
|
12
|
+
#
|
13
|
+
# @return [true]
|
14
|
+
# if object is matched by predicate
|
15
|
+
#
|
16
|
+
# @return [false]
|
17
|
+
# otherwise
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
abstract_method :match?
|
22
|
+
|
23
|
+
# Build predicate from string
|
24
|
+
#
|
25
|
+
# @param [String] notation
|
26
|
+
#
|
27
|
+
# @return [Filter]
|
28
|
+
# when can be build from string
|
29
|
+
#
|
30
|
+
# @return [nil]
|
31
|
+
# otherwise
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
def self.build(notation)
|
36
|
+
descendants.each do |descendant|
|
37
|
+
predicate = descendant.handle(notation)
|
38
|
+
return predicate if predicate
|
39
|
+
end
|
40
|
+
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return predicate for handle
|
45
|
+
#
|
46
|
+
# @param [String] _notation
|
47
|
+
#
|
48
|
+
# @return [nil]
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
#
|
52
|
+
def self.handle(_notation)
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
# Mutation predicate matching no inputs
|
57
|
+
Mutant.singleton_subclass_instance('CONTRADICTION', self) do
|
58
|
+
|
59
|
+
# Test for match
|
60
|
+
#
|
61
|
+
# @pram [Mutation] _mutation
|
62
|
+
#
|
63
|
+
# @return [true]
|
64
|
+
#
|
65
|
+
# @api private
|
66
|
+
#
|
67
|
+
def match?(_mutation)
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
# Mutation predicate matching all inputs
|
74
|
+
Mutant.singleton_subclass_instance('TAUTOLOGY', self) do
|
75
|
+
|
76
|
+
# Test for match
|
77
|
+
#
|
78
|
+
# @pram [Mutation] _mutation
|
79
|
+
#
|
80
|
+
# @return [true]
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
#
|
84
|
+
def match?(_mutation)
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end # Filter
|
91
|
+
end # Mutant
|
@@ -20,9 +20,9 @@ module Mutant
|
|
20
20
|
#
|
21
21
|
def run
|
22
22
|
info 'Mutant configuration:'
|
23
|
-
info 'Matcher:
|
24
|
-
info 'Filter:
|
25
|
-
info 'Strategy:
|
23
|
+
info 'Matcher: %s', object.matcher.inspect
|
24
|
+
info 'Subject Filter: %s', object.subject_predicate.inspect
|
25
|
+
info 'Strategy: %s', object.strategy.inspect
|
26
26
|
self
|
27
27
|
end
|
28
28
|
|