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
data/lib/mutant/cli.rb CHANGED
@@ -19,7 +19,7 @@ module Mutant
19
19
  # @param [Array<String>] arguments
20
20
  #
21
21
  # @return [Fixnum]
22
- # returns exit status
22
+ # the exit status
23
23
  #
24
24
  # @api private
25
25
  #
@@ -42,12 +42,11 @@ module Mutant
42
42
  #
43
43
  def initialize(arguments = [])
44
44
  @filters, @matchers = [], []
45
-
45
+ @debug = @fail_fast = @zombie = false
46
46
  @cache = Mutant::Cache.new
47
-
47
+ @strategy_builder = nil
48
48
  parse(arguments)
49
- strategy
50
- matcher
49
+ config # trigger lazyness now
51
50
  end
52
51
 
53
52
  # Return config
@@ -58,60 +57,20 @@ module Mutant
58
57
  #
59
58
  def config
60
59
  Config.new(
61
- :cache => @cache,
62
- :zombie => @zombie,
63
- :debug => debug?,
64
- :matcher => matcher,
65
- :filter => filter,
66
- :fail_fast => !!@fail_fast,
67
- :strategy => strategy,
68
- :reporter => reporter
60
+ cache: @cache,
61
+ zombie: @zombie,
62
+ debug: @debug,
63
+ matcher: matcher,
64
+ subject_predicate: @subject_predicate.output,
65
+ strategy: @strategy.output,
66
+ fail_fast: @fail_fast,
67
+ reporter: reporter
69
68
  )
70
69
  end
71
70
  memoize :config
72
71
 
73
72
  private
74
73
 
75
- # Test for running in debug mode
76
- #
77
- # @return [true]
78
- # if debug mode is active
79
- #
80
- # @return [false]
81
- # otherwise
82
- #
83
- # @api private
84
- #
85
- def debug?
86
- !!@debug
87
- end
88
-
89
- # Return mutation filter
90
- #
91
- # @return [Mutant::Matcher]
92
- #
93
- # @api private
94
- #
95
- def filter
96
- if @filters.empty?
97
- Mutation::Filter::ALL
98
- else
99
- Mutation::Filter::Whitelist.new(@filters)
100
- end
101
- end
102
- memoize :filter
103
-
104
- # Return stratety
105
- #
106
- # @return [Strategy]
107
- #
108
- # @api private
109
- #
110
- def strategy
111
- @strategy or raise(Error, 'No strategy was set!')
112
- end
113
- memoize :strategy
114
-
115
74
  # Return reporter
116
75
  #
117
76
  # @return [Mutant::Reporter::CLI]
@@ -121,7 +80,6 @@ module Mutant
121
80
  def reporter
122
81
  Reporter::CLI.new($stdout)
123
82
  end
124
- memoize :reporter
125
83
 
126
84
  # Return matcher
127
85
  #
@@ -134,37 +92,22 @@ module Mutant
134
92
  #
135
93
  def matcher
136
94
  if @matchers.empty?
137
- raise Error, 'No matchers given'
95
+ raise(Error, 'No matchers given')
138
96
  end
139
97
 
140
98
  Matcher::Chain.build(@matchers)
141
99
  end
142
- memoize :matcher
143
100
 
144
101
  # Add mutation filter
145
102
  #
146
- # @param [Class<Mutant::Filter>] klass
147
- #
148
- # @param [String] filter
103
+ # @param [Class<Predicate>] klass
149
104
  #
150
105
  # @return [undefined]
151
106
  #
152
107
  # @api private
153
108
  #
154
- def add_filter(klass, filter)
155
- @filters << klass.new(filter)
156
- end
157
-
158
- # Set strategy
159
- #
160
- # @param [Strategy] strategy
161
- #
162
- # @api private
163
- #
164
- # @return [undefined]
165
- #
166
- def set_strategy(strategy)
167
- @strategy = strategy
109
+ def add_filter(klass, *arguments)
110
+ @filters << klass.new(*arguments)
168
111
  end
169
112
 
170
113
  # Parse the command-line options
@@ -182,22 +125,20 @@ module Mutant
182
125
  def parse(arguments)
183
126
  opts = OptionParser.new do |builder|
