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.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.travis.yml +5 -4
  4. data/Gemfile.devtools +4 -4
  5. data/Guardfile +7 -5
  6. data/README.md +8 -8
  7. data/config/flay.yml +2 -2
  8. data/config/reek.yml +1 -0
  9. data/config/rubocop.yml +0 -4
  10. data/lib/mutant/cli/builder.rb +177 -0
  11. data/lib/mutant/cli/classifier/method.rb +10 -14
  12. data/lib/mutant/cli/classifier/namespace.rb +7 -9
  13. data/lib/mutant/cli/classifier.rb +29 -31
  14. data/lib/mutant/cli.rb +34 -96
  15. data/lib/mutant/color.rb +1 -1
  16. data/lib/mutant/config.rb +9 -3
  17. data/lib/mutant/constants.rb +1 -1
  18. data/lib/mutant/context/scope.rb +2 -2
  19. data/lib/mutant/differ.rb +0 -1
  20. data/lib/mutant/killer/rspec.rb +3 -8
  21. data/lib/mutant/killer.rb +1 -22
  22. data/lib/mutant/matcher/chain.rb +2 -2
  23. data/lib/mutant/matcher/filter.rb +32 -0
  24. data/lib/mutant/matcher/method/instance.rb +2 -2
  25. data/lib/mutant/matcher/method.rb +3 -3
  26. data/lib/mutant/matcher/methods.rb +1 -1
  27. data/lib/mutant/matcher.rb +1 -0
  28. data/lib/mutant/mutation/evil.rb +0 -10
  29. data/lib/mutant/mutation/neutral.rb +0 -23
  30. data/lib/mutant/mutation.rb +13 -23
  31. data/lib/mutant/mutator/node/begin.rb +12 -10
  32. data/lib/mutant/mutator/node/block.rb +1 -0
  33. data/lib/mutant/mutator/node/blockarg.rb +15 -0
  34. data/lib/mutant/mutator/node/case.rb +1 -0
  35. data/lib/mutant/mutator/node/connective/binary.rb +2 -2
  36. data/lib/mutant/mutator/node/const.rb +2 -1
  37. data/lib/mutant/mutator/node/dstr.rb +28 -0
  38. data/lib/mutant/mutator/node/dsym.rb +28 -0
  39. data/lib/mutant/mutator/node/generic.rb +3 -4
  40. data/lib/mutant/mutator/node/if.rb +1 -0
  41. data/lib/mutant/mutator/node/literal/boolean.rb +2 -2
  42. data/lib/mutant/mutator/node/literal/range.rb +8 -6
  43. data/lib/mutant/mutator/node/literal.rb +0 -17
  44. data/lib/mutant/mutator/node/masgn.rb +1 -1
  45. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +5 -4
  46. data/lib/mutant/mutator/node/op_asgn.rb +30 -0
  47. data/lib/mutant/mutator/node/restarg.rb +15 -0
  48. data/lib/mutant/mutator/node/return.rb +1 -2
  49. data/lib/mutant/mutator/node/send.rb +6 -5
  50. data/lib/mutant/mutator/node/super.rb +1 -0
  51. data/lib/mutant/mutator/node/while.rb +1 -0
  52. data/lib/mutant/mutator/node.rb +11 -1
  53. data/lib/mutant/node_helpers.rb +3 -3
  54. data/lib/mutant/predicate/attribute.rb +85 -0
  55. data/lib/mutant/predicate/blacklist.rb +27 -0
  56. data/lib/mutant/predicate/matcher.rb +36 -0
  57. data/lib/mutant/predicate/whitelist.rb +28 -0
  58. data/lib/mutant/predicate.rb +91 -0
  59. data/lib/mutant/reporter/cli/printer/config.rb +3 -3
  60. data/lib/mutant/reporter/cli/printer/killer.rb +1 -1
  61. data/lib/mutant/reporter/cli/printer/mutation.rb +12 -14
  62. data/lib/mutant/reporter/cli/printer/subject.rb +1 -3
  63. data/lib/mutant/reporter/cli/printer.rb +31 -7
  64. data/lib/mutant/runner/mutation.rb +9 -1
  65. data/lib/mutant/runner/subject.rb +9 -1
  66. data/lib/mutant/runner.rb +5 -6
  67. data/lib/mutant/strategy/rspec.rb +4 -4
  68. data/lib/mutant/strategy.rb +2 -0
  69. data/lib/mutant/support/method_object.rb +0 -1
  70. data/lib/mutant/version.rb +1 -2
  71. data/lib/mutant/zombifier.rb +6 -3
  72. data/lib/mutant.rb +12 -4
  73. data/mutant.gemspec +7 -7
  74. data/spec/integration/mutant/rspec_spec.rb +12 -5
  75. data/spec/shared/mutator_behavior.rb +2 -1
  76. data/spec/spec_helper.rb +11 -9
  77. data/spec/unit/mutant/cli/builder/rspec_spec.rb +38 -0
  78. data/spec/unit/mutant/cli/classifier/{method/each_spec.rb → method_spec.rb} +2 -14
  79. data/spec/unit/mutant/cli/classifier/namespace/{flat/each_spec.rb → flat_spec.rb} +1 -1
  80. data/spec/unit/mutant/cli/classifier/namespace/{recursive/each_spec.rb → recursive_spec.rb} +1 -1
  81. data/spec/unit/mutant/cli/classifier_spec.rb +59 -0
  82. data/spec/unit/mutant/{cli/class_methods/new_spec.rb → cli_new_spec.rb} +22 -23
  83. data/spec/unit/mutant/{cli/class_methods/run_spec.rb → cli_run_spec.rb} +8 -8
  84. data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +6 -6
  85. data/spec/unit/mutant/killer/success_predicate_spec.rb +5 -5
  86. data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +1 -1
  87. data/spec/unit/mutant/matcher/filter_spec.rb +19 -0
  88. data/spec/unit/mutant/matcher/namespace/each_spec.rb +5 -5
  89. data/spec/unit/mutant/mutation_spec.rb +42 -0
  90. data/spec/unit/mutant/mutator/each_spec.rb +1 -1
  91. data/spec/unit/mutant/mutator/node/and_asgn/mutation_spec.rb +3 -2
  92. data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +7 -2
  93. data/spec/unit/mutant/mutator/node/block_pass/mutation_spec.rb +1 -0
  94. data/spec/unit/mutant/mutator/node/blockarg/mutation_spec.rb +17 -0
  95. data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +5 -1
  96. data/spec/unit/mutant/mutator/node/cbase/mutation_spec.rb +1 -0
  97. data/spec/unit/mutant/mutator/node/const/mutation_spec.rb +3 -2
  98. data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +3 -3
  99. data/spec/unit/mutant/mutator/node/defined_predicate/mutation_spec.rb +6 -2
  100. data/spec/unit/mutant/mutator/node/dstr/mutation_spec.rb +4 -2
  101. data/spec/unit/mutant/mutator/node/dsym/mutation_spec.rb +4 -2
  102. data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +6 -1
  103. data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -1
  104. data/spec/unit/mutant/mutator/node/literal/float_spec.rb +1 -1
  105. data/spec/unit/mutant/mutator/node/literal/range_spec.rb +31 -0
  106. data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +4 -2
  107. data/spec/unit/mutant/mutator/node/literal/string_spec.rb +1 -1
  108. data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +1 -1
  109. data/spec/unit/mutant/mutator/node/masgn/mutation_spec.rb +6 -2
  110. data/spec/unit/mutant/mutator/node/match_current_line/mutation_spec.rb +1 -0
  111. data/spec/unit/mutant/mutator/node/named_value/access/mutation_spec.rb +5 -1
  112. data/spec/unit/mutant/mutator/node/named_value/constant_assignment/mutation_spec.rb +1 -2
  113. data/spec/unit/mutant/mutator/node/named_value/variable_assignment/mutation_spec.rb +5 -5
  114. data/spec/unit/mutant/mutator/node/op_assgn/mutation_spec.rb +3 -2
  115. data/spec/unit/mutant/mutator/node/or_asgn/mutation_spec.rb +3 -2
  116. data/spec/unit/mutant/mutator/node/rescue/mutation_spec.rb +1 -1
  117. data/spec/unit/mutant/mutator/node/restarg/mutation_spec.rb +3 -1
  118. data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +7 -3
  119. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +37 -2
  120. data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +4 -0
  121. data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +3 -0
  122. data/spec/unit/mutant/predicate_spec.rb +135 -0
  123. data/spec/unit/mutant/runner/config/subjects_spec.rb +11 -11
  124. data/spec/unit/mutant/runner/config/success_predicate_spec.rb +6 -6
  125. data/spec/unit/mutant/runner/mutation/killer_spec.rb +11 -11
  126. data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +9 -9
  127. data/spec/unit/mutant/strategy_spec.rb +21 -0
  128. data/spec/unit/mutant/subject_spec.rb +39 -0
  129. data/test_app/spec/shared/method_filter_parse_behavior.rb +1 -1
  130. metadata +54 -36
  131. data/lib/mutant/cli/classifier/scope.rb +0 -37
  132. data/lib/mutant/mutation/filter/code.rb +0 -49
  133. data/lib/mutant/mutation/filter/regexp.rb +0 -29
  134. data/lib/mutant/mutation/filter/whitelist.rb +0 -52
  135. data/lib/mutant/mutation/filter.rb +0 -78
  136. data/lib/mutant/strategy/static.rb +0 -20
  137. data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +0 -48
  138. 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
