mutant 0.9.11 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/bin/mutant +16 -11
  3. data/lib/mutant.rb +8 -4
  4. data/lib/mutant/bootstrap.rb +14 -1
  5. data/lib/mutant/cli.rb +9 -162
  6. data/lib/mutant/cli/command.rb +196 -0
  7. data/lib/mutant/cli/command/root.rb +13 -0
  8. data/lib/mutant/cli/command/run.rb +151 -0
  9. data/lib/mutant/cli/command/subscription.rb +54 -0
  10. data/lib/mutant/expression.rb +0 -1
  11. data/lib/mutant/isolation.rb +1 -1
  12. data/lib/mutant/isolation/fork.rb +2 -2
  13. data/lib/mutant/isolation/none.rb +1 -1
  14. data/lib/mutant/license.rb +9 -35
  15. data/lib/mutant/license/subscription.rb +31 -9
  16. data/lib/mutant/license/subscription/commercial.rb +2 -4
  17. data/lib/mutant/license/subscription/opensource.rb +7 -7
  18. data/lib/mutant/matcher/config.rb +2 -0
  19. data/lib/mutant/meta/example.rb +16 -4
  20. data/lib/mutant/meta/example/dsl.rb +33 -16
  21. data/lib/mutant/meta/example/verification.rb +70 -28
  22. data/lib/mutant/minitest/coverage.rb +51 -0
  23. data/lib/mutant/mutator/node.rb +2 -2
  24. data/lib/mutant/mutator/node/block_pass.rb +29 -0
  25. data/lib/mutant/mutator/node/{dstr.rb → dynamic_literal.rb} +7 -5
  26. data/lib/mutant/mutator/node/index.rb +4 -4
  27. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +1 -1
  28. data/lib/mutant/mutator/node/noop.rb +1 -1
  29. data/lib/mutant/mutator/node/op_asgn.rb +15 -1
  30. data/lib/mutant/mutator/node/send.rb +25 -1
  31. data/lib/mutant/mutator/node/send/attribute_assignment.rb +1 -0
  32. data/lib/mutant/reporter/cli/printer/isolation_result.rb +9 -3
  33. data/lib/mutant/selector/expression.rb +3 -1
  34. data/lib/mutant/subject/method/instance.rb +1 -1
  35. data/lib/mutant/test.rb +1 -1
  36. data/lib/mutant/version.rb +1 -1
  37. metadata +18 -336
  38. data/.github/workflows/ci.yml +0 -121
  39. data/.gitignore +0 -38
  40. data/.rspec +0 -5
  41. data/.rubocop.yml +0 -210
  42. data/Changelog.md +0 -91
  43. data/Gemfile +0 -7
  44. data/Gemfile.lock +0 -107
  45. data/Gemfile.shared +0 -10
  46. data/README.md +0 -199
  47. data/Rakefile +0 -5
  48. data/config/devtools.yml +0 -2
  49. data/config/reek.yml +0 -139
  50. data/config/yardstick.yml +0 -2
  51. data/docs/commercial-support.md +0 -14
  52. data/docs/concurrency.md +0 -39
  53. data/docs/incremental.md +0 -76
  54. data/docs/known-problems.md +0 -30
  55. data/docs/limitations.md +0 -50
  56. data/docs/mutant-minitest.md +0 -149
  57. data/docs/mutant-rspec.md +0 -130
  58. data/docs/nomenclature.md +0 -82
  59. data/docs/reading-reports.md +0 -74
  60. data/lib/mutant/mutator/node/dsym.rb +0 -22
  61. data/meta/and.rb +0 -13
  62. data/meta/and_asgn.rb +0 -14
  63. data/meta/array.rb +0 -27
  64. data/meta/begin.rb +0 -20
  65. data/meta/block.rb +0 -199
  66. data/meta/block_pass.rb +0 -8
  67. data/meta/blockarg.rb +0 -10
  68. data/meta/break.rb +0 -9
  69. data/meta/case.rb +0 -217
  70. data/meta/casgn.rb +0 -25
  71. data/meta/cbase.rb +0 -8
  72. data/meta/class.rb +0 -12
  73. data/meta/const.rb +0 -17
  74. data/meta/csend.rb +0 -10
  75. data/meta/cvar.rb +0 -7
  76. data/meta/cvasgn.rb +0 -9
  77. data/meta/date.rb +0 -59
  78. data/meta/def.rb +0 -196
  79. data/meta/defined.rb +0 -9
  80. data/meta/dstr.rb +0 -13
  81. data/meta/dsym.rb +0 -14
  82. data/meta/ensure.rb +0 -8
  83. data/meta/false.rb +0 -7
  84. data/meta/file.rb +0 -5
  85. data/meta/float.rb +0 -37
  86. data/meta/gvar.rb +0 -7
  87. data/meta/gvasgn.rb +0 -9
  88. data/meta/hash.rb +0 -20
  89. data/meta/if.rb +0 -72
  90. data/meta/index.rb +0 -133
  91. data/meta/indexasgn.rb +0 -31
  92. data/meta/int.rb +0 -18
  93. data/meta/ivar.rb +0 -8
  94. data/meta/ivasgn.rb +0 -22
  95. data/meta/kwarg.rb +0 -10
  96. data/meta/kwbegin.rb +0 -8
  97. data/meta/kwoptarg.rb +0 -13
  98. data/meta/lambda.rb +0 -23
  99. data/meta/line.rb +0 -5
  100. data/meta/lvar.rb +0 -16
  101. data/meta/lvasgn.rb +0 -24
  102. data/meta/masgn.rb +0 -7
  103. data/meta/match_current_line.rb +0 -14
  104. data/meta/next.rb +0 -10
  105. data/meta/nil.rb +0 -5
  106. data/meta/nthref.rb +0 -14
  107. data/meta/op_assgn.rb +0 -17
  108. data/meta/or.rb +0 -13
  109. data/meta/or_asgn.rb +0 -50
  110. data/meta/range.rb +0 -63
  111. data/meta/redo.rb +0 -5
  112. data/meta/regexp.rb +0 -80
  113. data/meta/regopt.rb +0 -10
  114. data/meta/rescue.rb +0 -84
  115. data/meta/return.rb +0 -16
  116. data/meta/sclass.rb +0 -12
  117. data/meta/self.rb +0 -7
  118. data/meta/send.rb +0 -600
  119. data/meta/str.rb +0 -7
  120. data/meta/super.rb +0 -27
  121. data/meta/sym.rb +0 -8
  122. data/meta/true.rb +0 -7
  123. data/meta/until.rb +0 -16
  124. data/meta/while.rb +0 -24
  125. data/meta/yield.rb +0 -9
  126. data/mutant-minitest.gemspec +0 -22
  127. data/mutant-rspec.gemspec +0 -22
  128. data/mutant.gemspec +0 -44
  129. data/mutant.sh +0 -12
  130. data/mutant.yml +0 -6
  131. data/spec/integration/mutant/corpus_spec.rb +0 -15
  132. data/spec/integration/mutant/isolation/fork_spec.rb +0 -28
  133. data/spec/integration/mutant/minitest_spec.rb +0 -11
  134. data/spec/integration/mutant/null_spec.rb +0 -16
  135. data/spec/integration/mutant/rspec_spec.rb +0 -15
  136. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +0 -9
  137. data/spec/integrations.yml +0 -63
  138. data/spec/shared/framework_integration_behavior.rb +0 -70
  139. data/spec/shared/method_matcher_behavior.rb +0 -47
  140. data/spec/spec_helper.rb +0 -90
  141. data/spec/support/corpus.rb +0 -318
  142. data/spec/support/file_system.rb +0 -62
  143. data/spec/support/ice_nine_config.rb +0 -10
  144. data/spec/support/ruby_vm.rb +0 -84
  145. data/spec/support/shared_context.rb +0 -169
  146. data/spec/support/xspec.rb +0 -183
  147. data/spec/unit/mutant/ast/find_metaclass_containing_spec.rb +0 -64
  148. data/spec/unit/mutant/ast/meta/optarg_spec.rb +0 -24
  149. data/spec/unit/mutant/ast/meta/send/proc_predicate_spec.rb +0 -30
  150. data/spec/unit/mutant/ast/meta/send/receiver_possible_top_level_const_predicate_spec.rb +0 -39
  151. data/spec/unit/mutant/ast/meta/send_spec.rb +0 -42
  152. data/spec/unit/mutant/ast/named_children_spec.rb +0 -89
  153. data/spec/unit/mutant/ast/sexp_spec.rb +0 -38
  154. data/spec/unit/mutant/ast_spec.rb +0 -57
  155. data/spec/unit/mutant/bootstrap_spec.rb +0 -216
  156. data/spec/unit/mutant/cli_spec.rb +0 -305
  157. data/spec/unit/mutant/clock_monotonic_spec.rb +0 -52
  158. data/spec/unit/mutant/config_spec.rb +0 -126
  159. data/spec/unit/mutant/context_spec.rb +0 -111
  160. data/spec/unit/mutant/env_spec.rb +0 -229
  161. data/spec/unit/mutant/expression/method_spec.rb +0 -62
  162. data/spec/unit/mutant/expression/methods_spec.rb +0 -66
  163. data/spec/unit/mutant/expression/namespace/exact_spec.rb +0 -28
  164. data/spec/unit/mutant/expression/namespace/recursive_spec.rb +0 -66
  165. data/spec/unit/mutant/expression/parser_spec.rb +0 -65
  166. data/spec/unit/mutant/expression_spec.rb +0 -45
  167. data/spec/unit/mutant/integration/rspec_spec.rb +0 -201
  168. data/spec/unit/mutant/integration_spec.rb +0 -150
  169. data/spec/unit/mutant/isolation/fork_spec.rb +0 -309
  170. data/spec/unit/mutant/isolation/none_spec.rb +0 -23
  171. data/spec/unit/mutant/isolation/result_spec.rb +0 -73
  172. data/spec/unit/mutant/license_spec.rb +0 -305
  173. data/spec/unit/mutant/loader_spec.rb +0 -79
  174. data/spec/unit/mutant/matcher/chain_spec.rb +0 -26
  175. data/spec/unit/mutant/matcher/compiler_spec.rb +0 -0
  176. data/spec/unit/mutant/matcher/config_spec.rb +0 -47
  177. data/spec/unit/mutant/matcher/filter_spec.rb +0 -22
  178. data/spec/unit/mutant/matcher/method/instance_spec.rb +0 -164
  179. data/spec/unit/mutant/matcher/method/metaclass_spec.rb +0 -108
  180. data/spec/unit/mutant/matcher/method/singleton_spec.rb +0 -90
  181. data/spec/unit/mutant/matcher/methods/instance_spec.rb +0 -54
  182. data/spec/unit/mutant/matcher/methods/metaclass_spec.rb +0 -62
  183. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +0 -51
  184. data/spec/unit/mutant/matcher/namespace_spec.rb +0 -39
  185. data/spec/unit/mutant/matcher/null_spec.rb +0 -12
  186. data/spec/unit/mutant/matcher/scope_spec.rb +0 -45
  187. data/spec/unit/mutant/matcher/static_spec.rb +0 -13
  188. data/spec/unit/mutant/matcher_spec.rb +0 -102
  189. data/spec/unit/mutant/meta/example/dsl_spec.rb +0 -108
  190. data/spec/unit/mutant/meta/example/verification_spec.rb +0 -154
  191. data/spec/unit/mutant/meta/example_spec.rb +0 -34
  192. data/spec/unit/mutant/mutation_spec.rb +0 -140
  193. data/spec/unit/mutant/mutator/node_spec.rb +0 -47
  194. data/spec/unit/mutant/mutator_spec.rb +0 -21
  195. data/spec/unit/mutant/parallel/driver_spec.rb +0 -126
  196. data/spec/unit/mutant/parallel/source/array_spec.rb +0 -57
  197. data/spec/unit/mutant/parallel/worker_spec.rb +0 -206
  198. data/spec/unit/mutant/parallel_spec.rb +0 -115
  199. data/spec/unit/mutant/parser_spec.rb +0 -26
  200. data/spec/unit/mutant/range_spec.rb +0 -141
  201. data/spec/unit/mutant/registry_spec.rb +0 -74
  202. data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +0 -17
  203. data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +0 -85
  204. data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +0 -45
  205. data/spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb +0 -132
  206. data/spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb +0 -25
  207. data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +0 -153
  208. data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +0 -45
  209. data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +0 -36
  210. data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +0 -44
  211. data/spec/unit/mutant/reporter/cli/printer/test_result_spec.rb +0 -16
  212. data/spec/unit/mutant/reporter/cli/printer_spec.rb +0 -163
  213. data/spec/unit/mutant/reporter/cli_spec.rb +0 -137
  214. data/spec/unit/mutant/reporter/null_spec.rb +0 -14
  215. data/spec/unit/mutant/reporter/sequence_spec.rb +0 -31
  216. data/spec/unit/mutant/repository/diff/ranges_spec.rb +0 -180
  217. data/spec/unit/mutant/repository/diff_spec.rb +0 -122
  218. data/spec/unit/mutant/repository/subject_filter_spec.rb +0 -30
  219. data/spec/unit/mutant/require_highjack_spec.rb +0 -73
  220. data/spec/unit/mutant/result/class_methods_spec.rb +0 -51
  221. data/spec/unit/mutant/result/env_spec.rb +0 -161
  222. data/spec/unit/mutant/result/mutation_spec.rb +0 -70
  223. data/spec/unit/mutant/result/subject_spec.rb +0 -111
  224. data/spec/unit/mutant/result/test_spec.rb +0 -14
  225. data/spec/unit/mutant/result_spec.rb +0 -33
  226. data/spec/unit/mutant/runner/sink_spec.rb +0 -174
  227. data/spec/unit/mutant/runner_spec.rb +0 -121
  228. data/spec/unit/mutant/selector/expression_spec.rb +0 -62
  229. data/spec/unit/mutant/selector/null_spec.rb +0 -17
  230. data/spec/unit/mutant/subject/method/instance_spec.rb +0 -276
  231. data/spec/unit/mutant/subject/method/metaclass_spec.rb +0 -63
  232. data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -61
  233. data/spec/unit/mutant/subject_spec.rb +0 -93
  234. data/spec/unit/mutant/transform/array_spec.rb +0 -92
  235. data/spec/unit/mutant/transform/bool_spec.rb +0 -63
  236. data/spec/unit/mutant/transform/error_spec.rb +0 -132
  237. data/spec/unit/mutant/transform/exception_spec.rb +0 -44
  238. data/spec/unit/mutant/transform/hash_spec.rb +0 -236
  239. data/spec/unit/mutant/transform/index_spec.rb +0 -92
  240. data/spec/unit/mutant/transform/named_spec.rb +0 -49
  241. data/spec/unit/mutant/transform/primitive_spec.rb +0 -56
  242. data/spec/unit/mutant/transform/sequence_spec.rb +0 -98
  243. data/spec/unit/mutant/util/one_spec.rb +0 -22
  244. data/spec/unit/mutant/warnings_spec.rb +0 -89
  245. data/spec/unit/mutant/world_spec.rb +0 -63
  246. data/spec/unit/mutant/zombifier_spec.rb +0 -122
  247. data/test_app/.rspec +0 -1
  248. data/test_app/Gemfile.minitest +0 -6
  249. data/test_app/Gemfile.rspec3.8 +0 -7
  250. data/test_app/lib/test_app.rb +0 -114
  251. data/test_app/lib/test_app/literal.rb +0 -35
  252. data/test_app/lib/test_app/metaclasses.rb +0 -108
  253. data/test_app/spec/spec_helper.rb +0 -9
  254. data/test_app/spec/unit/test_app/literal_spec.rb +0 -20
  255. data/test_app/test/unit/test_app/literal_test.rb +0 -16
