mutant 0.2.20 → 0.3.0.beta2

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.
Files changed (201) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +10 -11
  3. data/Changelog.md +93 -38
  4. data/Gemfile +3 -1
  5. data/Gemfile.devtools +16 -20
  6. data/Guardfile +1 -1
  7. data/README.md +36 -16
  8. data/Rakefile +21 -2
  9. data/TODO +11 -7
  10. data/bin/mutant +4 -0
  11. data/bin/zombie +4 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +2 -2
  14. data/config/flog.yml +1 -1
  15. data/config/{site.reek → reek.yml} +94 -70
  16. data/lib/mutant/cli/classifier/method.rb +100 -0
  17. data/lib/mutant/cli/classifier/namespace.rb +47 -0
  18. data/lib/mutant/cli/classifier/scope.rb +35 -0
  19. data/lib/mutant/cli/classifier.rb +141 -0
  20. data/lib/mutant/cli.rb +115 -162
  21. data/lib/mutant/color.rb +2 -2
  22. data/lib/mutant/config.rb +27 -0
  23. data/lib/mutant/constants.rb +32 -17
  24. data/lib/mutant/context/scope.rb +33 -51
  25. data/lib/mutant/context.rb +8 -19
  26. data/lib/mutant/differ.rb +5 -5
  27. data/lib/mutant/helper.rb +2 -17
  28. data/lib/mutant/killer/forked.rb +44 -0
  29. data/lib/mutant/killer/forking.rb +3 -57
  30. data/lib/mutant/killer/rspec.rb +16 -20
  31. data/lib/mutant/killer/static.rb +6 -7
  32. data/lib/mutant/killer.rb +48 -74
  33. data/lib/mutant/loader.rb +6 -6
  34. data/lib/mutant/matcher/chain.rb +4 -25
  35. data/lib/mutant/matcher/method/instance.rb +14 -24
  36. data/lib/mutant/matcher/method/singleton.rb +35 -46
  37. data/lib/mutant/matcher/method.rb +95 -83
  38. data/lib/mutant/matcher/{scope_methods.rb → methods.rb} +53 -76
  39. data/lib/mutant/matcher/namespace.rb +71 -0
  40. data/lib/mutant/matcher/scope.rb +34 -0
  41. data/lib/mutant/matcher.rb +24 -34
  42. data/lib/mutant/mutation/evil.rb +35 -0
  43. data/lib/mutant/mutation/filter/code.rb +7 -28
  44. data/lib/mutant/mutation/filter/regexp.rb +6 -18
  45. data/lib/mutant/mutation/filter/whitelist.rb +5 -4
  46. data/lib/mutant/mutation/filter.rb +10 -9
  47. data/lib/mutant/mutation/neutral.rb +35 -0
  48. data/lib/mutant/mutation.rb +21 -61
  49. data/lib/mutant/mutator/node/argument.rb +88 -0
  50. data/lib/mutant/mutator/node/arguments.rb +52 -0
  51. data/lib/mutant/mutator/node/assignment.rb +34 -38
  52. data/lib/mutant/mutator/node/begin.rb +33 -0
  53. data/lib/mutant/mutator/node/block.rb +14 -14
  54. data/lib/mutant/mutator/node/case.rb +59 -0
  55. data/lib/mutant/mutator/node/define.rb +26 -22
  56. data/lib/mutant/mutator/node/if.rb +31 -71
  57. data/lib/mutant/mutator/node/literal/array.rb +25 -9
  58. data/lib/mutant/mutator/node/literal/boolean.rb +13 -30
  59. data/lib/mutant/mutator/node/literal/dynamic.rb +6 -5
  60. data/lib/mutant/mutator/node/literal/fixnum.rb +18 -7
  61. data/lib/mutant/mutator/node/literal/float.rb +15 -8
  62. data/lib/mutant/mutator/node/literal/hash.rb +33 -52
  63. data/lib/mutant/mutator/node/literal/nil.rb +8 -7
  64. data/lib/mutant/mutator/node/literal/range.rb +25 -50
  65. data/lib/mutant/mutator/node/literal/regex.rb +15 -23
  66. data/lib/mutant/mutator/node/literal/string.rb +7 -6
  67. data/lib/mutant/mutator/node/literal/symbol.rb +7 -6
  68. data/lib/mutant/mutator/node/literal.rb +4 -46
  69. data/lib/mutant/mutator/node/mlhs.rb +27 -0
  70. data/lib/mutant/mutator/node/noop.rb +18 -43
  71. data/lib/mutant/mutator/node/return.rb +8 -8
  72. data/lib/mutant/mutator/node/send/binary.rb +31 -0
  73. data/lib/mutant/mutator/node/send.rb +106 -72
  74. data/lib/mutant/mutator/node/super.rb +15 -20
  75. data/lib/mutant/mutator/node/when.rb +32 -7
  76. data/lib/mutant/mutator/node/while.rb +9 -7
  77. data/lib/mutant/mutator/node.rb +116 -66
  78. data/lib/mutant/mutator/registry.rb +14 -11
  79. data/lib/mutant/mutator/util/array.rb +9 -9
  80. data/lib/mutant/mutator/util/symbol.rb +6 -20
  81. data/lib/mutant/mutator/util.rb +6 -3
  82. data/lib/mutant/mutator.rb +12 -28
  83. data/lib/mutant/node_helpers.rb +28 -0
  84. data/lib/mutant/random.rb +3 -2
  85. data/lib/mutant/reporter/cli/printer/config.rb +174 -0
  86. data/lib/mutant/reporter/cli/printer/killer.rb +42 -0
  87. data/lib/mutant/reporter/cli/printer/mutation.rb +55 -0
  88. data/lib/mutant/reporter/cli/printer/subject.rb +147 -0
  89. data/lib/mutant/reporter/cli/printer.rb +165 -0
  90. data/lib/mutant/reporter/cli.rb +9 -277
  91. data/lib/mutant/reporter/null.rb +6 -30
  92. data/lib/mutant/reporter.rb +6 -73
  93. data/lib/mutant/runner/config.rb +82 -0
  94. data/lib/mutant/runner/mutation.rb +58 -0
  95. data/lib/mutant/runner/subject.rb +81 -0
  96. data/lib/mutant/runner.rb +42 -92
  97. data/lib/mutant/singleton_methods.rb +2 -2
  98. data/lib/mutant/strategy/method_expansion.rb +51 -0
  99. data/lib/mutant/strategy/rspec/dm2/lookup/method.rb +142 -0
  100. data/lib/mutant/strategy/rspec/dm2/lookup.rb +61 -0
  101. data/lib/mutant/strategy/rspec/dm2.rb +22 -0
  102. data/lib/mutant/strategy/rspec.rb +20 -22
  103. data/lib/mutant/strategy/static.rb +18 -0
  104. data/lib/mutant/strategy.rb +15 -50
  105. data/lib/mutant/subject/method.rb +100 -0
  106. data/lib/mutant/subject.rb +18 -49
  107. data/lib/mutant/support/method_object.rb +4 -2
  108. data/lib/mutant.rb +40 -35
  109. data/mutant.gemspec +9 -8
  110. data/spec/integration/mutant/rspec_killer_spec.rb +3 -3
  111. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +9 -0
  112. data/spec/integration/mutant/zombie_spec.rb +1 -1
  113. data/spec/shared/method_matcher_behavior.rb +35 -0
  114. data/spec/shared/mutator_behavior.rb +63 -32
  115. data/spec/spec_helper.rb +13 -3
  116. data/spec/support/ice_nine_config.rb +8 -0
  117. data/spec/support/rspec.rb +1 -1
  118. data/spec/support/zombie.rb +1 -1
  119. data/spec/unit/mutant/cli/class_methods/new_spec.rb +42 -28
  120. data/spec/unit/mutant/cli/class_methods/run_spec.rb +15 -13
  121. data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +44 -0
  122. data/spec/unit/mutant/context/scope/root_spec.rb +4 -4
  123. data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +6 -5
  124. data/spec/unit/mutant/killer/success_predicate_spec.rb +28 -0
  125. data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +1 -1
  126. data/spec/unit/mutant/matcher/chain/each_spec.rb +1 -1
  127. data/spec/unit/mutant/matcher/chain/matchers_spec.rb +1 -1
  128. data/spec/unit/mutant/matcher/method/instance/each_spec.rb +112 -0
  129. data/spec/unit/mutant/matcher/method/singleton/each_spec.rb +93 -0
  130. data/spec/unit/mutant/matcher/methods/instance/each_spec.rb +59 -0
  131. data/spec/unit/mutant/matcher/methods/singleton/each_spec.rb +53 -0
  132. data/spec/unit/mutant/matcher/namespace/each_spec.rb +37 -0
  133. data/spec/unit/mutant/mutator/node/begin/mutation_spec.rb +33 -0
  134. data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +42 -14
  135. data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +319 -0
  136. data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +31 -27
  137. data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +75 -0
  138. data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -1
  139. data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +2 -2
  140. data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +1 -3
  141. data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +1 -9
  142. data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +6 -2
  143. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +111 -108
  144. data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +0 -33
  145. data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +2 -2
  146. data/spec/unit/mutant/runner/config/subjects_spec.rb +38 -0
  147. data/spec/unit/mutant/runner/config/success_predicate_spec.rb +53 -0
  148. data/spec/unit/mutant/runner/failed_predicte_spec.rb +33 -0
  149. data/spec/unit/mutant/runner/mutation/killer_spec.rb +39 -0
  150. data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +49 -0
  151. data/spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb +49 -0
  152. data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb +52 -0
  153. data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb +42 -0
  154. data/spec/unit/mutant/subject/context_spec.rb +6 -3
  155. data/spec/unit/mutant/subject/each_spec.rb +11 -8
  156. data/spec/unit/mutant/subject/node_spec.rb +6 -2
  157. data/test_app/spec/shared/method_filter_parse_behavior.rb +0 -2
  158. data/test_app/spec/shared/method_match_behavior.rb +1 -1
  159. data/test_app/spec/spec_helper.rb +4 -2
  160. metadata +101 -109
  161. data/config/roodi.yml +0 -26
  162. data/lib/mutant/matcher/method/classifier.rb +0 -141
  163. data/lib/mutant/matcher/object_space.rb +0 -114
  164. data/lib/mutant/mutator/node/actual_arguments.rb +0 -25
  165. data/lib/mutant/mutator/node/default_arguments.rb +0 -25
  166. data/lib/mutant/mutator/node/formal_arguments_19/default_mutations.rb +0 -33
  167. data/lib/mutant/mutator/node/formal_arguments_19/pattern_argument_expansion.rb +0 -35
  168. data/lib/mutant/mutator/node/formal_arguments_19/require_defaults.rb +0 -37
  169. data/lib/mutant/mutator/node/formal_arguments_19.rb +0 -41
  170. data/lib/mutant/mutator/node/iter_19.rb +0 -27
  171. data/lib/mutant/mutator/node/literal/empty_array.rb +0 -26
  172. data/lib/mutant/mutator/node/pattern_arguments.rb +0 -41
  173. data/lib/mutant/mutator/node/pattern_variable.rb +0 -23
  174. data/lib/mutant/mutator/node/receiver_case.rb +0 -122
  175. data/lib/mutant/mutator/node/send/binary_operator_method.rb +0 -61
  176. data/lib/mutant/mutator/node/send/with_arguments.rb +0 -81
  177. data/lib/mutant/reporter/stats.rb +0 -120
  178. data/lib/mutant/strategy/rspec/example_lookup.rb +0 -163
  179. data/spec/integration/mutant/method_matching_spec.rb +0 -269
  180. data/spec/shared/method_match_behavior.rb +0 -39
  181. data/spec/unit/mutant/killer/fail_ques_spec.rb +0 -39
  182. data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +0 -49
  183. data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +0 -12
  184. data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +0 -21
  185. data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +0 -52
  186. data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +0 -24
  187. data/spec/unit/mutant/matcher/object_space/each_spec.rb +0 -31
  188. data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +0 -60
  189. data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +0 -27
  190. data/spec/unit/mutant/strategy/rspec/example_lookup/spec_file_spec.rb +0 -236
  191. data/spec/unit/mutant/subject/class_methods/new_spec.rb +0 -13
  192. data/tasks/metrics/ci.rake +0 -7
  193. data/tasks/metrics/flay.rake +0 -41
  194. data/tasks/metrics/flog.rake +0 -43
  195. data/tasks/metrics/heckle.rake +0 -216
  196. data/tasks/metrics/metric_fu.rake +0 -31
  197. data/tasks/metrics/reek.rake +0 -15
  198. data/tasks/metrics/roodi.rake +0 -15
  199. data/tasks/metrics/yardstick.rake +0 -23
  200. data/tasks/spec.rake +0 -45
  201. data/tasks/yard.rake +0 -9