184
127
  builder.banner = 'usage: mutant STRATEGY [options] MATCHERS ...'
185
- builder.separator ''
186
- builder.separator 'Strategies:'
187
-
128
+ builder.separator('')
188
129
  add_strategies(builder)
189
130
  add_environmental_options(builder)
190
131
  add_options(builder)
191
132
  end
192
133
 
193
- matchers =
134
+ patterns =
194
135
  begin
195
136
  opts.parse!(arguments)
196
137
  rescue OptionParser::ParseError => error
197
138
  raise(Error, error.message, error.backtrace)
198
139
  end
199
140
 
200
- parse_matchers(matchers)
141
+ parse_matchers(patterns)
201
142
  end
202
143
 
203
144
  # Parse matchers
@@ -210,31 +151,29 @@ module Mutant
210
151
  #
211
152
  def parse_matchers(patterns)
212
153
  patterns.each do |pattern|
213
- matcher = Classifier.build(@cache, pattern)
154
+ matcher = Classifier.run(@cache, pattern)
214
155
  @matchers << matcher if matcher
215
156
  end
216
157
  end
217
158
 
218
159
  # Add strategies
219
160
  #
220
- # @param [Object] opts
161
+ # @param [OptionParser] parser
221
162
  #
222
163
  # @return [undefined]
223
164
  #
224
165
  # @api private
225
166
  #
226
- def add_strategies(opts)
227
- opts.separator ''
228
- opts.separator 'Strategies:'
167
+ def add_strategies(parser)
168
+ parser.separator(EMPTY_STRING)
169
+ parser.separator('Strategies:')
229
170
 
230
- opts.on('--static-success', 'does succeed on all mutations') do
231
- set_strategy Strategy::Static::Success.new
232
- end
233
- opts.on('--static-fail', 'does fail on all mutations') do
234
- set_strategy Strategy::Static::Fail.new
235
- end
236
- opts.on('--rspec', 'kills mutations with rspec') do
237
- set_strategy Strategy::Rspec.new
171
+ {
172
+ Builder::Rspec => :@strategy,
173
+ Builder::Predicate::Subject => :@subject_predicate,
174
+ }.each do |builder, instance_variable_name|
175
+ builder = builder.new(@cache, parser)
176
+ instance_variable_set(instance_variable_name, builder)
238
177
  end
239
178
  end
240
179
 
@@ -249,10 +188,10 @@ module Mutant
249
188
  def add_environmental_options(opts)
250
189
  opts.on('--zombie', 'Run mutant zombified') do
251
190
  @zombie = true
252
- end.on('-I', 'Add directory to $LOAD_PATH') do |directory|
191
+ end.on('-I', '--include DIRECTORY', 'Add DIRECTORY to $LOAD_PATH') do |directory|
253
192
  $LOAD_PATH << directory
254
- end.on('-r', '--require NAME', 'Require file with NAME') do |name|
255
- require name
193
+ end.on('-require', '--require NAME', 'Require file with NAME') do |name|
194
+ require(name)
256
195
  end
257
196
  end
258
197
 
@@ -272,7 +211,7 @@ module Mutant
272
211
  puts("mutant-#{Mutant::VERSION}")
273
212
  Kernel.exit(0)
274
213
  end.on('--code FILTER', 'Adds a code filter') do |filter|
275
- add_filter(Mutation::Filter::Code, filter)
214
+ add_filter(Predicate::Attribute, :code, filter)
276
215
  end.on('--fail-fast', 'Fail fast') do
277
216
  @fail_fast = true
278
217
  end.on('-d', '--debug', 'Enable debugging output') do
@@ -282,6 +221,5 @@ module Mutant
282
221
  exit
283
222
  end
284
223
  end
285
-
286
224
  end # CLI
287
225
  end # Mutant
data/lib/mutant/color.rb CHANGED
@@ -36,7 +36,7 @@ module Mutant
36
36
  # @param [String] text
37
37
  #
38
38
  # @return [String]
39
- # returns the argument string
39
+ # the argument string
40
40
  #
41
41
  # @api private
42
42
  #
data/lib/mutant/config.rb CHANGED
@@ -4,8 +4,14 @@ module Mutant
4
4
  # The configuration of a mutator run