@@ -7,6 +7,7 @@ module Mutant
7
7
  include Adamantium, Anima.new(
8
8
  :ignore_expressions,
9
9
  :match_expressions,
10
+ :start_expressions,
10
11
  :subject_filters
11
12
  )
12
13
 
@@ -18,6 +19,7 @@ module Mutant
18
19
  PRESENTATIONS = IceNine.deep_freeze(
19
20
  ignore_expressions: :syntax,
20
21
  match_expressions: :syntax,
22
+ start_expressions: :syntax,
21
23
  subject_filters: :inspect
22
24
  )
23
25
  private_constant(*constants(false))
@@ -3,7 +3,19 @@
3
3
  module Mutant
4
4
  module Meta
5
5
  class Example
6
- include Adamantium, Anima.new(:file, :node, :types, :expected)
6
+ include Adamantium
7
+ include Anima.new(
8
+ :expected,
9
+ :file,
10
+ :lvars,
11
+ :node,
12
+ :original_source,
13
+ :types
14
+ )
15
+
16
+ class Expected
17
+ include Anima.new(:original_source, :node)
18
+ end
7
19
 
8
20
  # Verification instance for example
9
21
  #
@@ -13,13 +25,13 @@ module Mutant
13
25
  end
14
26
  memoize :verification