@@ -2,291 +2,23 @@ module Mutant
2
2
  class Reporter
3
3
  # Reporter that reports in human readable format
4
4
  class CLI < self
5
- include Equalizer.new(:io)
5
+ include Concord::Public.new(:output)
6
6
 
7
- # Reporter subject
8
- #
9
- # @param [Subject] subject
10
- #
11
- # @return [self]
12
- #
13
- # @api private
14
- #
15
- def subject(subject)
16
- stats.subject
17
- puts("Subject: #{subject.identification}")
18
- end
7
+ NL = "\n".freeze
19
8
 
20
- # Return error stream
9
+ # Report object
21
10
  #
22
- # @return [IO]
23
- #
24
- # @api private
25
- #
26
- def error_stream
27
- @config.debug? ? io : StringIO.new
28
- end
29
-
30
- # Return output stream
31
- #
32
- # @return [IO]
33
- #
34
- # @api private
35
- #
36
- def output_stream
37
- @config.debug? ? io : StringIO.new
38
- end
39
-
40
- # Report mutation
41
- #
42
- # @param [Mutation] mutation
11
+ # @param [Object] object
43
12
  #
44
13
  # @return [self]
45
14
  #
46
15
  # @api private
47
16
  #
48
- def mutation(mutation)
49
- if @config.debug?
50
- colorized_diff(mutation)
51
- end
52
-
17
+ def report(object)
18
+ Printer.visit(object, output)
53
19
  self
