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,23 @@
1
+ module Mutest
2
+ # Module providing isolation
3
+ class Isolation
4
+ Error = Class.new(RuntimeError)
5
+
6
+ # Absolutly no isolation
7
+ #
8
+ # Only useful for debugging.
9
+ class None < self
10
+ # Call block in no isolation
11
+ #
12
+ # @return [Object]
13
+ #
14
+ # @raise [Error]
15
+ # if block terminates abnormal
16
+ def call
17
+ yield
18
+ rescue => exception
19
+ raise Error, exception
20
+ end
21
+ end # None
22
+ end # Isolation
23
+ end # Mutest
@@ -0,0 +1,27 @@
1
+ module Mutest
2
+ # Base class for code loaders
3
+ class Loader
4
+ include Anima.new(:binding, :kernel, :node, :subject)
5
+
6
+ # Call loader
7
+ #
8
+ # @return [self]
9
+ def self.call(*arguments)
10
+ new(*arguments).call
11
+ end
12
+
13
+ # Call loader
14
+ #
15
+ # One off the very few valid uses of eval
16
+ #
17
+ # @return [undefined]
18
+ def call
19
+ kernel.eval(
20
+ Unparser.unparse(node),
21
+ binding,
22
+ subject.source_path.to_s,
23
+ subject.source_line
24
+ )
25
+ end
26
+ end # Loader
27
+ end # Mutest
@@ -0,0 +1,14 @@
1
+ module Mutest
2
+ # Abstract matcher to find subjects to mutate
3
+ class Matcher
4
+ include Adamantium::Flat, AbstractType
5
+
6
+ # Call matcher
7
+ #
8
+ # @param [Env::Bootstrap] env
9
+ #
10
+ # @return [Enumerable<Subject>]
11
+ #
12
+ abstract_method :call
13
+ end # Matcher
14
+ end # Mutest
@@ -0,0 +1,19 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Matcher chaining results of other matchers together
4
+ class Chain < self
5
+ include Concord.new(:matchers)
6
+
7
+ # Call matcher
8
+ #
9
+ # @param [Env::Bootstrap] env
10
+ #
11
+ # @return [Enumerable<Subject>]
12
+ def call(env)
13
+ matchers.flat_map do |matcher|
14
+ matcher.call(env)
15
+ end
16
+ end
17
+ end # Chain
18
+ end # Matcher
19
+ end # Mutest
@@ -0,0 +1,55 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Compiler for complex matchers
4
+ class Compiler
5
+ include Concord.new(:config), AST::Sexp, Procto.call(:result)
6
+
7
+ # Generated matcher
8
+ #
9
+ # @return [Matcher]
10
+ def result
11
+ Filter.new(
12
+ Chain.new(config.match_expressions.map(&:matcher)),
13
+ Morpher::Evaluator::Predicate::Boolean::And.new(
14
+ [
15
+ ignored_subjects,
16
+ filtered_subjects
17
+ ]
18
+ )
19
+ )
20
+ end
21
+
22
+ # Subject expression prefix predicate
23
+ class SubjectPrefix
24
+ include Concord.new(:expression)
25
+
26
+ # Test if subject expression is matched by prefix
27
+ #
28
+ # @return [Boolean]
29
+ def call(subject)
30
+ expression.prefix?(subject.expression)
31
+ end
32
+ end # SubjectPrefix
33
+
34
+ private
35
+
36
+ # Predicate returning false on expression ignored subject
37
+ #
38
+ # @return [#call]
39
+ def ignored_subjects
40
+ Morpher::Evaluator::Predicate::Boolean::Negation.new(
41
+ Morpher::Evaluator::Predicate::Boolean::Or.new(
42
+ config.ignore_expressions.map(&SubjectPrefix.method(:new))
43
+ )
44
+ )
45
+ end
46
+
47
+ # Predicate returning false on filtered subject
48
+ #
49
+ # @return [#call]
50
+ def filtered_subjects
51
+ Morpher::Evaluator::Predicate::Boolean::And.new(config.subject_filters)
52
+ end
53
+ end # Compiler
54
+ end # Matcher
55
+ end # Mutest
@@ -0,0 +1,81 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Subject matcher configuration
4
+ #
5
+ # :reek:TooManyConstants
6
+ class Config
7
+ include Adamantium, Anima.new(
8
+ :ignore_expressions,
9
+ :match_expressions,
10
+ :subject_filters
11
+ )
12
+
13
+ INSPECT_FORMAT = "#<#{self} %s>".freeze
14
+ ATTRIBUTE_DELIMITER = ' '.freeze
15
+ ATTRIBUTE_FORMAT = '%s: [%s]'.freeze
16
+ ENUM_DELIMITER = ','.freeze
17
+ EMPTY_ATTRIBUTES = 'empty'.freeze
18
+ PRESENTATIONS = IceNine.deep_freeze(
19
+ ignore_expressions: :syntax,
20
+ match_expressions: :syntax,
21
+ subject_filters: :inspect
22
+ )
23
+ private_constant(*constants(false))
24
+
25
+ DEFAULT = new(Hash[anima.attribute_names.map { |name| [name, []] }])
26
+
27
+ # Inspection string
28
+ #
29
+ # @return [String]
30
+ def inspect
31
+ INSPECT_FORMAT % inspect_attributes
32
+ end
33
+ memoize :inspect
34
+
35
+ # Add value to configurable collection
36
+ #
37
+ # @param [Symbol] attribute
38
+ # @param [Object] value
39
+ #
40
+ # @return [Config]
41
+ def add(attribute, value)
42
+ with(attribute => public_send(attribute) + [value])
43
+ end
44
+
45
+ private
46
+
47
+ # Present attributes
48
+ #
49
+ # @return [Array<Symbol>]
50
+ def present_attributes
51
+ to_h.reject { |_key, value| value.empty? }.keys
52
+ end
53
+
54
+ # Formatted attributes
55
+ #
56
+ # @return [String]
57
+ def inspect_attributes
58
+ attributes = present_attributes
59
+ .map(&method(:format_attribute))
60
+ .join(ATTRIBUTE_DELIMITER)
61
+
62
+ attributes.empty? ? EMPTY_ATTRIBUTES : attributes
63
+ end
64
+
65
+ # Format attribute
66
+ #
67
+ # @param [Symbol] attribute_name
68
+ #
69
+ # @return [String]
70
+ def format_attribute(attribute_name)
71
+ format(
72
+ ATTRIBUTE_FORMAT,
73
+ attribute_name,
74
+ public_send(attribute_name)
75
+ .map(&PRESENTATIONS.fetch(attribute_name))
76
+ .join(ENUM_DELIMITER)
77
+ )
78
+ end
79
+ end # Config
80
+ end # Matcher
81
+ end # Mutest
@@ -0,0 +1,19 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Matcher filter
4
+ class Filter < self
5
+ include Concord.new(:matcher, :predicate)
6
+
7
+ # Enumerate matches
8
+ #
9
+ # @param [Env::Bootstrap] env
10
+ #
11
+ # @return [Enumerable<Subject>]
12
+ def call(env)
13
+ matcher
14
+ .call(env)
15
+ .select(&predicate.method(:call))
16
+ end
17
+ end # Filter
18
+ end # Matcher
19
+ end # Mutest
@@ -0,0 +1,138 @@
1
+ module Mutest
2
+ class Matcher
3
+ # Abstract base class for method matchers
4
+ #
5
+ # :reek:TooManyMethods { max_methods: 11 }
6
+ class Method < self
7
+ include AbstractType,
8
+ Adamantium::Flat,
9
+ Concord::Public.new(:scope, :target_method, :evaluator)
10
+
11
+ # Methods within rbx kernel directory are precompiled and their source
12
+ # cannot be accessed via reading source location. Same for methods created by eval.
13
+ BLACKLIST = %r{\A(kernel/|\(eval\)\z)}
14
+
15
+ SOURCE_LOCATION_WARNING_FORMAT =
16
+ '%s does not have a valid source location, unable to emit subject'.freeze
17
+
18
+ CLOSURE_WARNING_FORMAT =
19
+ '%s is dynamically defined in a closure, unable to emit subject'.freeze
20
+
21
+ # Matched subjects
22
+ #
23
+ # @param [Env::Bootstrap] env
24
+ #
25
+ # @return [Enumerable<Subject>]
26
+ def call(env)
27
+ evaluator.call(scope, target_method, env)
28
+ end
29
+
30
+ # Abstract method match evaluator
31
+ #
32
+ # Present to avoid passing the env argument around in case the
33
+ # logic would be implemented directly on the Matcher::Method
34
+ # instance
35
+ class Evaluator
36
+ include AbstractType,
37
+ Adamantium,
38
+ Concord.new(:scope, :target_method, :env),
39
+ Procto.call,
40
+ AST::NodePredicates
41
+
42
+ # Matched subjects
43
+ #
44
+ # @return [Enumerable<Subject>]
45
+ def call
46
+ return EMPTY_ARRAY if skip?
47
+
48
+ [subject].compact
49
+ end
50
+
51
+ private
52
+
53
+ # Test if method should be skipped
54
+ #
55
+ # @return [Truthy]
56
+ def skip?
57
+ location = source_location
58
+ if location.nil? || BLACKLIST.match(location.first)
59
+ env.warn(SOURCE_LOCATION_WARNING_FORMAT % target_method)
60
+ elsif matched_node_path.any?(&method(:n_block?))
61
+ env.warn(CLOSURE_WARNING_FORMAT % target_method)
62
+ end
63
+ end
64
+
65
+ # Target method name
66
+ #
67
+ # @return [String]
68
+ def method_name
69
+ target_method.name
70
+ end
71
+
72
+ # Target context
73
+ #
74
+ # @return [Context]
75
+ def context
76
+ Context.new(scope, source_file)
77
+ end
78
+
79
+ # Root source node
80
+ #
81
+ # @return [Parser::AST::Node]
82
+ def ast
83
+ source_file.ast
84
+ end
85
+
86
+ def source_file
87
+ env.parser.open(source_path)
88
+ end
89
+ memoize :source_file
90
+
91
+ # Path to source
92
+ #
93
+ # @return [Pathname]
94
+ def source_path
95
+ env.config.pathname.new(source_location.first)
96
+ end
97
+ memoize :source_path
98
+
99
+ # Source file line
100
+ #
101
+ # @return [Fixnum]
102
+ def source_line
103
+ source_location.last
104
+ end
105
+
106
+ # Full source location
107
+ #
108
+ # @return [Array{String,Fixnum}]
109
+ def source_location
110
+ target_method.source_location
111
+ end
112
+
113
+ # Matched subject
114
+ #
115
+ # @return [Subject]
116
+ # if there is a matched node
117
+ #
118
+ # @return [nil]
119
+ # otherwise
120
+ def subject
121
+ node = matched_node_path.last || return
122
+ self.class::SUBJECT_CLASS.new(context, node)
123
+ end
124
+ memoize :subject
125
+
126
+ # Matched node path
127
+ #
128
+ # @return [Array<Parser::AST::Node>]
129
+ def matched_node_path
130
+ AST.find_last_path(ast, &method(:match?))
131
+ end
132
+ memoize :matched_node_path
133
+ end # Evaluator
134
+
135
+ private_constant(*constants(false))
136
+ end # Method
137
+ end # Matcher
138
+ end # Mutest
@@ -0,0 +1,63 @@
1
+ module Mutest
2
+ class Matcher
3
+ class Method
4
+ # Matcher for instance methods
5
+ class Instance < self
6
+ # Dispatching builder, detects memoizable case
7
+ #
8
+ # @param [Class, Module] scope
9
+ # @param [UnboundMethod] method
10
+ #
11
+ # @return [Matcher::Method::Instance]
12
+ def self.new(scope, target_method)
13
+ name = target_method.name
14
+ evaluator =
15
+ if scope.include?(Memoizable) && scope.memoized?(name)
16
+ Evaluator::Memoized
17
+ else
18
+ Evaluator
19
+ end
20
+
21
+ super(scope, target_method, evaluator)
22
+ end
23
+
24
+ # Instance method specific evaluator
25
+ class Evaluator < Evaluator
26
+ SUBJECT_CLASS = Subject::Method::Instance
27
+ NAME_INDEX = 0
28
+
29
+ private
30
+
31
+ # Check if node is matched
32
+ #
33
+ # @param [Parser::AST::Node] node
34
+ #
35
+ # @return [Boolean]
36
+ def match?(node)
37
+ n_def?(node) &&
38
+ node.location.line.equal?(source_line) &&
39
+ node.children.fetch(NAME_INDEX).equal?(method_name)
40
+ end
41
+
42
+ # Evaluator specialized for memoized instance methods
43
+ class Memoized < self
44
+ SUBJECT_CLASS = Subject::Method::Instance::Memoized
45
+
46
+ private
47
+
48
+ # Source location
49
+ #
50
+ # @return [Array{String,Fixnum}]
51
+ def source_location
52
+ scope
53
+ .unmemoized_instance_method(method_name)
54
+ .source_location
55
+ end
56
+ end # Memoized
57
+ end # Evaluator
58
+
59
+ private_constant(*constants(false))
60
+ end # Instance
61
+ end # Method
62
+ end # Matcher
63
+ end # Mutest