15
27
 
16
- # Normalized source
28
+ # Original source as generated by unparser
17
29
  #
18
30
  # @return [String]
19
- def source
31
+ def original_source_generated
20
32
  Unparser.unparse(node)
21
33
  end
22
- memoize :source
34
+ memoize :original_source_generated
23
35
 
24
36
  # Generated mutations on example source
25
37
  #
@@ -25,10 +25,11 @@ module Mutant
25
25
  #
26
26
  # @return [undefined]
27
27
  def initialize(file, types)
28
+ @expected = []
28
29
  @file = file
30
+ @lvars = []
31
+ @source = nil
29
32
  @types = types
30
- @node = nil
31
- @expected = []
32
33
  end
33
34
 
34
35
  # Example captured by DSL
@@ -38,28 +39,41 @@ module Mutant
38
39
  # @raise [RuntimeError]
39
40
  # in case example cannot be build
40
41
  def example
41
- fail 'source not defined' unless @node
42
+ fail 'source not defined' unless @source
42
43
  Example.new(
43
- file: @file,
44
- node: @node,
45
- types: @types,
46
- expected: @expected
44
+ expected: @expected,
45
+ file: @file,
46
+ lvars: @lvars,
47
+ node: @node,
48
+ original_source: @source,
49
+ types: @types
47
50
  )