5
5
  class Config
6
6
  include Adamantium::Flat, Anima.new(
7
- :cache, :debug, :strategy, :matcher, :filter,
8
- :reporter, :fail_fast, :zombie
7
+ :cache,
8
+ :debug,
9
+ :strategy,
10
+ :matcher,
11
+ :subject_predicate,
12
+ :reporter,
13
+ :fail_fast,
14
+ :zombie
9
15
  )
10
16
 
11
17
  # Enumerate subjects
@@ -22,7 +28,7 @@ module Mutant
22
28
  #
23
29
  def subjects(&block)
24
30
  return to_enum(__method__) unless block_given?
25
- matcher.each(&block)
31
+ Matcher::Filter.new(matcher, subject_predicate).each(&block)
26
32
  self
27
33
  end
28
34
 
@@ -15,7 +15,7 @@ module Mutant
15
15
 
16
16
  # Set of op assign types
17
17
  OP_ASSIGN = [
18
- :or_asgn, :and_asgn
18
+ :or_asgn, :and_asgn, :op_asgn
19
19
  ].to_set.freeze
20
20
 
21
21
  # Set of node types that are not valid when emitted standalone
@@ -96,8 +96,8 @@ module Mutant
96
96
  # @api private
97
97
  #
98
98
  def match_prefixes
99
- name_nesting.length.downto(1).map do |last|
100
- name_nesting[0...last].join('::')
99
+ name_nesting.each_index.reverse_each.map do |index|
100
+ name_nesting.take(index.succ).join('::')
101
101
  end
102
102
  end
103
103
  memoize :match_prefixes
data/lib/mutant/differ.rb CHANGED
@@ -108,7 +108,6 @@ module Mutant
108
108
  # @param [String] line
109
109
  #
110
110
  # @return [String]
111
- # returns colorized line
112
111
  #
113
112
  # @api private
114
113
  #
@@ -23,13 +23,13 @@ module Mutant
23
23
  groups = example_groups
24
24
 
25
25
  unless groups
26
- $stderr.puts "No rspec example groups found for: #{match_prefixes.join(', ')}"
26
+ $stderr.puts("No rspec example groups found for: #{match_prefixes.join(', ')}")
27
27
  return false
28
28
  end
29
29
 
30
30
  reporter = RSpec::Core::Reporter.new
31
31
 
32
- example_groups.each do |group|
32
+ groups.each do |group|
33
33
  return true unless group.run(reporter)
34
34
  end
35
35
 
@@ -53,12 +53,7 @@ module Mutant
53
53
  # @api private
54
54
  #
55
55
  def example_groups
56
- match_prefixes.each do |match_expression|
57
- example_groups = find_with(match_expression)
58
- return example_groups unless example_groups.empty?
59
- end
60
-
61
- nil
56
+ match_prefixes.flat_map { |prefix| find_with(prefix) }.compact.uniq
62
57
  end
63
58
 
64
59
  # Return example groups that match expression
data/lib/mutant/killer.rb CHANGED
@@ -33,7 +33,7 @@ module Mutant
33
33
  #
34
34
  def initialize(strategy, mutation)
35
35
  @strategy, @mutation = strategy, mutation
36
- run_with_benchmark
36
+ @killed = run
37
37
  end
38
38
 
39
39
  # Test for kill failure
@@ -65,14 +65,6 @@ module Mutant
65
65
  @killed
66
66
  end
67
67
 
68
- # Return runtime of killer
69
- #
70
- # @return [Float]
71
- #
72
- # @api private
73
- #
74
- attr_reader :runtime
75
-
76
68
  # Return mutated source
77
69
  #
78
70
  # @return [String]
@@ -85,19 +77,6 @@ module Mutant
85
77
 
86
78
  private
87
79
 
88
- # Run with taking the time
89
- #
90
- # @return [undefined]
91
- #
92
- # @api private
93
- #
94
- def run_with_benchmark
95
- times = Benchmark.measure do
96
- @killed = run
97
- end
98
- @runtime = times.real
99
- end
100
-
101
80
  # Return subject
102
81
  #
103
82
  # @return [Subject]
@@ -9,10 +9,10 @@ module Mutant
9
9
  # Enumerate subjects
