mutest 0.0.1 → 0.0.2

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 (401) hide show
  1. checksums.yaml +4 -4
  2. data/.buildkite/hooks/pre-command +3 -0
  3. data/.buildkite/pipeline.yml +51 -0
  4. data/.gitattributes +1 -0
  5. data/.gitignore +38 -0
  6. data/.rspec +5 -0
  7. data/Gemfile +13 -0
  8. data/Gemfile.lock +216 -0
  9. data/Gemfile.shared +3 -0
  10. data/LICENSE +21 -0
  11. data/README.md +8 -0
  12. data/Rakefile +24 -0
  13. data/bin/mutest +39 -0
  14. data/build/Dockerfile +71 -0
  15. data/build/docker-bootstrap.sh +85 -0
  16. data/build/docker-exec +29 -0
  17. data/build/make-docker +3 -0
  18. data/build/ruby_matrix +1 -0
  19. data/build/run +5 -0
  20. data/build/strict-mode.sh +16 -0
  21. data/circle.yml +7 -0
  22. data/config/devtools.yml +2 -0
  23. data/config/flay.yml +3 -0
  24. data/config/flog.yml +2 -0
  25. data/config/reek.yml +137 -0
  26. data/config/rubocop.yml +395 -0
  27. data/config/triage.yml +2 -0
  28. data/config/yardstick.yml +2 -0
  29. data/lib/mutest.rb +243 -0
  30. data/lib/mutest/actor.rb +52 -0
  31. data/lib/mutest/actor/env.rb +28 -0
  32. data/lib/mutest/actor/mailbox.rb +31 -0
  33. data/lib/mutest/actor/receiver.rb +39 -0
  34. data/lib/mutest/actor/sender.rb +22 -0
  35. data/lib/mutest/ast.rb +44 -0
  36. data/lib/mutest/ast/meta.rb +7 -0
  37. data/lib/mutest/ast/meta/const.rb +22 -0
  38. data/lib/mutest/ast/meta/optarg.rb +24 -0
  39. data/lib/mutest/ast/meta/resbody.rb +15 -0
  40. data/lib/mutest/ast/meta/restarg.rb +15 -0
  41. data/lib/mutest/ast/meta/send.rb +89 -0
  42. data/lib/mutest/ast/meta/symbol.rb +15 -0
  43. data/lib/mutest/ast/named_children.rb +86 -0
  44. data/lib/mutest/ast/node_predicates.rb +17 -0
  45. data/lib/mutest/ast/nodes.rb +22 -0
  46. data/lib/mutest/ast/regexp.rb +50 -0
  47. data/lib/mutest/ast/regexp/transformer.rb +184 -0
  48. data/lib/mutest/ast/regexp/transformer/alternative.rb +39 -0
  49. data/lib/mutest/ast/regexp/transformer/character_set.rb +46 -0
  50. data/lib/mutest/ast/regexp/transformer/direct.rb +101 -0
  51. data/lib/mutest/ast/regexp/transformer/options_group.rb +65 -0
  52. data/lib/mutest/ast/regexp/transformer/quantifier.rb +112 -0
  53. data/lib/mutest/ast/regexp/transformer/recursive.rb +50 -0
  54. data/lib/mutest/ast/regexp/transformer/root.rb +28 -0
  55. data/lib/mutest/ast/regexp/transformer/text.rb +55 -0
  56. data/lib/mutest/ast/sexp.rb +26 -0
  57. data/lib/mutest/ast/types.rb +140 -0
  58. data/lib/mutest/cli.rb +196 -0
  59. data/lib/mutest/color.rb +39 -0
  60. data/lib/mutest/config.rb +28 -0
  61. data/lib/mutest/context.rb +98 -0
  62. data/lib/mutest/diff.rb +111 -0
  63. data/lib/mutest/env.rb +59 -0
  64. data/lib/mutest/env/bootstrap.rb +159 -0
  65. data/lib/mutest/expression.rb +55 -0
  66. data/lib/mutest/expression/method.rb +54 -0
  67. data/lib/mutest/expression/methods.rb +58 -0
  68. data/lib/mutest/expression/namespace.rb +75 -0
  69. data/lib/mutest/expression/parser.rb +64 -0
  70. data/lib/mutest/integration.rb +75 -0
  71. data/lib/mutest/isolation.rb +11 -0
  72. data/lib/mutest/isolation/fork.rb +72 -0
  73. data/lib/mutest/isolation/none.rb +23 -0
  74. data/lib/mutest/loader.rb +27 -0
  75. data/lib/mutest/matcher.rb +14 -0
  76. data/lib/mutest/matcher/chain.rb +19 -0
  77. data/lib/mutest/matcher/compiler.rb +55 -0
  78. data/lib/mutest/matcher/config.rb +81 -0
  79. data/lib/mutest/matcher/filter.rb +19 -0
  80. data/lib/mutest/matcher/method.rb +138 -0
  81. data/lib/mutest/matcher/method/instance.rb +63 -0
  82. data/lib/mutest/matcher/method/singleton.rb +88 -0
  83. data/lib/mutest/matcher/methods.rb +109 -0
  84. data/lib/mutest/matcher/namespace.rb +41 -0
  85. data/lib/mutest/matcher/null.rb +17 -0
  86. data/lib/mutest/matcher/scope.rb +38 -0
  87. data/lib/mutest/matcher/static.rb +15 -0
  88. data/lib/mutest/meta.rb +33 -0
  89. data/lib/mutest/meta/example.rb +32 -0
  90. data/lib/mutest/meta/example/dsl.rb +107 -0
  91. data/lib/mutest/meta/example/verification.rb +85 -0
  92. data/lib/mutest/mutation.rb +101 -0
  93. data/lib/mutest/mutator.rb +117 -0
  94. data/lib/mutest/mutator/node.rb +166 -0
  95. data/lib/mutest/mutator/node/and_asgn.rb +25 -0
  96. data/lib/mutest/mutator/node/argument.rb +68 -0
  97. data/lib/mutest/mutator/node/arguments.rb +90 -0
  98. data/lib/mutest/mutator/node/begin.rb +21 -0
  99. data/lib/mutest/mutator/node/binary.rb +64 -0
  100. data/lib/mutest/mutator/node/block.rb +51 -0
  101. data/lib/mutest/mutator/node/break.rb +21 -0
  102. data/lib/mutest/mutator/node/case.rb +47 -0
  103. data/lib/mutest/mutator/node/class.rb +21 -0
  104. data/lib/mutest/mutator/node/conditional_loop.rb +25 -0
  105. data/lib/mutest/mutator/node/const.rb +23 -0
  106. data/lib/mutest/mutator/node/define.rb +79 -0
  107. data/lib/mutest/mutator/node/defined.rb +24 -0
  108. data/lib/mutest/mutator/node/dstr.rb +20 -0
  109. data/lib/mutest/mutator/node/dsym.rb +20 -0
  110. data/lib/mutest/mutator/node/generic.rb +77 -0
  111. data/lib/mutest/mutator/node/if.rb +57 -0
  112. data/lib/mutest/mutator/node/kwbegin.rb +20 -0
  113. data/lib/mutest/mutator/node/literal.rb +19 -0
  114. data/lib/mutest/mutator/node/literal/array.rb +37 -0
  115. data/lib/mutest/mutator/node/literal/boolean.rb +27 -0
  116. data/lib/mutest/mutator/node/literal/fixnum.rb +36 -0
  117. data/lib/mutest/mutator/node/literal/float.rb +45 -0
  118. data/lib/mutest/mutator/node/literal/hash.rb +52 -0
  119. data/lib/mutest/mutator/node/literal/nil.rb +20 -0
  120. data/lib/mutest/mutator/node/literal/range.rb +38 -0
  121. data/lib/mutest/mutator/node/literal/regex.rb +76 -0
  122. data/lib/mutest/mutator/node/literal/string.rb +21 -0
  123. data/lib/mutest/mutator/node/literal/symbol.rb +26 -0
  124. data/lib/mutest/mutator/node/masgn.rb +21 -0
  125. data/lib/mutest/mutator/node/match_current_line.rb +22 -0
  126. data/lib/mutest/mutator/node/mlhs.rb +21 -0
  127. data/lib/mutest/mutator/node/named_value/access.rb +54 -0
  128. data/lib/mutest/mutator/node/named_value/constant_assignment.rb +42 -0
  129. data/lib/mutest/mutator/node/named_value/variable_assignment.rb +47 -0
  130. data/lib/mutest/mutator/node/next.rb +22 -0
  131. data/lib/mutest/mutator/node/noop.rb +19 -0
  132. data/lib/mutest/mutator/node/nthref.rb +22 -0
  133. data/lib/mutest/mutator/node/op_asgn.rb +50 -0
  134. data/lib/mutest/mutator/node/or_asgn.rb +26 -0
  135. data/lib/mutest/mutator/node/regexp.rb +33 -0
  136. data/lib/mutest/mutator/node/regexp/alternation_meta.rb +21 -0
  137. data/lib/mutest/mutator/node/regexp/capture_group.rb +26 -0
  138. data/lib/mutest/mutator/node/regexp/character_type.rb +29 -0
  139. data/lib/mutest/mutator/node/regexp/end_of_line_anchor.rb +21 -0
  140. data/lib/mutest/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor.rb +21 -0
  141. data/lib/mutest/mutator/node/regexp/one_or_more.rb +29 -0
  142. data/lib/mutest/mutator/node/regexp/zero_or_more.rb +29 -0
  143. data/lib/mutest/mutator/node/regopt.rb +28 -0
  144. data/lib/mutest/mutator/node/resbody.rb +34 -0
  145. data/lib/mutest/mutator/node/rescue.rb +69 -0
  146. data/lib/mutest/mutator/node/return.rb +24 -0
  147. data/lib/mutest/mutator/node/send.rb +270 -0
  148. data/lib/mutest/mutator/node/send/attribute_assignment.rb +39 -0
  149. data/lib/mutest/mutator/node/send/binary.rb +45 -0
  150. data/lib/mutest/mutator/node/send/conditional.rb +21 -0
  151. data/lib/mutest/mutator/node/send/index.rb +47 -0
  152. data/lib/mutest/mutator/node/splat.rb +23 -0
  153. data/lib/mutest/mutator/node/super.rb +24 -0
  154. data/lib/mutest/mutator/node/when.rb +60 -0
  155. data/lib/mutest/mutator/node/yield.rb +21 -0
  156. data/lib/mutest/mutator/node/zsuper.rb +20 -0
  157. data/lib/mutest/mutator/util.rb +11 -0
  158. data/lib/mutest/mutator/util/array.rb +42 -0
  159. data/lib/mutest/mutator/util/symbol.rb +19 -0
  160. data/lib/mutest/parallel.rb +89 -0
  161. data/lib/mutest/parallel/master.rb +181 -0
  162. data/lib/mutest/parallel/source.rb +57 -0
  163. data/lib/mutest/parallel/worker.rb +76 -0
  164. data/lib/mutest/parser.rb +22 -0
  165. data/lib/mutest/registry.rb +43 -0
  166. data/lib/mutest/reporter.rb +39 -0
  167. data/lib/mutest/reporter/cli.rb +87 -0
  168. data/lib/mutest/reporter/cli/format.rb +135 -0
  169. data/lib/mutest/reporter/cli/printer.rb +124 -0
  170. data/lib/mutest/reporter/cli/printer/config.rb +24 -0
  171. data/lib/mutest/reporter/cli/printer/env_progress.rb +76 -0
  172. data/lib/mutest/reporter/cli/printer/env_result.rb +20 -0
  173. data/lib/mutest/reporter/cli/printer/mutation_progress_result.rb +31 -0
  174. data/lib/mutest/reporter/cli/printer/mutation_result.rb +127 -0
  175. data/lib/mutest/reporter/cli/printer/status.rb +49 -0
  176. data/lib/mutest/reporter/cli/printer/status_progressive.rb +46 -0
  177. data/lib/mutest/reporter/cli/printer/subject_progress.rb +65 -0
  178. data/lib/mutest/reporter/cli/printer/subject_result.rb +23 -0
  179. data/lib/mutest/reporter/cli/printer/test_result.rb +28 -0
  180. data/lib/mutest/reporter/cli/tput.rb +43 -0
  181. data/lib/mutest/reporter/null.rb +14 -0
  182. data/lib/mutest/reporter/sequence.rb +24 -0
  183. data/lib/mutest/repository.rb +80 -0
  184. data/lib/mutest/require_highjack.rb +24 -0
  185. data/lib/mutest/result.rb +212 -0
  186. data/lib/mutest/runner.rb +81 -0
  187. data/lib/mutest/runner/sink.rb +63 -0
  188. data/lib/mutest/scope.rb +6 -0
  189. data/lib/mutest/selector.rb +13 -0
  190. data/lib/mutest/selector/expression.rb +25 -0
  191. data/lib/mutest/source_file.rb +47 -0
  192. data/lib/mutest/subject.rb +94 -0
  193. data/lib/mutest/subject/method.rb +42 -0
  194. data/lib/mutest/subject/method/instance.rb +43 -0
  195. data/lib/mutest/subject/method/singleton.rb +19 -0
  196. data/lib/mutest/test.rb +14 -0
  197. data/lib/mutest/util.rb +18 -0
  198. data/lib/mutest/version.rb +4 -0
  199. data/lib/mutest/warning_filter.rb +58 -0
  200. data/lib/mutest/zombifier.rb +119 -0
  201. data/meta/and.rb +13 -0
  202. data/meta/and_asgn.rb +12 -0
  203. data/meta/array.rb +28 -0
  204. data/meta/begin.rb +19 -0
  205. data/meta/block.rb +104 -0
  206. data/meta/block_pass.rb +6 -0
  207. data/meta/blockarg.rb +8 -0
  208. data/meta/break.rb +8 -0
  209. data/meta/case.rb +221 -0
  210. data/meta/casgn.rb +26 -0
  211. data/meta/cbase.rb +6 -0
  212. data/meta/class.rb +10 -0
  213. data/meta/const.rb +15 -0
  214. data/meta/csend.rb +8 -0
  215. data/meta/cvar.rb +5 -0
  216. data/meta/cvasgn.rb +8 -0
  217. data/meta/date.rb +57 -0
  218. data/meta/def.rb +260 -0
  219. data/meta/defined.rb +7 -0
  220. data/meta/dstr.rb +11 -0
  221. data/meta/dsym.rb +12 -0
  222. data/meta/ensure.rb +7 -0
  223. data/meta/false.rb +6 -0
  224. data/meta/float.rb +35 -0
  225. data/meta/gvar.rb +5 -0
  226. data/meta/gvasgn.rb +8 -0
  227. data/meta/hash.rb +22 -0
  228. data/meta/if.rb +75 -0
  229. data/meta/int.rb +16 -0
  230. data/meta/ivar.rb +6 -0
  231. data/meta/ivasgn.rb +21 -0
  232. data/meta/kwarg.rb +8 -0
  233. data/meta/kwbegin.rb +7 -0
  234. data/meta/kwoptarg.rb +11 -0
  235. data/meta/kwrestarg.rb +17 -0
  236. data/meta/lvar.rb +14 -0
  237. data/meta/lvasgn.rb +8 -0
  238. data/meta/masgn.rb +5 -0
  239. data/meta/match_current_line.rb +13 -0
  240. data/meta/next.rb +9 -0
  241. data/meta/nil.rb +3 -0
  242. data/meta/nthref.rb +12 -0
  243. data/meta/op_assgn.rb +39 -0
  244. data/meta/or.rb +13 -0
  245. data/meta/or_asgn.rb +48 -0
  246. data/meta/range.rb +37 -0
  247. data/meta/redo.rb +3 -0
  248. data/meta/regexp.rb +84 -0
  249. data/meta/regexp/character_types.rb +20 -0
  250. data/meta/regexp/regexp_alternation_meta.rb +11 -0
  251. data/meta/regexp/regexp_bol_anchor.rb +8 -0
  252. data/meta/regexp/regexp_bos_anchor.rb +16 -0
  253. data/meta/regexp/regexp_capture_group.rb +17 -0
  254. data/meta/regexp/regexp_eol_anchor.rb +8 -0
  255. data/meta/regexp/regexp_eos_anchor.rb +6 -0
  256. data/meta/regexp/regexp_eos_ob_eol_anchor.rb +8 -0
  257. data/meta/regexp/regexp_one_or_more.rb +32 -0
  258. data/meta/regexp/regexp_root_expression.rb +8 -0
  259. data/meta/regexp/regexp_zero_or_more.rb +32 -0
  260. data/meta/regopt.rb +8 -0
  261. data/meta/rescue.rb +87 -0
  262. data/meta/restarg.rb +9 -0
  263. data/meta/return.rb +14 -0
  264. data/meta/self.rb +5 -0
  265. data/meta/send.rb +849 -0
  266. data/meta/str.rb +5 -0
  267. data/meta/super.rb +25 -0
  268. data/meta/sym.rb +6 -0
  269. data/meta/true.rb +6 -0
  270. data/meta/until.rb +15 -0
  271. data/meta/while.rb +24 -0
  272. data/meta/yield.rb +8 -0
  273. data/mutest-rspec.gemspec +22 -0
  274. data/mutest.gemspec +45 -0
  275. data/spec/integration/mutest/corpus_spec.rb +18 -0
  276. data/spec/integration/mutest/isolation/fork_spec.rb +8 -0
  277. data/spec/integration/mutest/null_spec.rb +13 -0
  278. data/spec/integration/mutest/rspec_spec.rb +11 -0
  279. data/spec/integration/mutest/test_mutator_handles_types_spec.rb +7 -0
  280. data/spec/integrations.yml +32 -0
  281. data/spec/rcov.opts +7 -0
  282. data/spec/shared/framework_integration_behavior.rb +44 -0
  283. data/spec/shared/method_matcher_behavior.rb +49 -0
  284. data/spec/spec_helper.rb +70 -0
  285. data/spec/support/compress_helper.rb +9 -0
  286. data/spec/support/corpus.rb +331 -0
  287. data/spec/support/fake_actor.rb +107 -0
  288. data/spec/support/file_system.rb +60 -0
  289. data/spec/support/ice_nine_config.rb +8 -0
  290. data/spec/support/rb_bug.rb +15 -0
  291. data/spec/support/ruby_vm.rb +82 -0
  292. data/spec/support/shared_context.rb +125 -0
  293. data/spec/support/test_app.rb +5 -0
  294. data/spec/support/warning.rb +73 -0
  295. data/spec/support/warnings.yml +5 -0
  296. data/spec/support/xspec.rb +175 -0
  297. data/spec/unit/mutest/actor/binding_spec.rb +32 -0
  298. data/spec/unit/mutest/actor/env_spec.rb +29 -0
  299. data/spec/unit/mutest/actor/mailbox_spec.rb +25 -0
  300. data/spec/unit/mutest/actor/message_spec.rb +22 -0
  301. data/spec/unit/mutest/actor/receiver_spec.rb +56 -0
  302. data/spec/unit/mutest/actor/sender_spec.rb +22 -0
  303. data/spec/unit/mutest/ast/meta/optarg_spec.rb +21 -0
  304. data/spec/unit/mutest/ast/meta/send/proc_predicate_spec.rb +28 -0
  305. data/spec/unit/mutest/ast/meta/send/receiver_possible_top_level_const_predicate_spec.rb +37 -0
  306. data/spec/unit/mutest/ast/meta/send_spec.rb +42 -0
  307. data/spec/unit/mutest/ast/named_children_spec.rb +87 -0
  308. data/spec/unit/mutest/ast/regexp/parse_spec.rb +5 -0
  309. data/spec/unit/mutest/ast/regexp/supported_predicate_spec.rb +14 -0
  310. data/spec/unit/mutest/ast/regexp/transformer/lookup_table/table_spec.rb +19 -0
  311. data/spec/unit/mutest/ast/regexp/transformer/lookup_table_spec.rb +33 -0
  312. data/spec/unit/mutest/ast/regexp/transformer_spec.rb +19 -0
  313. data/spec/unit/mutest/ast/regexp_spec.rb +625 -0
  314. data/spec/unit/mutest/ast/sexp_spec.rb +36 -0
  315. data/spec/unit/mutest/ast_spec.rb +55 -0
  316. data/spec/unit/mutest/cli_spec.rb +247 -0
  317. data/spec/unit/mutest/context_spec.rb +141 -0
  318. data/spec/unit/mutest/diff_spec.rb +185 -0
  319. data/spec/unit/mutest/env/bootstrap_spec.rb +188 -0
  320. data/spec/unit/mutest/env_spec.rb +100 -0
  321. data/spec/unit/mutest/expression/method_spec.rb +44 -0
  322. data/spec/unit/mutest/expression/methods_spec.rb +59 -0
  323. data/spec/unit/mutest/expression/namespace/exact_spec.rb +26 -0
  324. data/spec/unit/mutest/expression/namespace/recursive_spec.rb +64 -0
  325. data/spec/unit/mutest/expression/parser_spec.rb +67 -0
  326. data/spec/unit/mutest/expression_spec.rb +45 -0
  327. data/spec/unit/mutest/integration/null_spec.rb +28 -0
  328. data/spec/unit/mutest/integration/rspec_spec.rb +197 -0
  329. data/spec/unit/mutest/integration_spec.rb +26 -0
  330. data/spec/unit/mutest/isolation/fork_spec.rb +155 -0
  331. data/spec/unit/mutest/isolation/none_spec.rb +16 -0
  332. data/spec/unit/mutest/loader_spec.rb +42 -0
  333. data/spec/unit/mutest/matcher/chain_spec.rb +24 -0
  334. data/spec/unit/mutest/matcher/compiler/subject_prefix_spec.rb +24 -0
  335. data/spec/unit/mutest/matcher/compiler_spec.rb +76 -0
  336. data/spec/unit/mutest/matcher/config_spec.rb +45 -0
  337. data/spec/unit/mutest/matcher/filter_spec.rb +20 -0
  338. data/spec/unit/mutest/matcher/method/instance_spec.rb +125 -0
  339. data/spec/unit/mutest/matcher/method/singleton_spec.rb +85 -0
  340. data/spec/unit/mutest/matcher/methods/instance_spec.rb +58 -0
  341. data/spec/unit/mutest/matcher/methods/singleton_spec.rb +54 -0
  342. data/spec/unit/mutest/matcher/namespace_spec.rb +35 -0
  343. data/spec/unit/mutest/matcher/null_spec.rb +10 -0
  344. data/spec/unit/mutest/matcher/scope_spec.rb +33 -0
  345. data/spec/unit/mutest/matcher/static_spec.rb +11 -0
  346. data/spec/unit/mutest/meta/example/dsl_spec.rb +123 -0
  347. data/spec/unit/mutest/meta/example/verification_spec.rb +120 -0
  348. data/spec/unit/mutest/meta/example_spec.rb +32 -0
  349. data/spec/unit/mutest/mutation_spec.rb +129 -0
  350. data/spec/unit/mutest/mutator/node_spec.rb +43 -0
  351. data/spec/unit/mutest/mutator_spec.rb +30 -0
  352. data/spec/unit/mutest/parallel/driver_spec.rb +26 -0
  353. data/spec/unit/mutest/parallel/master_spec.rb +335 -0
  354. data/spec/unit/mutest/parallel/source/array_spec.rb +47 -0
  355. data/spec/unit/mutest/parallel/worker_spec.rb +65 -0
  356. data/spec/unit/mutest/parallel_spec.rb +16 -0
  357. data/spec/unit/mutest/parser_spec.rb +24 -0
  358. data/spec/unit/mutest/registry_spec.rb +45 -0
  359. data/spec/unit/mutest/reporter/cli/printer/config_spec.rb +29 -0
  360. data/spec/unit/mutest/reporter/cli/printer/env_progress_spec.rb +74 -0
  361. data/spec/unit/mutest/reporter/cli/printer/env_result_spec.rb +35 -0
  362. data/spec/unit/mutest/reporter/cli/printer/mutation_progress_result_spec.rb +23 -0
  363. data/spec/unit/mutest/reporter/cli/printer/mutation_result_spec.rb +110 -0
  364. data/spec/unit/mutest/reporter/cli/printer/status_progressive_spec.rb +43 -0
  365. data/spec/unit/mutest/reporter/cli/printer/status_spec.rb +119 -0
  366. data/spec/unit/mutest/reporter/cli/printer/subject_progress_spec.rb +34 -0
  367. data/spec/unit/mutest/reporter/cli/printer/subject_result_spec.rb +37 -0
  368. data/spec/unit/mutest/reporter/cli/printer/test_result_spec.rb +14 -0
  369. data/spec/unit/mutest/reporter/cli/printer_spec.rb +161 -0
  370. data/spec/unit/mutest/reporter/cli/tput_spec.rb +48 -0
  371. data/spec/unit/mutest/reporter/cli_spec.rb +212 -0
  372. data/spec/unit/mutest/reporter/null_spec.rb +12 -0
  373. data/spec/unit/mutest/reporter/sequence_spec.rb +29 -0
  374. data/spec/unit/mutest/repository/diff_spec.rb +106 -0
  375. data/spec/unit/mutest/repository/subject_filter_spec.rb +28 -0
  376. data/spec/unit/mutest/require_highjack_spec.rb +71 -0
  377. data/spec/unit/mutest/result/class_methods_spec.rb +49 -0
  378. data/spec/unit/mutest/result/env_spec.rb +82 -0
  379. data/spec/unit/mutest/result/mutation_spec.rb +37 -0
  380. data/spec/unit/mutest/result/subject_spec.rb +109 -0
  381. data/spec/unit/mutest/result_spec.rb +31 -0
  382. data/spec/unit/mutest/runner/sink_spec.rb +172 -0
  383. data/spec/unit/mutest/runner_spec.rb +69 -0
  384. data/spec/unit/mutest/selector/expression_spec.rb +59 -0
  385. data/spec/unit/mutest/source_file_spec.rb +42 -0
  386. data/spec/unit/mutest/subject/method/instance/memoized_spec.rb +78 -0
  387. data/spec/unit/mutest/subject/method/instance_spec.rb +64 -0
  388. data/spec/unit/mutest/subject/method/singleton_spec.rb +51 -0
  389. data/spec/unit/mutest/subject_spec.rb +87 -0
  390. data/spec/unit/mutest/util/one_spec.rb +20 -0
  391. data/spec/unit/mutest/warning_filter_spec.rb +99 -0
  392. data/spec/unit/mutest/zombifier_spec.rb +120 -0
  393. data/spec/unit/mutest_spec.rb +15 -0
  394. data/test_app/.rspec +1 -0
  395. data/test_app/Gemfile.rspec3.4 +7 -0
  396. data/test_app/Gemfile.rspec3.5 +7 -0
  397. data/test_app/lib/test_app.rb +109 -0
  398. data/test_app/lib/test_app/literal.rb +40 -0
  399. data/test_app/spec/spec_helper.rb +9 -0
  400. data/test_app/spec/unit/test_app/literal_spec.rb +20 -0
  401. metadata +784 -9