48
51
  end
49
52
 
53
+ # Declare a local variable
54
+ #
55
+ # @param [Symbol]
56
+ def declare_lvar(name)
57
+ @lvars << name
58
+ end
59
+
50
60
  private
51
61
 
52
62
  def source(input)
53
- fail 'source already defined' if @node
54
- @node = node(input)
63
+ fail 'source already defined' if @source
64
+
65
+ @source = input
66
+ @node = node(input)
55
67
  end
56
68
 
57
69
  def mutation(input)
58
- node = node(input)
59
- if @expected.include?(node)
70
+ expected = Expected.new(original_source: input, node: node(input))
71
+
72
+ if @expected.include?(expected)
60
73
  fail "Mutation for input: #{input.inspect} is already expected"
61
74
  end
62
- @expected << node
75
+
76
+ @expected << expected
63
77
  end
64
78
 
65
79
  def singleton_mutations
@@ -70,14 +84,17 @@ module Mutant
70
84
  def node(input)
71
85
  case input
72
86
  when String
73
- Unparser::Preprocessor.run(Unparser.parse(input))
74
- when ::Parser::AST::Node
75
- input
87
+ parser.parse(Unparser.buffer(input))
76
88
  else
77
- fail "Cannot coerce to node: #{input.inspect}"
89
+ fail "Unsupported input: #{input.inspect}"
78
90
  end
