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,55 @@
1
+ module Mutest
2
+ # Abstract base class for match expression
3
+ class Expression
4
+ include AbstractType, Adamantium::Flat
5
+
6
+ fragment = /[A-Za-z][A-Za-z\d_]*/
7
+ SCOPE_NAME_PATTERN = /(?<scope_name>#{fragment}(?:#{SCOPE_OPERATOR}#{fragment})*)/
8
+ SCOPE_SYMBOL_PATTERN = '(?<scope_symbol>[.#])'.freeze
9
+
10
+ private_constant(*constants(false))
11
+
12
+ # Syntax of expression
13
+ #
14
+ # @return [String]
15
+ abstract_method :syntax
16
+
17
+ # Match length with other expression
18
+ #
19
+ # @param [Expression] other
20
+ #
21
+ # @return [Fixnum]
22
+ def match_length(other)
23
+ if eql?(other)
24
+ syntax.length
25
+ else
26
+ 0
27
+ end
28
+ end
29
+
30
+ # Test if expression is prefix
31
+ #
32
+ # @param [Expression] other
33
+ #
34
+ # @return [Boolean]
35
+ def prefix?(other)
36
+ !match_length(other).zero?
37
+ end
38
+
39
+ # Try to parse input into expression of receiver class
40
+ #
41
+ # @param [String] input
42
+ #
43
+ # @return [Expression]
44
+ # when successful
45
+ #
46
+ # @return [nil]
47
+ # otherwise
48
+ def self.try_parse(input)
49
+ match = self::REGEXP.match(input)
50
+ return unless match
51
+ names = anima.attribute_names
52
+ new(Hash[names.zip(names.map(&match.method(:[])))])
53
+ end
54
+ end # Expression
55
+ end # Mutest
@@ -0,0 +1,54 @@
1
+ module Mutest
2
+ class Expression
3
+ # Explicit method expression
4
+ class Method < self
5
+ include Anima.new(
6
+ :method_name,
7
+ :scope_name,
8
+ :scope_symbol
9
+ )
10
+
11
+ private(*anima.attribute_names)
12
+
13
+ MATCHERS = IceNine.deep_freeze(
14
+ '.' => Matcher::Methods::Singleton,
15
+ '#' => Matcher::Methods::Instance
16
+ )
17
+
18
+ METHOD_NAME_PATTERN = Regexp.union(
19
+ /(?<method_name>[A-Za-z_][A-Za-z\d_]*[!?=]?)/,
20
+ *AST::Types::OPERATOR_METHODS.map(&:to_s)
21
+ ).freeze
22
+
23
+ private_constant(*constants(false))
24
+
25
+ REGEXP = /\A#{SCOPE_NAME_PATTERN}#{SCOPE_SYMBOL_PATTERN}#{METHOD_NAME_PATTERN}\z/
26
+
27
+ # Syntax of expression
28
+ #
29
+ # @return [String]
30
+ def syntax
31
+ [scope_name, scope_symbol, method_name].join
32
+ end
33
+ memoize :syntax
34
+
35
+ # Matcher for expression
36
+ #
37
+ # @return [Matcher]
38
+ def matcher
39
+ methods_matcher = MATCHERS.fetch(scope_symbol).new(scope)
40
+
41
+ Matcher::Filter.new(methods_matcher, ->(subject) { subject.expression.eql?(self) })
42
+ end
43
+
44
+ private
45
+
46
+ # Scope object
47
+ #
48
+ # @return [Class, Method]
49
+ def scope
50
+ Object.const_get(scope_name)
51
+ end
52
+ end # Method
53
+ end # Expression
54
+ end # Mutest
@@ -0,0 +1,58 @@
1
+ module Mutest
2
+ class Expression
3
+ # Abstract base class for methods expression
4
+ class Methods < self
5
+ include Anima.new(
6
+ :scope_name,
7
+ :scope_symbol
8
+ )
9
+
10
+ private(*anima.attribute_names)
11
+
12
+ MATCHERS = IceNine.deep_freeze(
13
+ '.' => Matcher::Methods::Singleton,
14
+ '#' => Matcher::Methods::Instance
15
+ )
16
+ private_constant(*constants(false))
17
+
18
+ REGEXP = /\A#{SCOPE_NAME_PATTERN}#{SCOPE_SYMBOL_PATTERN}\z/
19
+
20
+ # Syntax of expression
21
+ #
22
+ # @return [String]
23
+ def syntax
24
+ [scope_name, scope_symbol].join
25
+ end
26
+ memoize :syntax
27
+
28
+ # Matcher on expression
29
+ #
30
+ # @return [Matcher::Method]
31
+ def matcher
32
+ MATCHERS.fetch(scope_symbol).new(scope)
33
+ end
34
+
35
+ # Length of match with other expression
36
+ #
37
+ # @param [Expression] expression
38
+ #
39
+ # @return [Fixnum]
40
+ def match_length(expression)
41
+ if expression.syntax.start_with?(syntax)
42
+ syntax.length
43
+ else
44
+ 0
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # Scope object
51
+ #
52
+ # @return [Class, Method]
53
+ def scope
54
+ Object.const_get(scope_name)
55
+ end
56
+ end # Methods
57
+ end # Expression
58
+ end # Mutest
@@ -0,0 +1,75 @@
1
+ module Mutest
2
+ class Expression
3
+ # Abstract base class for expressions matching namespaces
4
+ class Namespace < self
5
+ include AbstractType, Anima.new(:scope_name)
6
+ private(*anima.attribute_names)
7
+
8
+ # Recursive namespace expression
9
+ class Recursive < self
10
+ REGEXP = /\A#{SCOPE_NAME_PATTERN}?\*\z/
11
+
12
+ # Initialize object
13
+ #
14
+ # @return [undefined]
15
+ def initialize(*)
16
+ super
17
+ @recursion_pattern = Regexp.union(
18
+ /\A#{scope_name}\z/,
19
+ /\A#{scope_name}::/,
20
+ /\A#{scope_name}[.#]/
21
+ )
22
+ end
23
+
24
+ # Syntax for expression
25
+ #
26
+ # @return [String]
27
+ def syntax
28
+ "#{scope_name}*"
29
+ end
30
+ memoize :syntax
31
+
32
+ # Matcher for expression
33
+ #
34
+ # @return [Matcher]
35
+ def matcher
36
+ Matcher::Namespace.new(self)
37
+ end
38
+
39
+ # Length of match with other expression
40
+ #
41
+ # @param [Expression] expression
42
+ #
43
+ # @return [Fixnum]
44
+ def match_length(expression)
45
+ if @recursion_pattern =~ expression.syntax
46
+ scope_name.length
47
+ else
48
+ 0
49
+ end
50
+ end
51
+ end # Recursive
52
+
53
+ # Exact namespace expression
54
+ class Exact < self
55
+ MATCHER = Matcher::Scope
56
+ private_constant(*constants(false))
57
+
58
+ REGEXP = /\A#{SCOPE_NAME_PATTERN}\z/
59
+
60
+ # Matcher matcher on expression
61
+ #
62
+ # @return [Matcher]
63
+ def matcher
64
+ Matcher::Scope.new(Object.const_get(scope_name))
65
+ end
66
+
67
+ # Syntax for expression
68
+ #
69
+ # @return [String]
70
+ alias_method :syntax, :scope_name
71
+ public :syntax
72
+ end # Exact
73
+ end # Namespace
74
+ end # Expression
75
+ end # Mutest
@@ -0,0 +1,64 @@
1
+ module Mutest
2
+ class Expression
3
+ class Parser
4
+ include Concord.new(:types)
5
+
6
+ class ParserError < RuntimeError
7
+ include AbstractType
8
+ end # ParserError
9
+
10
+ # Error raised on invalid expressions
11
+ class InvalidExpressionError < ParserError; end
12
+
13
+ # Error raised on ambiguous expressions
14
+ class AmbiguousExpressionError < ParserError; end
15
+
16
+ # Parse input into expression or raise
17
+ #
18
+ # @param [String] syntax
19
+ #
20
+ # @return [Expression]
21
+ # if expression is valid
22
+ #
23
+ # @raise [ParserError]
24
+ # otherwise
25
+ def call(input)
26
+ try_parse(input) or fail InvalidExpressionError, "Expression: #{input.inspect} is not valid"
27
+ end
28
+
29
+ # Try to parse input into expression
30
+ #
31
+ # @param [String] input
32
+ #
33
+ # @return [Expression]
34
+ # if expression is valid
35
+ #
36
+ # @return [nil]
37
+ # otherwise
38
+ def try_parse(input)
39
+ expressions = expressions(input)
40
+ case expressions.length
41
+ when 0, 1
42
+ expressions.first
43
+ else
44
+ fail AmbiguousExpressionError, "Ambiguous expression: #{input.inspect}"
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # Expressions parsed from input
51
+ #
52
+ # @param [String] input
53
+ #
54
+ # @return [Array<Expression>]
55
+ # if expressions can be parsed from input
56
+ def expressions(input)
57
+ types.each_with_object([]) do |type, aggregate|
58
+ expression = type.try_parse(input)
59
+ aggregate << expression if expression
60
+ end
61
+ end
62
+ end # Parser
63
+ end # Expression
64
+ end # Mutest
@@ -0,0 +1,75 @@
1
+ module Mutest
2
+ # Abstract base class mutest test framework integrations
3
+ class Integration
4
+ include AbstractType, Adamantium::Flat, Concord.new(:config)
5
+
6
+ # Setup integration
7
+ #
8
+ # Integrations are supposed to define a constant under
9
+ # Mutest::Integration named after the capitalized +name+
10
+ # parameter.
11
+ #
12
+ # This avoids having to maintain a mutable registry.
13
+ #
14
+ # @param kernel [Kernel]
15
+ # @param name [String]
16
+ #
17
+ # @return [Class<Integration>]
18
+ def self.setup(kernel, name)
19
+ kernel.require("mutest/integration/#{name}")
20
+ const_get(name.capitalize)
21
+ end
22
+
23
+ # Perform integration setup
24
+ #
25
+ # @return [self]
26
+ def setup
27
+ self
28
+ end
29
+
30
+ # Run a collection of tests
31
+ #
32
+ # @param [Enumerable<Test>] tests
33
+ #
34
+ # @return [Result::Test]
35
+ abstract_method :call
36
+
37
+ # Available tests for integration
38
+ #
39
+ # @return [Enumerable<Test>]
40
+ abstract_method :all_tests
41
+
42
+ private
43
+
44
+ # Expression parser
45
+ #
46
+ # @return [Expression::Parser]
47
+ def expression_parser
48
+ config.expression_parser
49
+ end
50
+
51
+ # Null integration that never kills a mutation
52
+ class Null < self
53
+ # Available tests for integration
54
+ #
55
+ # @return [Enumerable<Test>]
56
+ def all_tests
57
+ EMPTY_ARRAY
58
+ end
59
+
60
+ # Run a collection of tests
61
+ #
62
+ # @param [Enumerable<Mutest::Test>] tests
63
+ #
64
+ # @return [Result::Test]
65
+ def call(tests)
66
+ Result::Test.new(
67
+ output: '',
68
+ passed: true,
69
+ runtime: 0.0,
70
+ tests: tests
71
+ )
72
+ end
73
+ end # Null
74
+ end # Integration
75
+ end # Mutest
@@ -0,0 +1,11 @@
1
+ module Mutest
2
+ class Isolation
3
+ include AbstractType
4
+
5
+ # Call block in isolation
6
+ #
7
+ # @return [Object]
8
+ # the blocks result
9
+ abstract_method :call
10
+ end # Isolation
11
+ end # Mutest
@@ -0,0 +1,72 @@
1
+ module Mutest
2
+ class Isolation
3
+ # Isolation via the fork(2) systemcall.
4
+ #
5
+ # We do inject so many globals and common patterns to make this unit
6
+ # specifiable without mocking the globals and more important: Not having
7
+ # mutations that bypass mocks into a real world side effect.
8
+ class Fork < self
9
+ include Anima.new(:process, :stderr, :stdout, :io, :devnull, :marshal)
10
+
11
+ # Prevent mutation from `process.fork` to `fork` to call Kernel#fork
12
+ undef_method :fork
13
+
14
+ # Call block in isolation
15
+ #
16
+ # @return [Object]
17
+ # returns block execution result
18
+ #
19
+ # @raise [Error]
20
+ # if block terminates abnormal
21
+ def call(&block)
22
+ io.pipe(binmode: true) do |pipes|
23
+ parent(*pipes, &block)
24
+ end
25
+ rescue => exception
26
+ raise Error, exception
27
+ end
28
+
29
+ # Handle parent process
30
+ #
31
+ # @param [IO] reader
32
+ # @param [IO] writer
33
+ #
34
+ # @return [undefined]
35
+ def parent(reader, writer, &block)
36
+ pid =
37
+ process.fork do
38
+ child(reader, writer, &block)
39
+ end
40
+
41
+ writer.close
42
+ marshal.load(reader)
43
+ ensure
44
+ process.waitpid(pid) if pid
45
+ end
46
+
47
+ # Handle child process
48
+ #
49
+ # @param [IO] reader
50
+ # @param [IO] writer
51
+ #
52
+ # @return [undefined]
53
+ def child(reader, writer, &block)
54
+ reader.close
55
+ writer.binmode
56
+ writer.syswrite(marshal.dump(result(&block)))
57
+ writer.close
58
+ end
59
+
60
+ # The block result computed under silencing
61
+ #
62
+ # @return [Object]
63
+ def result
64
+ devnull.call do |null|
65
+ stderr.reopen(null)
66
+ stdout.reopen(null)
67
+ yield
68
+ end
69
+ end
70
+ end # Fork
71
+ end # Isolation
72
+ end # Mutest