10
10
  #
11
11
  # @return [Enumerator<Subject]
12
- # returns subject enumerator if no block given
12
+ # if no block given
13
13
  #
14
14
  # @return [self]
15
- # returnns self otherwise
15
+ # otherwise
16
16
  #
17
17
  # @api private
18
18
  #
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ module Mutant
4
+ class Matcher
5
+ # Matcher filter
6
+ class Filter < self
7
+ include Concord.new(:matcher, :filter)
8
+
9
+ # Enumerate matches
10
+ #
11
+ # @return [self]
12
+ # if block given
13
+ #
14
+ # @return [Enumerator<Subject>]
15
+ # otherwise
16
+ #
17
+ # @api private
18
+ #
19
+ def each
20
+ return to_enum unless block_given?
21
+
22
+ matcher.each do |subject|
23
+ next if filter.match?(subject)
24
+ yield subject
25
+ end
26
+
27
+ self
28
+ end
29
+
30
+ end # Filter
31
+ end # Matcher
32
+ end # Mutant
@@ -45,10 +45,10 @@ module Mutant
45
45
  # @param [Parser::AST::Node] node
46
46
  #
47
47
  # @return [true]
48
- # returns true if node matches method
48
+ # if node matches method
49
49
  #
50
50
  # @return [false]
51
- # returns false if node NOT matches method
51
+ # otherwise
52
52
  #
53
53
  # @api private
54
54
  #
@@ -14,10 +14,10 @@ module Mutant
14
14
  # Enumerate matches
15
15
  #
16
16
  # @return [Enumerable<Subject>]
17
- # returns enumerable when no block given
17
+ # if no block given
18
18
  #
19
19
  # @return [self]
20
- # returns self when block given
20
+ # otherwise
21
21
  #
22
22
  # @api private
23
23
  #
@@ -129,7 +129,7 @@ module Mutant
129
129
  # Return subject
130
130
  #
131
131
  # @return [Subject]
132
- # returns subject if there is a matched node
132
+ # if there is a matched node
133
133
  #
134
134
  # @return [nil]
135
135
  # otherwise
@@ -117,7 +117,7 @@ module Mutant
117
117
  def candidate_scope
118
118
  scope.singleton_class
119
119
  end
120
- memoize :candidate_scope, :freezer => :noop
120
+ memoize :candidate_scope, freezer: :noop
121
121
 
122
122
  end # Singleton
123
123
 
@@ -14,6 +14,7 @@ module Mutant
14
14
  # if block given
15
15
  #
16
16
  # @return [Enumerable<Subject>]
17
+ # otherwise
17
18
  #
18
19
  # @api private
19
20
  #
@@ -32,16 +32,6 @@ module Mutant
32
32
  killer.killed?
33
33
  end
34
34
 
35
- # Indicate if a killer should treat a kill as problematic
36
- #
37
- # @return [false] Killing evil mutants is not problematic
38
- #
39
- # @api private
40
- #
41
- def should_survive?
42
- false
43
- end
44
-
45
35
  end # Evil
46
36
  end # Mutation
47
37
  end # Mutant
@@ -12,19 +12,6 @@ module Mutant
12
12
 
13
13
  SYMBOL = 'noop'
14
14
 
15
- # Indicate if a killer should treat a kill as problematic
16
- #
17
- # @return [false] Killing noop mutants is a serious problem. Failures
18
- # in noop may indicate a broken test suite, but they can also be an
19
- # indication mutant has altered the runtime environment in a subtle
20
- # way and tickled an odd bug
21
- #
22
- # @api private
23
- #
24
- def should_survive?
25
- false
26
- end
27
-
28
15
  end
29
16
 
30
17
  # Return identification
@@ -54,16 +41,6 @@ module Mutant
54
41
  !killer.killed?
55
42
  end
56
43
 
57
- # Indicate if a killer should treat a kill as problematic
58
- #
59
- # @return [true] Neutral mutants must die
60
- #
61
- # @api private
62
- #
63
- def should_survive?
64
- false
65
- end
66
-
67
44
  end # Neutral
68
45
  end # Mutation
69
46
  end # Mutant