79
91
  end
80
92
 
93
+ def parser
94
+ Unparser.parser.tap do |parser|
95
+ @lvars.each(&parser.static_env.public_method(:declare))
96
+ end
97
+ end
81
98
  end # DSL
82
99
  end # Example
83
100
  end # Meta
@@ -11,54 +11,96 @@ module Mutant
11
11
  #
12
12
  # @return [Boolean]
13
13
  def success?
14
- [missing, unexpected, no_diffs, invalid_syntax].all?(&:empty?)
14
+ [
15
+ original_verification,
16
+ invalid,
17
+ missing,
18
+ no_diffs,
19
+ unexpected
20
+ ].all?(&:empty?)
15
21
  end
16
22
  memoize :success?
17
23
 
18
- # Error report
19
- #
20
- # @return [String]
21
24
  def error_report
22
- fail 'no error report on successful validation' if success?
23
-
24
- YAML.dump(
25
- 'file' => example.file,
26
- 'original_ast' => example.node.inspect,
27
- 'original_source' => example.source,
28
- 'missing' => format_mutations(missing),
29
- 'unexpected' => format_mutations(unexpected),
30
- 'invalid_syntax' => format_mutations(invalid_syntax),
31
- 'no_diff' => no_diff_report
32
- )
25
+ reports.join("\n")
33
26
  end
34
- memoize :error_report
35
27
 
36
28
  private
37
29
 