@@ -0,0 +1,88 @@
1
+ module Mutest
2
+ class Matcher
3
+ class Method
4
+ # Matcher for singleton methods
5
+ class Singleton < self
6
+ # New singleton method matcher
7
+ #
8
+ # @param [Class, Module] scope
9
+ # @param [Symbol] method_name
10
+ #
11
+ # @return [Matcher::Method::Singleton]
12
+ def self.new(scope, method_name)
13
+ super(scope, method_name, Evaluator)
14
+ end
15
+
16
+ # Singleton method evaluator
17
+ class Evaluator < Evaluator
18
+ SUBJECT_CLASS = Subject::Method::Singleton
19
+ RECEIVER_INDEX = 0
20
+ NAME_INDEX = 1
21
+ RECEIVER_WARNING = 'Can only match :defs on :self or :const got %p unable to match'.freeze
22
+
23
+ private
24
+
25
+ # Test for node match
26
+ #
27
+ # @param [Parser::AST::Node] node
28
+ #
29
+ # @return [Boolean]
30
+ def match?(node)
31
+ n_defs?(node) && line?(node) && name?(node) && receiver?(node)
32
+ end
33
+
34
+ # Test for line match
35
+ #
36
+ # @param [Parser::AST::Node] node
37
+ #
38
+ # @return [Boolean]
39
+ def line?(node)
40
+ node
41
+ .location
42
+ .line
43
+ .equal?(source_line)
44
+ end
45
+
46
+ # Test for name match
47
+ #
48
+ # @param [Parser::AST::Node] node
49
+ #
50
+ # @return [Boolean]
51
+ def name?(node)
52
+ node.children.fetch(NAME_INDEX).equal?(method_name)
53
+ end
54
+
55
+ # Test for receiver match
56
+ #
57
+ # @param [Parser::AST::Node] node
58
+ #
59
+ # @return [Boolean]
60
+ def receiver?(node)
61
+ receiver = node.children.fetch(RECEIVER_INDEX)
62
+ case receiver.type
63
+ when :self
64
+ true
65
+ when :const
66
+ receiver_name?(receiver)
67
+ else
68
+ env.warn(RECEIVER_WARNING % receiver.type)
69
+ nil
70
+ end
71
+ end
72
+
73
+ # Test if receiver name matches context
74
+ #
75
+ # @param [Parser::AST::Node] node
76
+ #
77
+ # @return [Boolean]
78
+ def receiver_name?(node)
79
+ name = node.children.fetch(NAME_INDEX)
80
+ name.to_s.eql?(context.unqualified_name)
81
+ end
82
+ end # Evaluator
83
+
84
+ private_constant(*constants(false))
85
+ end # Singleton
86
+ end # Method
87
+ end # Matcher
88
+ end # Mutest
@@ -0,0 +1,109 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Abstract base class for matcher that returns method subjects from scope
4
+ class Methods < self
5
+ include AbstractType, Concord.new(:scope)
6
+
7
+ CANDIDATE_NAMES = IceNine.deep_freeze(%i[
8
+ public_instance_methods
9
+ private_instance_methods
10
+ protected_instance_methods
11
+ ])
12
+
13
+ private_constant(*constants(false))
14
+
15
+ # Enumerate subjects
16
+ #
17
+ # @param [Env::Bootstrap] env
18
+ #
19
+ # @return [Enumerable<Subject>]
20
+ def call(env)
21
+ Chain.new(
22
+ methods.map { |method| matcher.new(scope, method) }
23
+ ).call(env)
24
+ end
25
+
26
+ private
27
+
28
+ # method matcher class
29
+ #
30
+ # @return [Class:Matcher::Method]
31
+ def matcher
32
+ self.class::MATCHER
33
+ end
34
+
35
+ # Available methods scope
36
+ #
37
+ # @return [Enumerable<Method, UnboundMethod>]
38
+ def methods
39
+ candidate_names.each_with_object([]) do |name, methods|
40
+ method = access(name)
41
+ methods << method if method.owner.equal?(candidate_scope)
42
+ end
43
+ end
44
+ memoize :methods
45
+
46
+ # Candidate method names on target scope
47
+ #
48
+ # @return [Enumerable<Symbol>]
49
+ def candidate_names
50
+ CANDIDATE_NAMES
51
+ .map(&candidate_scope.method(:public_send))
52
+ .reduce(:+)
53
+ .sort
54
+ end
55
+
56
+ # Candidate scope
57
+ #
58
+ # @return [Class, Module]
59
+ abstract_method :candidate_scope
60
+
61
+ # Matcher for singleton methods
62
+ class Singleton < self
63
+ MATCHER = Matcher::Method::Singleton
64
+
65
+ private
66
+
67
+ # Method object on scope
68
+ #
69
+ # @param [Symbol] method_name
70
+ #
71
+ # @return [Method]
72
+ def access(method_name)
73
+ scope.method(method_name)
74
+ end
75
+
76
+ # Candidate scope
77
+ #
78
+ # @return [Class]
79
+ def candidate_scope
80
+ scope.singleton_class
81
+ end
82
+ memoize :candidate_scope, freezer: :noop
83
+ end # Singleton
84
+
85
+ # Matcher for instance methods
86
+ class Instance < self
87
+ MATCHER = Matcher::Method::Instance
88
+
89
+ private
90
+
91
+ # Method object on scope
92
+ #
93
+ # @param [Symbol] method_name
94
+ #
95
+ # @return [UnboundMethod]
96
+ def access(method_name)
97
+ scope.instance_method(method_name)
98
+ end
99
+
100
+ # Candidate scope
101
+ #
102
+ # @return [Class, Module]
103
+ def candidate_scope
104
+ scope
105
+ end
106
+ end # Instance
107
+ end # Methods
108
+ end # Matcher
109
+ end # Mutest
@@ -0,0 +1,41 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Matcher for specific namespace
4
+ class Namespace < self
5
+ include Concord::Public.new(:expression)
6
+
7
+ # Enumerate subjects
8
+ #
9
+ # @param [Env::Bootstrap] env
10
+ #
11
+ # @return [Enumerable<Subject>]
12
+ def call(env)
13
+ Chain.new(
14
+ matched_scopes(env).map { |scope| Scope.new(scope.raw) }
15
+ ).call(env)
16
+ end
17
+
18
+ private
19
+
20
+ # The matched scopes
21
+ #
22
+ # @param [Env] env
23
+ #
24
+ # @return [Enumerable<Scope>]
25
+ def matched_scopes(env)
26
+ env
27
+ .matchable_scopes
28
+ .select(&method(:match?))
29
+ end
30
+
31
+ # Test scope if matches expression
32
+ #
33
+ # @param [Scope] scope
34
+ #
35
+ # @return [Boolean]
36
+ def match?(scope)
37
+ expression.prefix?(scope.expression)
38
+ end
39
+ end # Namespace
40
+ end # Matcher
41
+ end # Mutest
@@ -0,0 +1,17 @@
1
+ module Mutest
2
+ class Matcher
3
+ # A null matcher, that does not match any subjects
4
+ class Null < self
5
+ include Concord.new
6
+
7
+ # Enumerate subjects
8
+ #
9
+ # @param [Env::Bootstrap] env
10
+ #
11
+ # @return [Enumerable<Subject>]
12
+ def call(_env)
13
+ EMPTY_ARRAY
14
+ end
15
+ end # Null
16
+ end # Matcher
17
+ end # Mutest
@@ -0,0 +1,38 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Matcher expanding Mutest::Scope objects into method matches
4
+ # at singleton or instance level
5
+ #
6
+ # If we *ever* get other subjects than methods, its likely the place
7
+ # to hook in custom matchers. In that case the scope matchers to expand
8
+ # should be passed as arguments to the constructor.
9
+ class Scope < self
10
+ include Concord.new(:scope)
11
+
12
+ MATCHERS = [
13
+ Matcher::Methods::Singleton,
14
+ Matcher::Methods::Instance
15
+ ].freeze
16
+
17
+ private_constant(*constants(false))
18
+
19
+ # Matched subjects
20
+ #
21
+ # @param [Env::Bootstrap] env
22
+ #
23
+ # @return [Enumerable<Subject>]
24
+ def call(env)
25
+ Chain.new(effective_matchers).call(env)
26
+ end
27
+
28
+ private
29
+
30
+ # Effective matchers
31
+ #
32
+ # @return [Enumerable<Matcher>]
33
+ def effective_matchers
34
+ MATCHERS.map { |matcher| matcher.new(scope) }
35
+ end
36
+ end # Scope
37
+ end # Matcher
38
+ end # Mutest
@@ -0,0 +1,15 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Matcher returning subjects already known at its creation time
4
+ class Static
5
+ include Concord.new(:subjects)
6
+
7
+ # Call matcher
8
+ #
9
+ # @return [Enumerable<Subject>]
10
+ def call(_env)
11
+ subjects
12
+ end
13
+ end # Static
14
+ end # Matcher
15
+ end # Mutest
@@ -0,0 +1,33 @@
1
+ module Mutest
2
+ # Namespace for mutest metadata
3
+ module Meta
4
+ require 'mutest/meta/example'
5
+ require 'mutest/meta/example/dsl'
6
+ require 'mutest/meta/example/verification'
7
+
8
+ # Mutation example
9
+ class Example
10
+ # rubocop:disable MutableConstant
11
+ ALL = []
12
+
13
+ # Add example
14
+ #
15
+ # @return [undefined]
16
+ def self.add(type, &block)
17
+ file = caller.first.split(':in', 2).first
18
+ ALL << DSL.call(file, type, block)
19
+ end
20
+
21
+ Pathname.glob(Pathname.new(__dir__).parent.parent.join('meta', '*.rb'))
22
+ .sort
23
+ .each(&method(:require))
24
+
25
+ ALL.freeze
26
+
27
+ # Remove mutation method only present for DSL executions from meta/**/*.rb
28
+ class << self
29
+ undef_method :add
30
+ end
31
+ end # Example
32
+ end # Meta
33
+ end # Mutest
@@ -0,0 +1,32 @@
1
+ module Mutest
2
+ module Meta
3
+ class Example
4
+ include Adamantium, Anima.new(:file, :node, :node_type, :expected)
5
+
6
+ # Verification instance for example
7
+ #
8
+ # @return [Verification]
9
+ def verification
10
+ Verification.new(self, generated)
11
+ end
12
+
13
+ # Normalized source
14
+ #
15
+ # @return [String]
16
+ def source
17
+ Unparser.unparse(node)
18
+ end
19
+ memoize :source
20
+
21
+ # Generated mutations on example source
22
+ #
23
+ # @return [Enumerable<Mutest::Mutation>]
24
+ def generated
25
+ Mutator.mutate(node).map do |node|
26
+ Mutation::Evil.new(self, node)
27
+ end
28
+ end
29
+ memoize :generated
30
+ end # Example
31
+ end # Meta
32
+ end # Mutest
@@ -0,0 +1,107 @@
1
+ module Mutest
2
+ module Meta
3
+ class Example
4
+ # Example DSL
5
+ class DSL
6
+ include AST::Sexp
7
+
8
+ # Run DSL on block
9
+ #
10
+ # @return [Example]
11
+ def self.call(file, type, block)
12
+ instance = new(file, type)
13
+ instance.instance_eval(&block)
14
+ instance.example
15
+ end
16
+
17
+ private_class_method :new
18
+
19
+ # Initialize object
20
+ #
21
+ # @return [undefined]
22
+ def initialize(file, type)
23
+ @file = file
24
+ @type = type
25
+ @node = nil
26
+ @expected = []
27
+ end
28
+
29
+ # Example captured by DSL
30
+ #
31
+ # @return [Example]
32
+ #
33
+ # @raise [RuntimeError]
34
+ # in case example cannot be build
35
+ def example
36
+ fail 'source not defined' unless @node
37
+ Example.new(
38
+ file: @file,
39
+ node: @node,
40
+ node_type: @type,
41
+ expected: @expected
42
+ )
43
+ end
44
+
45
+ private
46
+
47
+ # Set original source
48
+ #
49
+ # @param [String,Parser::AST::Node] input
50
+ #
51
+ # @return [undefined]
52
+ def source(input)
53
+ fail 'source already defined' if @node
54
+ @node = node(input)
55
+ end
56
+
57
+ # Add expected mutation
58
+ #
59
+ # @param [String,Parser::AST::Node] input
60
+ #
61
+ # @return [undefined]
62
+ def mutation(input)
63
+ node = node(input)
64
+ if @expected.include?(node)
65
+ fail "Mutation for input: #{input.inspect} is already expected"
66
+ end
67
+ @expected << node
68
+ end
69
+
70
+ # Add singleton mutations
71
+ #
72
+ # @return [undefined]
73
+ def singleton_mutations
74
+ mutation('nil')
75
+ mutation('self')
76
+ end
77
+
78
+ # Add regexp mutations
79
+ #
80
+ # @return [undefined]
81
+ def regexp_mutations
82
+ mutation('//')
83
+ mutation('/nomatch\A/')
84
+ end
85
+
86
+ # Helper method to coerce input to node
87
+ #
88
+ # @param [String,Parser::AST::Node] input
89
+ #
90
+ # @return [Parser::AST::Node]
91
+ #
92
+ # @raise [RuntimeError]
93
+ # in case input cannot be coerced
94
+ def node(input)
95
+ case input
96
+ when String
97
+ Unparser::Preprocessor.run(::Parser::CurrentRuby.parse(input))
98
+ when ::Parser::AST::Node
99
+ input
100
+ else
101
+ fail "Cannot coerce to node: #{input.inspect}"
102
+ end
103
+ end
104
+ end # DSL
105
+ end # Example
106
+ end # Meta
107
+ end # Mutest