- :dstr, :dsym, :yield, :rescue, :redo, :defined?,
15
- :blockarg, :op_asgn, :and_asgn,
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, :or_asgn, :kwbegin
18
+ :sclass, :match_with_lvasgn, :match_current_line, :kwbegin
20
19
  )
21
20
 
22
21
  private
@@ -22,6 +22,7 @@ module Mutant
22
22
  mutate_condition
23
23
  mutate_if_branch
24
24
  mutate_else_branch
25
+ emit_nil
25
26
  end
26
27
 
27
28
  # Emit conditon mutations
@@ -10,8 +10,8 @@ module Mutant
10
10
  private
11
11
 
12
12
  MAP = {
13
- :true => :false,
14
- :false => :true
13
+ true: :false,
14
+ false: :true
15
15
  }.freeze
16
16
 
17
17
  handle(*MAP.keys)
@@ -10,8 +10,8 @@ module Mutant
10
10
  include AbstractType
11
11
 
12
12
  MAP = {
13
- :irange => :erange,
14
- :erange => :irange
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
- emit_start_mutations
33
- emit_end_mutations
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 emit_end_mutations
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 emit_start_mutations
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
@@ -20,7 +20,7 @@ module Mutant
20
20
  # @api private
21
21
  #
22
22
  def dispatch
23
- # noop, for now
23
+ emit_nil
24
24
  end
25
25
 
26
26
  end # MultipleAssignment
@@ -11,10 +11,10 @@ module Mutant
11
11
  children :name, :value
12
12
 
13
13
  MAP = IceNine.deep_freeze(
14
- :gvasgn => '$',
15
- :cvasgn => '@@',
16
- :ivasgn => '@',
17
- :lvasgn => ''
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
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ module Mutant
4
+ class Mutator
5
+ class Node
6
+
7
+ # Restarg mutator
8
+ class Restarg < Generic
9
+
10
+ handle(:restarg)
11
+
12
+ end # Restarg
13
+ end # Node
14
+ end # Mutator
15
+ end # Mutant
@@ -22,9 +22,8 @@ module Mutant
22
22
  if value
23
23
  emit(value)
24
24
  emit_value_mutations
25
- else
26
- emit_nil
27
25
  end
26
+ emit_nil
28
27
  end
29
28
 
30
29
  end # Return
@@ -12,8 +12,8 @@ module Mutant
12
12
  children :receiver, :selector
13
13
 
14
14
  SELECTOR_REPLACEMENTS = {
15
- :send => :public_send,
16
- :gsub => :sub
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
- emit_selector_mutations
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 mutations
113
+ # Emit selector replacement
113
114
  #
114
115
  # @return [undefined]
115
116
  #
116
117
  # @api private
117
118
  #
118
- def emit_selector_mutations
119
+ def emit_selector_replacement
119
120
  replacement = SELECTOR_REPLACEMENTS.fetch(selector) { return }
120
121
  emit_selector(replacement)
121
122
  end
@@ -27,6 +27,7 @@ module Mutant
27
27
  mutate_child(index)
28
28
  delete_child(index)
29
29
  end
30
+ emit_nil
30
31
  end
31
32
 
32
33
  end # Super
@@ -23,6 +23,7 @@ module Mutant
23
23
  emit_condition_mutations
24
24
  emit_body_mutations
25
25
  emit_body(nil)
26
+ emit_nil
26
27
  end
27
28
 
28
29
  end # While
@@ -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
@@ -18,13 +18,13 @@ module Mutant
18
18
  module_function :s
19
19
 
20
20
  NAN =
21
- s(:begin, s(:send, s(:float, 0.0), :/, s(:args, s(:float, 0.0))))
21
+ s(:send, s(:float, 0.0), :/, s(:args, s(:float, 0.0)))
22
22
  INFINITY =
23
- s(:begin, s(:send, s(:float, 1.0), :/, s(:args, s(:float, 0.0))))
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(:begin, s(:send, s(:float, -1.0), :/, s(:args, s(:float, 0.0))))
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: %s', object.matcher.inspect
24
- info 'Filter: %s', object.filter.inspect
25
- info 'Strategy: %s', object.strategy.inspect
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
 
@@ -8,7 +8,7 @@ module Mutant
8
8
  # Printer for killer results
9
9
  class Killer < self
10
10
 
11
- handle(Mutant::Killer::Forked)
11
+ handle(Mutant::Killer)
12
12
 
13
13
  SUCCESS = '.'.freeze
14
14
  FAILURE = 'F'.freeze