30
+ def reports
31
+ reports = [example.file]
32
+ reports.concat(original)
33
+ reports.concat(original_verification)
34
+ reports.concat(make_report('Missing mutations:', missing))
35
+ reports.concat(make_report('Unexpected mutations:', unexpected))
36
+ reports.concat(make_report('No-Diff mutations:', no_diffs))
37
+ reports.concat(invalid)
38
+ end
39
+
40
+ def make_report(label, mutations)
41
+ if mutations.any?
42
+ [label, mutations.map(&method(:report_mutation))]
43
+ else
44
+ []
45
+ end
46
+ end
47
+
48
+ def report_mutation(mutation)
49
+ [
50
+ mutation.node.inspect,
51
+ mutation.source
52
+ ]
53
+ end
54
+
55
+ def original
56
+ [
57
+ 'Original:',
58
+ example.node,
59
+ example.original_source
60
+ ]
61
+ end
62
+
63
+ def original_verification
64
+ validation = Unparser::Validation.from_string(example.original_source)
65
+ if validation.success?
66
+ []
67
+ else
68
+ [
69
+ prefix('[original]', validation.report)
70
+ ]
71
+ end
72
+ end
73
+
74
+ def prefix(prefix, string)
75
+ string.each_line.map do |line|
76
+ "#{prefix} #{line}"
77
+ end.join
78
+ end
79
+
80
+ def invalid
81
+ mutations.each_with_object([]) do |mutation, aggregate|
82
+ validation = Unparser::Validation.from_node(mutation.node)
83
+ aggregate << prefix('[invalid-mutation]', validation.report) unless validation.success?
84
+ end
85
+ end
86
+ memoize :invalid
87
+
38
88
  def unexpected
39
89
  mutations.reject do |mutation|
40
- example.expected.include?(mutation.node)
90
+ example.expected.any? { |expected| expected.node.eql?(mutation.node) }
41
91
  end
42
92
  end
43
93
  memoize :unexpected
44
94
 
45
95
  def missing
46
- (example.expected - mutations.map(&:node)).map do |node|
47
- Mutation::Evil.new(self, node)
96
+ (example.expected.map(&:node) - mutations.map(&:node)).map do |node|
97
+ Mutation::Evil.new(nil, node)
48
98
  end
49
99
  end
50
100
  memoize :missing
51
101
 
52
- def invalid_syntax
53
- mutations.reject do |mutation|
54
- ::Parser::CurrentRuby.parse(mutation.source)
55
- rescue ::Parser::SyntaxError # rubocop:disable Lint/SuppressedException
56
- end
57
- end
58
- memoize :invalid_syntax
59
-
60
102
  def no_diffs
61
- mutations.select { |mutation| mutation.source.eql?(example.source) }
103
+ mutations.select { |mutation| mutation.source.eql?(example.original_source_generated) }
62
104
  end
63
105
  memoize :no_diffs
64
106
 
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest'
4
+
5
+ module Mutant
6
+ module Minitest
7
+ module Coverage
8
+ # Setup coverage declaration for current class
9
+ #
10
+ # @param [String]
11
+ #
12
+ # @example
13
+ #
14
+ # class MyTest < MiniTest::Test
15
+ # cover 'MyCode*'
16
+ #
17
+ # def test_some_stuff
18
+ # end
19
+ # end
20
+ #
21
+ # @api public
22
+ def cover(expression)
23
+ @cover_expressions = Set.new unless defined?(@cover_expressions)
24
+
25
+ @cover_expressions << expression
26
+ end
27
+
28
+ # Effective coverage expression
29
+ #
30
+ # @return [Set<String>]
31
+ #
32
+ # @api private
33
+ def resolve_cover_expressions
34
+ return @cover_expressions if defined?(@cover_expressions)
35
+
36
+ try_superclass_cover_expressions
37
+ end
38
+
39
+ private
40
+
41
+ def try_superclass_cover_expressions
42
+ return if superclass.equal?(::Minitest::Runnable)
43
+
44
+ superclass.resolve_cover_expressions
45
+ end
46
+
47
+ end # Coverage
48
+ end # Minitest
49
+ end # Mutant
50
+
51
+ Minitest::Test.extend(Mutant::Minitest::Coverage)
@@ -75,7 +75,7 @@ module Mutant
75
75
  end
76
76
 
77
77
  def emit_nil
78
- emit(N_NIL) unless left_assignment?
78
+ emit(N_NIL) unless left_op_assignment?
79
79
  end
80
80
 
81
81
  def parent_node
@@ -86,7 +86,7 @@ module Mutant
86
86
  parent_node&.type
