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,85 @@
1
+ module Mutest
2
+ module Meta
3
+ class Example
4
+ # Example verification
5
+ class Verification
6
+ include Adamantium::Flat, Concord.new(:example, :mutations)
7
+
8
+ # Test if mutation was verified successfully
9
+ #
10
+ # @return [Boolean]
11
+ def success?
12
+ missing.empty? && unexpected.empty? && no_diffs.empty?
13
+ end
14
+
15
+ # Error report
16
+ #
17
+ # @return [String]
18
+ def error_report
19
+ fail 'no error report on successful validation' if success?
20
+
21
+ YAML.dump(
22
+ 'file' => example.file,
23
+ 'original_ast' => example.node.inspect,
24
+ 'original_source' => example.source,
25
+ 'missing' => format_mutations(missing),
26
+ 'unexpected' => format_mutations(unexpected),
27
+ 'no_diff' => no_diff_report
28
+ )
29
+ end
30
+
31
+ private
32
+
33
+ # Unexpected mutations
34
+ #
35
+ # @return [Array<Parser::AST::Node>]
36
+ def unexpected
37
+ mutations.map(&:node) - example.expected
38
+ end
39
+ memoize :unexpected
40
+
41
+ # Mutations with no diff to original
42
+ #
43
+ # @return [Enumerable<Mutation>]
44
+ def no_diffs
45
+ mutations.select { |mutation| mutation.source.eql?(example.source) }
46
+ end
47
+ memoize :no_diffs
48
+
49
+ # Mutation report
50
+ #
51
+ # @param [Array<Parser::AST::Node>] nodes
52
+ #
53
+ # @return [Array<Hash>]
54
+ def format_mutations(nodes)
55
+ nodes.map do |node|
56
+ {
57
+ 'node' => node.inspect,
58
+ 'source' => Unparser.unparse(node)
59
+ }
60
+ end
61
+ end
62
+
63
+ # No diff mutation report
64
+ #
65
+ # @return [Array, nil]
66
+ def no_diff_report
67
+ no_diffs.map do |mutation|
68
+ {
69
+ 'node' => mutation.node.inspect,
70
+ 'source' => mutation.source
71
+ }
72
+ end
73
+ end
74
+
75
+ # Missing mutations
76
+ #
77
+ # @return [Array<Parser::AST::Node>]
78
+ def missing
79
+ example.expected - mutations.map(&:node)
80
+ end
81
+ memoize :missing
82
+ end # Verification
83
+ end # Example
84
+ end # Meta
85
+ end # Mutest
@@ -0,0 +1,101 @@
1
+ module Mutest
2
+ # Represent a mutated node with its subject
3
+ class Mutation
4
+ include AbstractType, Adamantium::Flat
5
+ include Concord::Public.new(:subject, :node)
6
+
7
+ CODE_DELIMITER = "\0".freeze
8
+ CODE_RANGE = (0..4).freeze
9
+
10
+ # Identification string
11
+ #
12
+ # @return [String]
13
+ def identification
14
+ "#{self.class::SYMBOL}:#{subject.identification}:#{code}"
15
+ end
16
+ memoize :identification
17
+
18
+ # Mutation code
19
+ #
20
+ # @return [String]
21
+ def code
22
+ sha1[CODE_RANGE]
23
+ end
24
+ memoize :code
25
+
26
+ # Normalized mutation source
27
+ #
28
+ # @return [String]
29
+ def source
30
+ Unparser.unparse(node)
31
+ end
32
+ memoize :source
33
+
34
+ # Normalized original source
35
+ #
36
+ # @return [String]
37
+ def original_source
38
+ subject.source
39
+ end
40
+
41
+ # Test if mutation is killed by test reports
42
+ #
43
+ # @param [Result::Test] test_result
44
+ #
45
+ # @return [Boolean]
46
+ def self.success?(test_result)
47
+ self::TEST_PASS_SUCCESS.equal?(test_result.passed)
48
+ end
49
+
50
+ # Insert mutated node
51
+ #
52
+ # @param kernel [Kernel]
53
+ #
54
+ # @return [self]
55
+ def insert(kernel)
56
+ subject.prepare
57
+ Loader.call(
58
+ binding: TOPLEVEL_BINDING,
59
+ kernel: kernel,
60
+ node: root,
61
+ subject: subject
62
+ )
63
+ self
64
+ end
65
+
66
+ private
67
+
68
+ # SHA1 sum of source and subject identification
69
+ #
70
+ # @return [String]
71
+ def sha1
72
+ Digest::SHA1.hexdigest(subject.identification + CODE_DELIMITER + source)
73
+ end
74
+ memoize :sha1
75
+
76
+ # Mutated root node
77
+ #
78
+ # @return [Parser::AST::Node]
79
+ def root
80
+ subject.context.root(node)
81
+ end
82
+
83
+ # Evil mutation that should case mutations to fail tests
84
+ class Evil < self
85
+ SYMBOL = 'evil'.freeze
86
+ TEST_PASS_SUCCESS = false
87
+ end # Evil
88
+
89
+ # Neutral mutation that should not cause mutations to fail tests
90
+ class Neutral < self
91
+ SYMBOL = 'neutral'.freeze
92
+ TEST_PASS_SUCCESS = true
93
+ end # Neutral
94
+
95
+ # Noop mutation, special case of neutral
96
+ class Noop < Neutral
97
+ SYMBOL = 'noop'.freeze
98
+ TEST_PASS_SUCCESS = true
99
+ end # Noop
100
+ end # Mutation
101
+ end # Mutest
@@ -0,0 +1,117 @@
1
+ module Mutest
2
+ # Generator for mutations
3
+ class Mutator
4
+ REGISTRY = Registry.new
5
+
6
+ include Adamantium::Flat,
7
+ Concord.new(:input, :filter, :parent),
8
+ AbstractType,
9
+ Procto.call(:output)
10
+
11
+ # Lookup and invoke dedicated AST mutator
12
+ #
13
+ # @param node [Parser::AST::Node]
14
+ # @param parent [nil,Mutest::Mutator::Node]
15
+ #
16
+ # @return [Set<Parser::AST::Node>]
17
+ #
18
+ # :reek:LongParameterList
19
+ def self.mutate(node, filter = ->(_) {}, parent = nil)
20
+ self::REGISTRY.lookup(node.type).call(node, filter, parent)
21
+ end
22
+
23
+ # Register node class handler
24
+ #
25
+ # @return [undefined]
26
+ def self.handle(*types)
27
+ types.each do |type|
28
+ self::REGISTRY.register(type, self)
29
+ end
30
+ end
31
+ private_class_method :handle
32
+
33
+ # Return output
34
+ #
35
+ # @return [Set<Parser::AST::Node>]
36
+ attr_reader :output
37
+
38
+ private
39
+
40
+ # Initialize object
41
+ #
42
+ # @param [Object] input
43
+ # @param [#call] mutation filter
44
+ # @param [Object] parent
45
+ # @param [#call(node)] block
46
+ #
47
+ # @return [undefined]
48
+ def initialize(_input, _filter, _parent = nil)
49
+ super
50
+
51
+ @output = Set.new
52
+
53
+ dispatch unless disabled?
54
+ end
55
+
56
+ def disabled?
57
+ filter.call(input)
58
+ end
59
+
60
+ # Test if generated object is not guarded from emitting
61
+ #
62
+ # @param [Object] object
63
+ #
64
+ # @return [Boolean]
65
+ def new?(object)
66
+ !object.eql?(input)
67
+ end
68
+
69
+ # Dispatch node generations
70
+ #
71
+ # @return [undefined]
72
+ abstract_method :dispatch
73
+
74
+ # Emit generated mutation if object is not equivalent to input
75
+ #
76
+ # @param [Object] object
77
+ #
78
+ # @return [undefined]
79
+ def emit(object)
80
+ return unless new?(object)
81
+
82
+ output << object
83
+ end
84
+
85
+ # Shortcut to create a new unfrozen duplicate of input
86
+ #
87
+ # @return [Object]
88
+ def dup_input
89
+ input.dup
90
+ end
91
+
92
+ # Mutate child nodes within source path
93
+ #
94
+ # @return [Set<Parser::AST::Node>]
95
+ def mutate(node, parent = nil)
96
+ self.class.mutate(node, filter, parent)
97
+ end
98
+
99
+ # Run input with mutator
100
+ #
101
+ # @return [undefined]
102
+ def run(mutator)
103
+ mutate_with(mutator, input)
104
+ end
105
+
106
+ # Mutate nodes using a specific mutator class
107
+ #
108
+ # @yield [Object] value emitted by provided mutator
109
+ #
110
+ # @return [undefined]
111
+ def mutate_with(mutator, nodes, &block)
112
+ block ||= method(:emit)
113
+
114
+ mutator.call(nodes, filter).each(&block)
115
+ end
116
+ end # Mutator
117
+ end # Mutest
@@ -0,0 +1,166 @@
1
+ module Mutest
2
+ # Generator for mutations
3
+ class Mutator
4
+ # Abstract base class for node mutators
5
+ class Node < self
6
+ include AbstractType, Unparser::Constants
7
+ include AST::NamedChildren, AST::NodePredicates, AST::Sexp, AST::Nodes
8
+
9
+ TAUTOLOGY = ->(_input) { true }
10
+
11
+ # Helper to define a named child
12
+ #
13
+ # @param [Parser::AST::Node] node
14
+ #
15
+ # @param [Fixnum] index
16
+ #
17
+ # @return [undefined]
18
+ def self.define_named_child(name, index)
19
+ super
20
+
21
+ define_method(:"emit_#{name}_mutations") do |&block|
22
+ mutate_child(index, &block)
23
+ end
24
+
25
+ define_method(:"emit_#{name}") do |node|
26
+ emit_child_update(index, node)
27
+ end
28
+ end
29
+ private_class_method :define_named_child
30
+
31
+ private
32
+
33
+ # Node to mutate
34
+ #
35
+ # @return [Parser::AST::Node]
36
+ alias_method :node, :input
37
+
38
+ # Duplicate of original
39
+ #
40
+ # @return [Parser::AST::Node]
41
+ alias_method :dup_node, :dup_input
42
+
43
+ # Original nodes children
44
+ #
45
+ # @return [Array<Parser::AST::Node>]
46
+ def children
47
+ node.children
48
+ end
49
+
50
+ # Dispatch on child index
51
+ #
52
+ # @param [Fixnum] index
53
+ #
54
+ # @return [undefined]
55
+ def mutate_child(index, &block)
56
+ block ||= TAUTOLOGY
57
+ mutate(children.fetch(index), self).each do |mutation|
58
+ next unless block.call(mutation)
59
+ emit_child_update(index, mutation)
60
+ end
61
+ end
62
+
63
+ # Emit delete child mutation
64
+ #
65
+ # @param [Fixnum] index
66
+ #
67
+ # @return [undefined]
68
+ def delete_child(index)
69
+ dup_children = children.dup
70
+ dup_children.delete_at(index)
71
+ emit_type(*dup_children)
72
+ end
73
+
74
+ # Emit updated child
75
+ #
76
+ # @param [Fixnum] index
77
+ # @param [Parser::AST::Node] node
78
+ #
79
+ # @return [undefined]
80
+ def emit_child_update(index, node)
81
+ new_children = children.dup
82
+ new_children[index] = node
83
+ emit_type(*new_children)
84
+ end
85
+
86
+ # Emit a new AST node with same class as wrapped node
87
+ #
88
+ # @param [Array<Parser::AST::Node>] children
89
+ #
90
+ # @return [undefined]
91
+ def emit_type(*children)
92
+ emit(::Parser::AST::Node.new(node.type, children))
93
+ end
94
+
95
+ # Emit singleton literals
96
+ #
97
+ # @return [undefined]
98
+ def emit_singletons
99
+ emit_nil
100
+ emit_self
101
+ end
102
+
103
+ # Emit a literal self
104
+ #
105
+ # @return [undefined]
106
+ def emit_self
107
+ emit(N_SELF)
108
+ end
109
+
110
+ # Emit a literal nil
111
+ #
112
+ # @return [undefined]
113
+ def emit_nil
114
+ emit(N_NIL) unless asgn_left?
115
+ end
116
+
117
+ # Parent node
118
+ #
119
+ # @return [Parser::AST::Node] node
120
+ # if parent with node is present
121
+ #
122
+ # @return [nil]
123
+ # otherwise
124
+ def parent_node
125
+ parent.node if parent
126
+ end
127
+
128
+ # Parent type
129
+ #
130
+ # @return [Symbol] type
131
+ # if parent with type is present
132
+ #
133
+ # @return [nil]
134
+ # otherwise
135
+ def parent_type
136
+ parent_node.type if parent_node
137
+ end
138
+
139
+ # Test if the node is the left of an or_asgn or op_asgn
140
+ #
141
+ # @return [Boolean]
142
+ def asgn_left?
143
+ AST::Types::OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
144
+ end
145
+
146
+ # Children indices
147
+ #
148
+ # @param [Range] range
149
+ #
150
+ # @return [Enumerable<Fixnum>]
151
+ def children_indices(range)
152
+ range.begin.upto(children.length + range.end)
153
+ end
154
+
155
+ # Emit single child mutation
156
+ #
157
+ # @return [undefined]
158
+ def mutate_single_child
159
+ children.each_with_index do |child, index|
160
+ mutate_child(index)
161
+ yield child, index unless children.one?
162
+ end
163
+ end
164
+ end # Node
165
+ end # Mutator
166
+ end # Mutest