54
20
  end
55
21
 
56
- # Report config
57
- #
58
- # @param [Mutant::Config] config
59
- #
60
- # @return [self]
61
- #
62
- # @api private
63
- #
64
- def config(config)
65
- puts 'Mutant configuration:'
66
- puts "Matcher: #{config.matcher.inspect}"
67
- puts "Filter: #{config.filter.inspect}"
68
- puts "Strategy: #{config.strategy.inspect}"
69
- end
70
-
71
- # Report noop
72
- #
73
- # @param [Killer] killer
74
- #
75
- # @return [self]
76
- #
77
- # @api private
78
- #
79
- def noop(killer)
80
- color, word =
81
- if killer.fail?
82
- [Color::GREEN, 'Alive']
83
- else
84
- [Color::RED, 'Killed']
85
- end
86
-
87
- print_killer(color, word, killer)
88
-
89
- unless killer.fail?
90
- puts(killer.mutation.source)
91
- stats.noop_fail(killer)
92
- end
93
-
94
- self
95
- end
96
-
97
- # Reporter killer
98
- #
99
- # @param [Killer] killer
100
- #
101
- # @return [self]
102
- #
103
- # @api private
104
- #
105
- def killer(killer)
106
- stats.killer(killer)
107
-
108
- color, word =
109
- if killer.fail?
110
- [Color::RED, 'Alive']
111
- else
112
- [Color::GREEN, 'Killed']
113
- end
114
-
115
- print_killer(color, word, killer)
116
-
117
- if killer.fail?
118
- colorized_diff(killer.mutation)
119
- end
120
-
121
- self
122
- end
123
-
124
- # Report errors
125
- #
126
- # @param [Enumerable<Killer>] errors
127
- #
128
- # @api private
129
- #
130
- # @return [self]
131
- #
132
- def errors(errors)
133
- errors.each do |error|
134
- failure(error)
135
- end
136
-
137
- puts
138
- puts "subjects: #{stats.subjects}"
139
- puts "mutations: #{stats.mutations}"
140
- puts "noop_fails: #{stats.noop_fails}"
141
- puts "kills: #{stats.kills}"
142
- puts "alive: #{stats.alive}"
143
- puts "mtime: %02.2fs" % stats.time
144
- puts "rtime: %02.2fs" % stats.runtime
145
- end
146
-
147
- # Return IO stream
148
- #
149
- # @return [IO]
150
- #
151
- # @api private
152
- #
153
- attr_reader :io
154
-
155
- # Return stats
156
- #
157
- # @return [Stats]
158
- #
159
- # @api private
160
- #
161
- attr_reader :stats
162
-
163
- private
164
-
165
- # Initialize reporter
166
- #
167
- # @param [Config] config
168
- #
169
- # @return [undefined]
170
- #
171
- # @api private
172
- #
173
- def initialize(config)
174
- super
175
- @io = $stdout
176
- @stats = Stats.new
177
- end
178
-
179
- # Report failure on killer
180
- #
181
- # @param [Killer] killer
182
- #
183
- # @return [undefined]
184
- #
185
- # @api private
186
- #
187
- def failure(killer)
188
- puts(colorize(Color::RED, "!!! Mutant alive: #{killer.identification} !!!"))
189
- colorized_diff(killer.mutation)
190
- puts("Took: (%02.2fs)" % killer.runtime)
191
- end
192
-
193
- # Test for colored output
194
- #
195
- # @return [true]
196
- # returns true if output is colored
197
- #
198
- # @return [false]
199
- # returns false otherwise
200
- #
201
- # @api private
202
- #
203
- def color?
204
- tty?
205
- end
206
-
207
- # Colorize message
208
- #
209
- # @param [Color] color
210
- # @param [String] message
211
- #
212
- # @api private
213
- #
214
- # @return [String]
215
- # returns colorized string if color is enabled
216
- # returns unmodified message otherwise
217
- #
218
- def colorize(color, message)
219
- color = Color::NONE unless color?
220
- color.format(message)
221
- end
222
-
223
- # Write string to io
224
- #
225
- # @param [String] string
226
- #
227
- # @return [undefined]
228
- #
229
- # @api private
230
- #
231
- def puts(string="\n")
232
- io.puts(string)
233
- end
234
-
235
- # Write colorized diff
236
- #
237
- # @param [Mutation] mutation
238
- #
239
- # @return [undefined]
240
- #
241
- # @api private
242
- #
243
- def colorized_diff(mutation)
244
- if mutation.kind_of?(Mutation::Noop)
245
- puts mutation.original_source
246
- return
247
- end
248
-
249
- original, current = mutation.original_source, mutation.source
250
- differ = Differ.new(original, current)
251
- diff = color? ? differ.colorized_diff : differ.diff
252
-
253
- # FIXME remove this branch before release
254
- if diff.empty?
255
- raise "Unable to create a diff, so ast mutation or to_source has an error!"
256
- end
257
-
258
- puts(diff)
259
- self
260
- end
261
-
262
- # Print killer
263
- #
264
- # @param [Color] color
265
- # @param [String] word
266
- # @param [Killer] killer
267
- #
268
- # @return [undefined]
269
- #
270
- # @api private
271
- #
272
- def print_killer(color, word, killer)
273
- puts(colorize(color, "%s: %s (%02.2fs)" % [word, killer.identification, killer.runtime]))
274
- end
275
-
276
- # Test for output to tty
277
- #
278
- # @return [true]
279
- # returns true if output is a tty
280
- #
281
- # @return [false]
282
- # returns false otherwise
283
- #
284
- # @api private
285
- #
286
- def tty?
287
- @io.respond_to?(:tty?) && @io.tty?
288
- end
289
- memoize :tty?
290
- end
291
- end
292
- end
22
+ end # CLI
23
+ end # Reporter
24
+ end # Mutant
@@ -4,42 +4,18 @@ module Mutant
4
4
  # Null reporter
