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,46 @@
1
+ module Mutest
2
+ class Reporter
3
+ class CLI
4
+ class Printer
5
+ # Reporter for progressive output format on scheduler Status objects
6
+ class StatusProgressive < self
7
+ FORMAT = '(%02d/%02d) %3d%% - killtime: %0.02fs runtime: %0.02fs overhead: %0.02fs'.freeze
8
+
9
+ delegate(
10
+ :coverage,
11
+ :runtime,
12
+ :amount_mutations_killed,
13
+ :amount_mutations,
14
+ :amount_mutation_results,
15
+ :killtime,
16
+ :overhead
17
+ )
18
+
19
+ # Run printer
20
+ #
21
+ # @return [undefined]
22
+ def run
23
+ status(
24
+ FORMAT,
25
+ amount_mutations_killed,
26
+ amount_mutations,
27
+ coverage * 100,
28
+ killtime,
29
+ runtime,
30
+ overhead
31
+ )
32
+ end
33
+
34
+ private
35
+
36
+ # Object being printed
37
+ #
38
+ # @return [Result::Env]
39
+ def object
40
+ super().payload
41
+ end
42
+ end # StatusProgressive
43
+ end # Printer
44
+ end # CLI
45
+ end # Reporter
46
+ end # Mutest
@@ -0,0 +1,65 @@
1
+ module Mutest
2
+ class Reporter
3
+ class CLI
4
+ class Printer
5
+ # Reporter for subject progress
6
+ class SubjectProgress < self
7
+ FORMAT = '(%02d/%02d) %3d%% - killtime: %0.02fs runtime: %0.02fs overhead: %0.02fs'.freeze
8
+
9
+ delegate(
10
+ :tests,
11
+ :subject,
12
+ :coverage,
13
+ :runtime,
14
+ :amount_mutations_killed,
15
+ :amount_mutations,
16
+ :amount_mutation_results,
17
+ :killtime,
18
+ :overhead
19
+ )
20
+
21
+ # Run printer
22
+ #
23
+ # @return [undefined]
24
+ def run
25
+ puts("#{subject.identification} mutations: #{amount_mutations}")
26
+ print_mutation_results
27
+ print_progress_bar_finish
28
+ print_stats
29
+ end
30
+
31
+ private
32
+
33
+ # Print stats
34
+ #
35
+ # @return [undefined]
36
+ def print_stats
37
+ status(
38
+ FORMAT,
39
+ amount_mutations_killed,
40
+ amount_mutations,
41
+ coverage * 100,
42
+ killtime,
43
+ runtime,
44
+ overhead
45
+ )
46
+ end
47
+
48
+ # Print progress bar finish
49
+ #
50
+ # @return [undefined]
51
+ def print_progress_bar_finish
52
+ puts(nil) unless amount_mutation_results.zero?
53
+ end
54
+
55
+ # Print mutation results
56
+ #
57
+ # @return [undefined]
58
+ def print_mutation_results
59
+ visit_collection(MutationProgressResult, object.mutation_results)
60
+ end
61
+ end # SubjectProgress
62
+ end # Printer
63
+ end # CLI
64
+ end # Reporter
65
+ end # Mutest
@@ -0,0 +1,23 @@
1
+ module Mutest
2
+ class Reporter
3
+ class CLI
4
+ class Printer
5
+ # Subject result printer
6
+ class SubjectResult < self
7
+ delegate :subject, :alive_mutation_results, :tests
8
+
9
+ # Run report printer
10
+ #
11
+ # @return [undefined]
12
+ def run
13
+ status(subject.identification)
14
+ tests.each do |test|
15
+ puts("- #{test.identification}")
16
+ end
17
+ visit_collection(MutationResult, alive_mutation_results)
18
+ end
19
+ end # SubjectResult
20
+ end # Printer
21
+ end # CLI
22
+ end # Reporter
23
+ end # Mutest
@@ -0,0 +1,28 @@
1
+ module Mutest
2
+ class Reporter
3
+ class CLI
4
+ class Printer
5
+ # Test result reporter
6
+ class TestResult < self
7
+ delegate :tests, :runtime
8
+
9
+ STATUS_FORMAT = '- %d @ runtime: %s'.freeze
10
+ OUTPUT_HEADER = 'Test Output:'.freeze
11
+ TEST_FORMAT = ' - %s'.freeze
12
+
13
+ # Run test result reporter
14
+ #
15
+ # @return [undefined]
16
+ def run
17
+ info(STATUS_FORMAT, tests.length, runtime)
18
+ tests.each do |test|
19
+ info(TEST_FORMAT, test.identification)
20
+ end
21
+ puts(OUTPUT_HEADER)
22
+ puts(object.output)
23
+ end
24
+ end # TestResult
25
+ end # Printer
26
+ end # CLI
27
+ end # Reporter
28
+ end # Mutest
@@ -0,0 +1,43 @@
1
+ module Mutest
2
+ class Reporter
3
+ class CLI
4
+ # Interface to the optionally present tput binary
5
+ class Tput
6
+ include Adamantium, Concord::Public.new(:prepare, :restore)
7
+
8
+ private_class_method :new
9
+
10
+ # Detected tput support
11
+ #
12
+ # @return [Tput]
13
+ # if tput support is present
14
+ #
15
+ # @return [nil]
16
+ # otherwise
17
+ def self.detect
18
+ reset = capture('tput reset')
19
+ save = capture('tput sc') if reset
20
+ restore = capture('tput rc') if save
21
+ clean = capture('tput ed') || capture('tput cd') if restore
22
+ new(reset + save, restore + clean) if clean
23
+ end
24
+
25
+ # Capture output
26
+ #
27
+ # @param [String] command
28
+ # command to run
29
+ #
30
+ # @return [String]
31
+ # stdout of command on success
32
+ #
33
+ # @return [nil]
34
+ # otherwise
35
+ def self.capture(command)
36
+ stdout, _stderr, exitstatus = Open3.capture3(command)
37
+ stdout if exitstatus.success?
38
+ end
39
+ private_class_method :capture
40
+ end # Tput
41
+ end # CLI
42
+ end # Reporter
43
+ end # Mutest
@@ -0,0 +1,14 @@
1
+ module Mutest
2
+ class Reporter
3
+ # Null reporter
4
+ class Null < self
5
+ include Equalizer.new
6
+
7
+ %w[warn report start progress].each do |name|
8
+ define_method name do |_object|
9
+ self
10
+ end
11
+ end
12
+ end # Null
13
+ end # Reporter
14
+ end # Mutest
@@ -0,0 +1,24 @@
1
+ module Mutest
2
+ class Reporter
3
+ class Sequence < self
4
+ include Concord.new(:reporters)
5
+
6
+ %i[warn progress report start].each do |name|
7
+ define_method(name) do |value|
8
+ reporters.each do |reporter|
9
+ reporter.public_send(name, value)
10
+ end
11
+
12
+ self
13
+ end
14
+ end
15
+
16
+ # Minimum reporter delay
17
+ #
18
+ # @return [Float]
19
+ def delay
20
+ reporters.map(&:delay).min
21
+ end
22
+ end # Sequence
23
+ end # Reporter
24
+ end # Mutest
@@ -0,0 +1,80 @@
1
+ module Mutest
2
+ module Repository
3
+ # Error raised on repository interaction problems
4
+ RepositoryError = Class.new(RuntimeError)
5
+
6
+ # Subject filter based on repository diff
7
+ class SubjectFilter
8
+ include Adamantium, Concord.new(:diff)
9
+
10
+ # Test if subject was touched in diff
11
+ #
12
+ # @param [Subject] subject
13
+ #
14
+ # @return [Boolean]
15
+ def call(subject)
16
+ diff.touches?(subject.source_path, subject.source_lines)
17
+ end
18
+ end # SubjectFilter
19
+
20
+ # Diff between two objects in repository
21
+ class Diff
22
+ include Adamantium, Anima.new(:config, :from, :to)
23
+
24
+ HEAD = 'HEAD'.freeze
25
+
26
+ # Test if diff changes file at line range
27
+ #
28
+ # @param [Pathname] path
29
+ # @param [Range<Fixnum>] line_range
30
+ #
31
+ # @return [Boolean]
32
+ #
33
+ # @raise [RepositoryError]
34
+ # when git command failed
35
+ def touches?(path, line_range)
36
+ return false unless within_working_directory?(path) && tracks?(path)
37
+
38
+ command = %W[
39
+ git log
40
+ #{from}...#{to}
41
+ -L #{line_range.begin},#{line_range.end}:#{path}
42
+ ]
43
+
44
+ stdout, status = config.open3.capture2(*command, binmode: true)
45
+
46
+ fail RepositoryError, "Command #{command} failed!" unless status.success?
47
+
48
+ !stdout.empty?
49
+ end
50
+
51
+ private
52
+
53
+ # Test if path is tracked in repository
54
+ #
55
+ # FIXME: Cache results, to avoid spending time on producing redundant results.
56
+ #
57
+ # @param [Pathname] path
58
+ #
59
+ # @return [Boolean]
60
+ def tracks?(path)
61
+ command = %W[git ls-files --error-unmatch -- #{path}]
62
+ config.kernel.system(
63
+ *command,
64
+ out: File::NULL,
65
+ err: File::NULL
66
+ )
67
+ end
68
+
69
+ # Test if the path is within the current working directory
70
+ #
71
+ # @param [Pathname] path
72
+ #
73
+ # @return [TrueClass, nil]
74
+ def within_working_directory?(path)
75
+ working_directory = config.pathname.pwd
76
+ path.ascend { |parent| return true if working_directory.eql?(parent) }
77
+ end
78
+ end # Diff
79
+ end # Repository
80
+ end # Mutest
@@ -0,0 +1,24 @@
1
+ module Mutest
2
+ # Require highjack
3
+ module RequireHighjack
4
+ # Install require callback
5
+ #
6
+ # @param [Module] target
7
+ # @param [#call] callback
8
+ #
9
+ # @return [#call]
10
+ # the original implementation on singleton
11
+ def self.call(target, callback)
12
+ target.public_method(:require).tap do
13
+ target.module_eval do
14
+ undef_method(:require)
15
+ define_method(:require, &callback)
16
+ class << self
17
+ undef_method(:require)
18
+ end
19
+ define_singleton_method(:require, &callback)
20
+ end
21
+ end
22
+ end
23
+ end # RequireHighjack
24
+ end # Mutest
@@ -0,0 +1,212 @@
1
+ module Mutest
2
+ # Namespace and mixin module for results
3
+ module Result
4
+ # Coverage mixin
5
+ module Coverage
6
+ FULL_COVERAGE = Rational(1).freeze
7
+ private_constant(*constants(false))
8
+
9
+ # Observed coverage
10
+ #
11
+ # @return [Rational]
12
+ def coverage
13
+ if amount_mutation_results.zero?
14
+ FULL_COVERAGE
15
+ else
16
+ Rational(amount_mutations_killed, amount_mutation_results)
17
+ end
18
+ end
19
+ end # Coverage
20
+
21
+ # Class level mixin
22
+ module ClassMethods
23
+ # Generate a sum method from name and collection
24
+ #
25
+ # @param [Symbol] name
26
+ # the attribute name on collection item and method name to use
27
+ #
28
+ # @param [Symbol] collection
29
+ # the attribute name used to receive collection
30
+ #
31
+ # @return [undefined]
32
+ def sum(name, collection)
33
+ define_method(name) do
34
+ public_send(collection).map(&name).reduce(0, :+)
35
+ end
36
+ memoize(name)
37
+ end
38
+ end # ClassMethods
39
+
40
+ private_constant(*constants(false))
41
+
42
+ # Mutest overhead running mutatet tests
43
+ #
44
+ # This is NOT the overhead of mutation testing, just an engine specific
45
+ # measurement for the efficiency of the parallelization engine, kill
46
+ # isolation etc.
47
+ #
48
+ # @return [Float]
49
+ def overhead
50
+ runtime - killtime
51
+ end
52
+
53
+ # Hook called when module gets included
54
+ #
55
+ # @param [Class, Module] host
56
+ #
57
+ # @return [undefined]
58
+ def self.included(host)
59
+ host.class_eval do
60
+ include Adamantium
61
+ extend ClassMethods
62
+ end
63
+ end
64
+
65
+ # Env result object
66
+ class Env
67
+ include Coverage, Result, Anima.new(
68
+ :env,
69
+ :runtime,
70
+ :subject_results
71
+ )
72
+
73
+ # Test if run is successful
74
+ #
75
+ # @return [Boolean]
76
+ def success?
77
+ coverage.eql?(Rational(1))
78
+ end
79
+ memoize :success?
80
+
81
+ # Failed subject results
82
+ #
83
+ # @return [Array<Result::Subject>]
84
+ def failed_subject_results
85
+ subject_results.reject(&:success?)
86
+ end
87
+
88
+ sum :amount_mutation_results, :subject_results
89
+ sum :amount_mutations_alive, :subject_results
90
+ sum :amount_mutations_killed, :subject_results
91
+ sum :killtime, :subject_results
92
+
93
+ # Amount of mutations
94
+ #
95
+ # @return [Fixnum]
96
+ def amount_mutations
97
+ env.mutations.length
98
+ end
99
+
100
+ # Amount of subjects
101
+ #
102
+ # @return [Fixnum]
103
+ def amount_subjects
104
+ env.subjects.length
105
+ end
106
+ end # Env
107
+
108
+ # Test result
109
+ class Test
110
+ include Result, Anima.new(
111
+ :output,
112
+ :passed,
113
+ :runtime,
114
+ :tests
115
+ )
116
+ end # Test
117
+
118
+ # Subject result
119
+ class Subject
120
+ include Coverage, Result, Anima.new(
121
+ :mutation_results,
122
+ :subject,
123
+ :tests
124
+ )
125
+
126
+ sum :killtime, :mutation_results
127
+ sum :runtime, :mutation_results
128
+
129
+ # Test if subject was processed successful
130
+ #
131
+ # @return [Boolean]
132
+ def success?
133
+ alive_mutation_results.empty?
134
+ end
135
+
136
+ # Alive mutations
137
+ #
138
+ # @return [Array<Result::Mutation>]
139
+ def alive_mutation_results
140
+ mutation_results.reject(&:success?)
141
+ end
142
+ memoize :alive_mutation_results
143
+
144
+ # Amount of mutations
145
+ #
146
+ # @return [Fixnum]
147
+ def amount_mutation_results
148
+ mutation_results.length
149
+ end
150
+
151
+ # Amount of mutations
152
+ #
153
+ # @return [Fixnum]
154
+ def amount_mutations
155
+ subject.mutations.length
156
+ end
157
+
158
+ # Number of killed mutations
159
+ #
160
+ # @return [Fixnum]
161
+ def amount_mutations_killed
162
+ killed_mutation_results.length
163
+ end
164
+
165
+ # Number of alive mutations
166
+ #
167
+ # @return [Fixnum]
168
+ def amount_mutations_alive
169
+ alive_mutation_results.length
170
+ end
171
+
172
+ private
173
+
174
+ # Killed mutation results
175
+ #
176
+ # @return [Array<Result::Mutation>]
177
+ def killed_mutation_results
178
+ mutation_results.select(&:success?)
179
+ end
180
+ memoize :killed_mutation_results
181
+ end # Subject
182
+
183
+ # Mutation result
184
+ class Mutation
185
+ include Result, Anima.new(
186
+ :mutation,
187
+ :test_result
188
+ )
189
+
190
+ # The runtime
191
+ #
192
+ # @return [Float]
193
+ def runtime
194
+ test_result.runtime
195
+ end
196
+
197
+ # The time spent on killing
198
+ #
199
+ # @return [Float]
200
+ #
201
+ # @api private
202
+ alias_method :killtime, :runtime
203
+
204
+ # Test if mutation was handled successfully
205
+ #
206
+ # @return [Boolean]
207
+ def success?
208
+ mutation.class.success?(test_result)
209
+ end
210
+ end # Mutation
211
+ end # Result
212
+ end # Mutest