@@ -31,18 +31,6 @@ module Mutant
31
31
  #
32
32
  abstract_method :success?
33
33
 
34
- # Indicate if a killer should treat a kill as problematic
35
- #
36
- # @return [true]
37
- # if killing is unexpected
38
- #
39
- # @return [false]
40
- # if killing is expected
41
- #
42
- # @api private
43
- #
44
- abstract_method :should_survive?
45
-
46
34
  # Insert mutated node
47
35
  #
48
36
  # FIXME: Cache subject visibility in a better way! Ideally dont mutate it
@@ -81,17 +69,6 @@ module Mutant
81
69
  end
82
70
  memoize :code
83
71
 
84
- # Return sha1 sum of source and subject identification
85
- #
86
- # @return [String]
87
- #
88
- # @api private
89
- #
90
- def sha1
91
- Digest::SHA1.hexdigest(subject.identification + 0.chr + source)
92
- end
93
- memoize :sha1
94
-
95
72
  # Return source
96
73
  #
97
74
  # @return [String]
@@ -113,5 +90,18 @@ module Mutant
113
90
  subject.source
114
91
  end
115
92
 
93
+ private
94
+
95
+ # Return sha1 sum of source and subject identification
96
+ #
97
+ # @return [String]
98
+ #
99
+ # @api private
100
+ #
101
+ def sha1
102
+ Digest::SHA1.hexdigest(subject.identification + 0.chr + source)
103
+ end
104
+ memoize :sha1
105
+
116
106
  end # Mutation
117
107
  end # Mutant
@@ -19,9 +19,7 @@ module Mutant
19
19
  #
20
20
  def dispatch
21
21
  Util::Array.each(children, self) do |children|
22
- if children.length > 1
23
- emit_self(*children)
24
- end
22
+ emit_child_subset(children)
25
23
  end
26
24
  children.each_with_index do |child, index|
27
25
  mutate_child(index)
@@ -29,18 +27,22 @@ module Mutant
29
27
  end
30
28
  end
31
29
 
32
- # Test if parent input is a send
30
+ # Emit child subset
33
31
  #
34
- # @return [true]
35
- # if parent input is a send node
32
+ # @param [Array<Parser::AST::Node>] nodes
36
33
  #
37
- # @return [false]
38
- # otherwise
34
+ # @return [undefined]
39
35
  #
40
36
  # @api private
41
37
  #
42
- def parent_send?
43
- parent && parent.input.type == :send
38
+ def emit_child_subset(children)
39
+ case children.length
40
+ when 0
41
+ when 1
42
+ emit(children.first)
43
+ else
44
+ emit_self(*children)
45
+ end
44
46
  end
45
47
 
46
48
  end # Block
@@ -26,6 +26,7 @@ module Mutant
26
26
  end
27
27
  emit_body(nil)
28
28
  emit_body(RAISE)
29
+ emit_nil
29
30
  end
30
31
 
31
32
  end # Block
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ module Mutant
4
+ class Mutator
5
+ class Node
6
+
7
+ # Blockarg mutator
8
+ class Blockarg < Generic
9
+
10
+ handle(:blockarg)
11
+
12
+ end # Blockarg
13
+ end # Node
14
+ end # Mutator
15
+ end # Mutant
@@ -23,6 +23,7 @@ module Mutant
23
23
  emit_condition_mutations
24
24
  emit_when_mutations
25
25
  emit_else_mutations
26
+ emit_nil
26
27
  end
27
28
 
28
29
  # Emit when mutations
@@ -9,8 +9,8 @@ module Mutant
9
9
  class Binary < Node
10
10
 
11
11
  INVERSE = {
12
- :and => :or,
13
- :or => :and,
12
+ and: :or,
13
+ or: :and
14
14
  }.freeze
15
15
 
16
16
  handle(*INVERSE.keys)
@@ -18,7 +18,8 @@ module Mutant
18
18
  # @api private
19
19
  #
20
20
  def dispatch
21
- emit_nil
21
+ emit_nil unless parent_type == :const
22
+ emit_self(nil, *children.drop(1))
22
23
  children.each_with_index do |child, index|
23
24
  mutate_child(index) if child.kind_of?(Parser::AST::Node)
24
25
  end