5
5
  class Null < self
6
6
 
7
- # Report subject
7
+ # Report object
8
8
  #
9
- # @param [Subject] subject
9
+ # @param [Object] _object
10
10
  #
11
11
  # @return [self]
12
12
  #
13
13
  # @api private
14
14
  #
15
- def subject(*)
15
+ def report(_object)
16
16
  self
17
17
  end
18
18
 
19
- # Report mutation
20
- #
21
- # @param [Mutation] mutation
22
- #
23
- # @return [self]
24
- #
25
- # @api private
26
- #
27
- def mutation(*)
28
- self
29
- end
30
-
31
- # Report killer
32
- #
33
- # @param [Killer] killer
34
- #
35
- # @return [self]
36
- #
37
- # @api private
38
- #
39
- def killer(*)
40
- self
41
- end
42
- end
43
-
44
- end
45
- end
19
+ end # Null
20
+ end # Reporter
21
+ end # Mutant
@@ -1,84 +1,17 @@
1
1
  module Mutant
2
- # Abstract reporter
2
+ # Abstract base class for reporters
3
3
  class Reporter
4
4
  include Adamantium::Flat, AbstractType
5
5
 
6
- # Report subject
6
+ # Report object
7
7
  #
8
- # @param [Subject] subject
8
+ # @param [Object] object
9
9
  #
