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,36 @@
1
+ RSpec.describe Mutest::AST::Sexp do
2
+ let(:object) do
3
+ Class.new do
4
+ include Mutest::AST::Sexp
5
+
6
+ public :n_not
7
+ public :s
8
+ end.new
9
+ end
10
+
11
+ describe '#n_not' do
12
+ subject { object.n_not(node) }
13
+
14
+ let(:node) { s(:true) }
15
+
16
+ it 'returns negated ast' do
17
+ expect(subject).to eql(s(:send, s(:true), :!))
18
+ end
19
+ end
20
+
21
+ describe '#s' do
22
+ subject { object.s(*arguments) }
23
+
24
+ context 'with single argument' do
25
+ let(:arguments) { %i[foo] }
26
+
27
+ it { is_expected.to eql(Parser::AST::Node.new(:foo)) }
28
+ end
29
+
30
+ context 'with single multiple arguments' do
31
+ let(:arguments) { %i[foo bar baz] }
32
+
33
+ it { is_expected.to eql(Parser::AST::Node.new(:foo, %i[bar baz])) }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,55 @@
1
+ RSpec.describe Mutest::AST do
2
+ let(:object) { described_class }
3
+
4
+ describe '.find_last_path' do
5
+ subject { object.find_last_path(root, &block) }
6
+
7
+ let(:root) { s(:root, parent) }
8
+ let(:child_a) { s(:child_a) }
9
+ let(:child_b) { s(:child_b) }
10
+ let(:parent) { s(:parent, child_a, child_b) }
11
+
12
+ def path
13
+ subject.map(&:type)
14
+ end
15
+
16
+ context 'when no node matches' do
17
+ let(:block) { ->(_) { false } }
18
+
19
+ it { is_expected.to eql([]) }
20
+ end
21
+
22
+ context 'when called without block' do
23
+ let(:block) { nil }
24
+
25
+ it 'raises error' do
26
+ expect { subject }.to raise_error(ArgumentError, 'block expected')
27
+ end
28
+ end
29
+
30
+ context 'on non Parser::AST::Node child' do
31
+ let(:block) { ->(node) { fail if node.equal?(child_a) } }
32
+ let(:child_a) { AST::Node.new(:foo) }
33
+
34
+ it 'does not yield that node' do
35
+ expect(path).to eql([])
36
+ end
37
+ end
38
+
39
+ context 'when one node matches' do
40
+ let(:block) { ->(node) { node.equal?(child_a) } }
41
+
42
+ it 'returns the full path' do
43
+ expect(path).to eql(%i[root parent child_a])
44
+ end
45
+ end
46
+
47
+ context 'when two nodes match' do
48
+ let(:block) { ->(node) { node.equal?(child_a) || node.equal?(child_b) } }
49
+
50
+ it 'returns the last full path' do
51
+ expect(path).to eql(%i[root parent child_b])
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,247 @@
1
+ RSpec.describe Mutest::CLI do
2
+ let(:object) { described_class }
3
+
4
+ shared_examples_for 'an invalid cli run' do
5
+ it 'raises error' do
6
+ expect do
7
+ subject
8
+ end.to raise_error(Mutest::CLI::Error, expected_message)
9
+ end
10
+ end
11
+
12
+ shared_examples_for 'a cli parser' do
13
+ it { expect(subject.config.integration).to eql(expected_integration) }
14
+ it { expect(subject.config.reporter).to eql(expected_reporter) }
15
+ it { expect(subject.config.matcher).to eql(expected_matcher_config) }
16
+ end
17
+
18
+ describe '.run' do
19
+ subject { object.run(arguments) }
20
+
21
+ let(:arguments) { instance_double(Array) }
22
+ let(:report) { instance_double(Mutest::Result::Env, success?: report_success) }
23
+ let(:config) { instance_double(Mutest::Config) }
24
+ let(:env) { instance_double(Mutest::Env) }
25
+
26
+ before do
27
+ expect(described_class).to receive(:call).with(arguments).and_return(config)
28
+ expect(Mutest::Env::Bootstrap).to receive(:call).with(config).and_return(env)
29
+ expect(Mutest::Runner).to receive(:call).with(env).and_return(report)
30
+ end
31
+
32
+ context 'when report signals success' do
33
+ let(:report_success) { true }
34
+
35
+ it 'exits failure' do
36
+ expect(subject).to be(true)
37
+ end
38
+ end
39
+
40
+ context 'when report signals error' do
41
+ let(:report_success) { false }
42
+
43
+ it 'exits failure' do
44
+ expect(subject).to be(false)
45
+ end
46
+ end
47
+
48
+ context 'when execution raises an Mutest::CLI::Error' do
49
+ let(:exception) { Mutest::CLI::Error.new('test-error') }
50
+ let(:report_success) { nil }
51
+
52
+ before do
53
+ expect(report).to receive(:success?).and_raise(exception)
54
+ end
55
+
56
+ it 'exits failure' do
57
+ expect($stderr).to receive(:puts).with('test-error')
58
+ expect(subject).to be(false)
59
+ end
60
+ end
61
+ end
62
+
63
+ describe '.new' do
64
+ subject { object.new(arguments) }
65
+
66
+ let(:object) { described_class }
67
+
68
+ # Defaults
69
+ let(:expected_integration) { Mutest::Integration::Null }
70
+ let(:expected_reporter) { Mutest::Config::DEFAULT.reporter }
71
+ let(:expected_matcher_config) { default_matcher_config }
72
+
73
+ let(:default_matcher_config) do
74
+ Mutest::Matcher::Config::DEFAULT
75
+ .with(match_expressions: expressions.map(&method(:parse_expression)))
76
+ end
77
+
78
+ let(:flags) { [] }
79
+ let(:expressions) { %w[TestApp*] }
80
+
81
+ let(:arguments) { flags + expressions }
82
+
83
+ context 'with unknown flag' do
84
+ let(:flags) { %w[--invalid] }
85
+
86
+ let(:expected_message) { 'invalid option: --invalid' }
87
+
88
+ it_should_behave_like 'an invalid cli run'
89
+ end
90
+
91
+ context 'with unknown option' do
92
+ let(:flags) { %w[--invalid Foo] }
93
+
94
+ let(:expected_message) { 'invalid option: --invalid' }
95
+
96
+ it_should_behave_like 'an invalid cli run'
97
+ end
98
+
99
+ context 'with include help flag' do
100
+ let(:flags) { %w[--help] }
101
+
102
+ before do
103
+ expect($stdout).to receive(:puts).with(expected_message)
104
+ expect(Kernel).to receive(:exit)
105
+ end
106
+
107
+ it_should_behave_like 'a cli parser'
108
+
109
+ let(:expected_message) do
110
+ strip_indent(<<-MESSAGE)
111
+ usage: mutest [options] MATCH_EXPRESSION ...
112
+ Environment:
113
+ --zombie Run mutest zombified
114
+ -I, --include DIRECTORY Add DIRECTORY to $LOAD_PATH
115
+ -r, --require NAME Require file with NAME
116
+ -j, --jobs NUMBER Number of kill jobs. Defaults to number of processors.
117
+
118
+ Options:
119
+ --use INTEGRATION Use INTEGRATION to kill mutations
120
+ --ignore-subject EXPRESSION Ignore subjects that match EXPRESSION as prefix
121
+ --since REVISION Only select subjects touched since REVISION
122
+ --fail-fast Fail fast
123
+ --version Print mutests version
124
+ -h, --help Show this message
125
+ MESSAGE
126
+ end
127
+ end
128
+
129
+ context 'with include flag' do
130
+ let(:flags) { %w[--include foo] }
131
+
132
+ it_should_behave_like 'a cli parser'
133
+
134
+ it 'configures includes' do
135
+ expect(subject.config.includes).to eql(%w[foo])
136
+ end
137
+ end
138
+
139
+ context 'with use flag' do
140
+ context 'when integration exists' do
141
+ let(:flags) { %w[--use rspec] }
142
+
143
+ before do
144
+ expect(Kernel).to receive(:require)
145
+ .with('mutest/integration/rspec')
146
+ .and_call_original
147
+ end
148
+
149
+ it_should_behave_like 'a cli parser'
150
+
151
+ let(:expected_integration) { Mutest::Integration::Rspec }
152
+ end
153
+
154
+ context 'when integration does NOT exist' do
155
+ let(:flags) { %w[--use other] }
156
+
157
+ it 'raises error' do
158
+ expect { subject }.to raise_error(
159
+ Mutest::CLI::Error,
160
+ 'Could not load integration "other" (you may want to try installing the gem mutest-other)'
161
+ )
162
+ end
163
+ end
164
+ end
165
+
166
+ context 'with version flag' do
167
+ let(:flags) { %w[--version] }
168
+
169
+ before do
170
+ expect(Kernel).to receive(:exit)
171
+ expect($stdout).to receive(:puts).with("mutest-#{Mutest::VERSION}")
172
+ end
173
+
174
+ it_should_behave_like 'a cli parser'
175
+ end
176
+
177
+ context 'with jobs flag' do
178
+ let(:flags) { %w[--jobs 0] }
179
+
180
+ it_should_behave_like 'a cli parser'
181
+
182
+ it 'configures expected coverage' do
183
+ expect(subject.config.jobs).to be(0)
184
+ end
185
+ end
186
+
187
+ context 'with require flags' do
188
+ let(:flags) { %w[--require foo --require bar] }
189
+
190
+ it_should_behave_like 'a cli parser'
191
+
192
+ it 'configures requires' do
193
+ expect(subject.config.requires).to eql(%w[foo bar])
194
+ end
195
+ end
196
+
197
+ context 'with --since flag' do
198
+ let(:flags) { %w[--since master] }
199
+
200
+ let(:expected_matcher_config) do
201
+ default_matcher_config.with(
202
+ subject_filters: [
203
+ Mutest::Repository::SubjectFilter.new(
204
+ Mutest::Repository::Diff.new(
205
+ config: Mutest::Config::DEFAULT,
206
+ from: 'HEAD',
207
+ to: 'master'
208
+ )
209
+ )
210
+ ]
211
+ )
212
+ end
213
+
214
+ it_should_behave_like 'a cli parser'
215
+ end
216
+
217
+ context 'with subject-ignore flag' do
218
+ let(:flags) { %w[--ignore-subject Foo::Bar] }
219
+
220
+ let(:expected_matcher_config) do
221
+ default_matcher_config.with(ignore_expressions: [parse_expression('Foo::Bar')])
222
+ end
223
+
224
+ it_should_behave_like 'a cli parser'
225
+ end
226
+
227
+ context 'with fail-fast flag' do
228
+ let(:flags) { %w[--fail-fast] }
229
+
230
+ it_should_behave_like 'a cli parser'
231
+
232
+ it 'sets the fail fast option' do
233
+ expect(subject.config.fail_fast).to be(true)
234
+ end
235
+ end
236
+
237
+ context 'with zombie flag' do
238
+ let(:flags) { %w[--zombie] }
239
+
240
+ it_should_behave_like 'a cli parser'
241
+
242
+ it 'sets the zombie option' do
243
+ expect(subject.config.zombie).to be(true)
244
+ end
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,141 @@
1
+ RSpec.describe Mutest::Context do
2
+ describe '.wrap' do
3
+ subject { described_class.wrap(scope, node) }
4
+
5
+ let(:node) { s(:str, 'test') }
6
+
7
+ context 'with Module as scope' do
8
+ let(:scope) { Mutest }
9
+
10
+ let(:expected) do
11
+ s(:module,
12
+ s(:const, nil, :Mutest),
13
+ s(:str, 'test'))
14
+ end
15
+
16
+ it { is_expected.to eql(expected) }
17
+ end
18
+
19
+ context 'with Class as scope' do
20
+ let(:scope) { described_class }
21
+
22
+ let(:expected) do
23
+ s(:class,
24
+ s(:const, nil, :Context),
25
+ nil,
26
+ s(:str, 'test'))
27
+ end
28
+
29
+ it { is_expected.to eql(expected) }
30
+ end
31
+ end
32
+
33
+ let(:source_path) { instance_double(Pathname) }
34
+ let(:scope) { TestApp::Literal }
35
+
36
+ let(:object) do
37
+ described_class.new(scope, instance_double(Mutest::SourceFile))
38
+ end
39
+
40
+ describe '#identification' do
41
+ subject { object.identification }
42
+
43
+ it { is_expected.to eql(scope.name) }
44
+ end
45
+
46
+ describe '#root' do
47
+ subject { object.root(node) }
48
+
49
+ let(:node) { s(:sym, :node) }
50
+
51
+ let(:expected_source) do
52
+ generate(parse(<<-RUBY))
53
+ module TestApp
54
+ class Literal
55
+ :node
56
+ end
57
+ end
58
+ RUBY
59
+ end
60
+
61
+ let(:generated_source) do
62
+ Unparser.unparse(subject)
63
+ end
64
+
65
+ it 'creates correct source' do
66
+ expect(generated_source).to eql(expected_source)
67
+ end
68
+ end
69
+
70
+ describe '#unqualified_name' do
71
+ subject { object.unqualified_name }
72
+
73
+ context 'with top level constant name' do
74
+ let(:scope) { TestApp }
75
+
76
+ it 'returns the unqualified name' do
77
+ is_expected.to eql('TestApp')
78
+ end
79
+
80
+ it_should_behave_like 'an idempotent method'
81
+ end
82
+
83
+ context 'with scoped constant name' do
84
+ it 'returns the unqualified name' do
85
+ is_expected.to eql('Literal')
86
+ end
87
+
88
+ it_should_behave_like 'an idempotent method'
89
+ end
90
+ end
91
+
92
+ describe '#match_expressions' do
93
+ subject { object.match_expressions }
94
+
95
+ context 'on toplevel scope' do
96
+ let(:scope) { TestApp }
97
+
98
+ it { is_expected.to eql([parse_expression('TestApp*')]) }
99
+ end
100
+
101
+ context 'on nested scope' do
102
+ specify do
103
+ is_expected.to eql(
104
+ [
105
+ parse_expression('TestApp::Literal*'),
106
+ parse_expression('TestApp*')
107
+ ]
108
+ )
109
+ end
110
+ end
111
+ end
112
+
113
+ describe '#ignore?' do
114
+ let(:object) do
115
+ described_class.new(scope, source_file)
116
+ end
117
+
118
+ let(:source_file) { instance_double(Mutest::SourceFile) }
119
+ let(:node) { s(:node) }
120
+
121
+ before do
122
+ allow(source_file).to receive(:ignore?).with(node).and_return(ignore)
123
+ end
124
+
125
+ context 'when comment disables the node' do
126
+ let(:ignore) { true }
127
+
128
+ it 'ignores the node' do
129
+ expect(object.ignore?(node)).to be(true)
130
+ end
131
+ end
132
+
133
+ context 'when comment does not disable the node' do
134
+ let(:ignore) { false }
135
+
136
+ it 'ignores the node' do
137
+ expect(object.ignore?(node)).to be(false)
138
+ end
139
+ end
140
+ end
141
+ end