87
87
  end
88
88
 
89
- def left_assignment?
89
+ def left_op_assignment?
90
90
  AST::Types::OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
91
91
  end
92
92
 
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ class Mutator
5
+ class Node
6
+ class BlockPass < self
7
+
8
+ handle(:block_pass)
9
+
10
+ children :argument
11
+
12
+ private
13
+
14
+ def dispatch
15
+ emit_argument_mutations
16
+ emit_symbol_to_proc_mutations
17
+ end
18
+
19
+ def emit_symbol_to_proc_mutations
20
+ return unless n_sym?(argument)
21
+
22
+ Send::SELECTOR_REPLACEMENTS.fetch(*argument, EMPTY_ARRAY).each do |method|
23
+ emit_argument(s(:sym, method))
24
+ end
25
+ end
26
+ end # Block
27
+ end # Node
28
+ end # Mutator
29
+ end # Mutant
@@ -3,17 +3,19 @@
3
3
  module Mutant
4
4
  class Mutator
5
5
  class Node
6
+ # Mutator for dynamic literals
7
+ class DynamicLiteral < self
6
8
 
7
- # Dstr mutator
8
- class Dstr < Generic
9
-
10
- handle(:dstr)
9
+ handle(:dstr, :dsym)
11
10
 
12
11
  private
13
12
 
14
13
  def dispatch
15
- super()
16
14
  emit_singletons
15
+
16
+ children.each_index do |index|
17
+ mutate_child(index, &method(:n_begin?))
18
+ end
17
19
  end
18
20
 
19
21
  end # Dstr
@@ -24,7 +24,7 @@ module Mutant
24
24
  end
25
25
 
26
26
  def emit_send_forms
27
- return if left_assignment?
27
+ return if left_op_assignment?
28
28
 
29
29
  SEND_REPLACEMENTS.each do |selector|
30
30
  emit(s(:send, receiver, selector, *indices))
@@ -43,7 +43,7 @@ module Mutant
43
43
 
44
44
  def mutate_indices
45
45
  children_indices(index_range).each do |index|
46
- emit_propagation(children.fetch(index)) unless left_assignment?
46
+ emit_propagation(children.fetch(index)) unless left_op_assignment?
47
47
  delete_child(index)
48
48
  mutate_child(index)
49
49
  end
@@ -77,7 +77,7 @@ module Mutant
77
77
  def dispatch
78
78
  super()
79
79
 
80
- return if left_assignment?
80
+ return if left_op_assignment?
81
81
 
82
82
  emit_index_read
83
83
  emit(children.last)
@@ -89,7 +89,7 @@ module Mutant
89
89
  end
90
90
 
91
91
  def index_range
92
- if left_assignment?
92
+ if left_op_assignment?
93
93
  NO_VALUE_RANGE
94
94
  else
95
95
  REGULAR_RANGE
@@ -18,7 +18,7 @@ module Mutant
18
18
  }
19
19
 
20
20
  MAP = IceNine.deep_freeze(
21
- Hash[map.map { |type, prefix| [type, [prefix, /^#{::Regexp.escape(prefix)}/]] }]
21
+ map.transform_values { |prefix| [prefix, /^#{::Regexp.escape(prefix)}/] }
22
22
  )
23
23
 
24
24
  handle(*MAP.keys)
@@ -7,7 +7,7 @@ module Mutant
7
7
  # Mutation emitter to handle noop nodes
8
8
  class Noop < self
9
9
 
10
- handle(:__ENCODING__, :block_pass, :cbase, :lambda)
10
+ handle(:__ENCODING__, :cbase, :lambda)
11
11
 
12
12
  private
13
13
 
@@ -15,10 +15,24 @@ module Mutant
15
15
 
16
16
  def dispatch
17
17
  emit_singletons
18
+
19
+ left_mutations
20
+
21
+ emit_right_mutations
22
+ end
23
+
24
+ def left_mutations
18
25
  emit_left_mutations do |node|
19
26
  !n_self?(node)
20
27
  end
21
- emit_right_mutations
28
+
29
+ emit_left_promotion if n_send?(left)
30
+ end
31
+
32
+ def emit_left_promotion
33
+ receiver = left.children.first
34
+
35
+ emit_left(s(:ivasgn, *receiver)) if n_ivar?(receiver)
22
36
  end
23
37
 
24
38
  end # OpAsgn