10
10
  # @return [self]
11
11
  #
12
12
  # @api private
13
13
  #
14
- abstract_method :subject
14
+ abstract_method :report
15
15
 
16
- # Report mutation
17
- #
18
- # @param [Mutation] mutation
19
- #
20
- # @return [self]
21
- #
22
- # @api private
23
- #
24
- abstract_method :mutation
25
-
26
- # Report notice
27
- #
28
- # @param [String] notice
29
- #
30
- # @return [self]
31
- #
32
- # @api private
33
- #
34
- abstract_method :notice
35
-
36
- # Report killer
37
- #
38
- # @param [Killer] killer
39
- #
40
- # @return [self]
41
- #
42
- # @api private
43
- #
44
- abstract_method :killer
45
-
46
- # Report config
47
- #
48
- # @param [Mutant::Config] config
49
- #
50
- # @return [self]
51
- #
52
- # @api private
53
- #
54
- abstract_method :config
55
-
56
- # Return output stream
57
- #
58
- # @return [IO]
59
- #
60
- # @api private
61
- #
62
- abstract_method :output_stream
63
-
64
- # Return error stream
65
- #
66
- # @return [IO]
67
- #
68
- # @api private
69
- #
70
- abstract_method :error_stream
71
-
72
- private
73
-
74
- # Initialize reporter
75
- #
76
- # @param [Config] config
77
- #
78
- # @api private
79
- #
80
- def initialize(config)
81
- @config = config
82
- end
83
- end
84
- end
16
+ end # Reporter
17
+ end # Mutant
@@ -0,0 +1,82 @@
1
+ module Mutant
2
+ class Runner
3
+ # Runner for object config
4
+ class Config < self
5
+
6
+ # Return subject runners
7
+ #
8
+ # @return [Enumerable<Runner::Subject>]
9
+ #
10
+ # @api private
11
+ #
12
+ attr_reader :subjects
13
+
14
+ # Return failed subjects
15
+ #
16
+ # @return [Enumerable<Subject>]
17
+ #
18
+ # @api private
19
+ #
20
+ def failed_subjects
21
+ subjects.select(&:failed?)
22
+ end
23
+ memoize :failed_subjects
24
+
25
+ # Test if run was successful
26
+ #
27
+ # @return [true]
28
+ # if run was successful
29
+ #
30
+ # @return [false]
31
+ # otherwise
32
+ #
33
+ # @api private
34
+ #
35
+ def success?
36
+ failed_subjects.empty?
37
+ end
38
+ memoize :success?
39
+
40
+ # Return strategy
41
+ #
42
+ # @return [Strategy]
43
+ #
44
+ # @api private
45
+ #
46
+ def strategy
47
+ config.strategy
48
+ end
49
+
50
+ private
51
+
52
+ # Run config
53
+ #
54
+ # @return [undefined]
55
+ #
56
+ # @api private
57
+ #
58
+ def run_subjects
59
+ strategy = self.strategy
60
+ strategy.setup
61
+ @subjects = config.subjects.map do |subject|
62
+ Subject.run(self, subject)
63
+ end
64
+ strategy.teardown
65
+ end
66
+
67
+ # Run with strategy management
68
+ #
69
+ # @return [undefined]
70
+ #
71
+ # @api private
72
+ #
73
+ def run
74
+ report(config)
75
+ run_subjects
76
+ @end = Time.now
77
+ report(self)
78
+ end
79
+
80
+ end # Config
81
+ end # Runner
82
+ end # Mutant
@@ -0,0 +1,58 @@
1
+ module Mutant
2
+ class Runner
3
+ # Mutation runner
4
+ class Mutation < self
5
+ include Concord::Public.new(:config, :mutation)
6
+
7
+ # Return killer instance
8
+ #
9
+ # @return [Killer]
10
+ #
11
+ # @api private
12
+ #
13
+ attr_reader :killer
14
+
15
+ # Initialize object
16
+ #
17
+ # @param [Config] config
18
+ # @param [Mutation] mutation
19
+ #
20
+ # @return [undefined]
21
+ #
22
+ # @api private
23
+ #
24
+ def initialize(config, mutation)
25
+ @mutation = mutation
26
+ super(config)
27
+ end
28
+
29
+ # Test if mutation was handeled successfully
30
+ #
31
+ # @return [true]
32
+ # if successful
33
+ #
34
+ # @return [false]
35
+ # otherwise
36
+ #
37
+ # @api private
38
+ #
39
+ def success?
40
+ mutation.success?(killer)
41
+ end
42
+
43
+ private
44
+
45
+ # Perform operation
46
+ #
47
+ # @return [undefined]
48
+ #
49
+ # @api private
50
+ #
51
+ def run
52
+ @killer = config.strategy.kill(mutation)
53
+ report(@killer)
54
+ end
55
+
56
+ end # Mutation
57
+ end # Runner
58
+ end # Mutant
@@ -0,0 +1,81 @@
1
+ module Mutant
2
+ class Runner
3
+ # Subject specific runner
4
+ class Subject < self
5
+ include Concord::Public.new(:config, :subject)
6
+
7
+ # Return subject
8
+ #
9
+ # @return [Subject]
10
+ #
11
+ # @api private
12
+ #
13
+ attr_reader :subject
14
+
15
+ # Initialize object
16
+ #
17
+ # @param [Config] config
18
+ # @param [Subject] subject
19
+ #
20
+ # @return [undefined]
21
+ #
22
+ # @api private
23
+ #
24
+ def initialize(config, subject)
25
+ @subject = subject
26
+ super(config)
27
+ end
28
+
29
+ # Return mutation runners
30
+ #
31
+ # @return [Enumerable<Runner::Mutation>]
32
+ #
33
+ # @api private
34
+ #
35
+ attr_reader :mutations
36
+
37
+ # Return failed mutations
38
+ #
39
+ # @return [Enumerable<Mutation>]
40
+ #
41
+ # @api private
42
+ #
43
+ def failed_mutations
44
+ mutations.select(&:failed?)
45
+ end
46
+ memoize :failed_mutations
47
+
48
+ # Test if subject was processed successful
49
+ #
50
+ # @return [true]
51
+ # if successful
52
+ #
53
+ # @return [false]
54
+ # otherwise
55
+ #
56
+ # @api private
57
+ #
58
+ def success?
59
+ failed_mutations.empty?
60
+ end
61
+
62
+ private
63
+
64
+ # Perform operation
65
+ #
66
+ # @return [undefined]
67
+ #
68
+ # @api private
69
+ #
70
+ def run
71
+ subject = self.subject
72
+ report(subject)
73
+ @mutations = subject.map do |mutation|
74
+ Mutation.run(config, mutation)
75
+ end
76
+ report(self)
77
+ end
78
+
79
+ end # Subject
80
+ end # Runner
81
+ end # Mutant