mutant 0.5.26 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.travis.yml +1 -0
  4. data/Changelog.md +16 -3
  5. data/Gemfile +0 -2
  6. data/Gemfile.devtools +2 -2
  7. data/README.md +9 -15
  8. data/bin/mutant +0 -1
  9. data/config/flay.yml +1 -1
  10. data/config/flog.yml +1 -1
  11. data/config/mutant.yml +1 -1
  12. data/config/reek.yml +14 -11
  13. data/config/rubocop.yml +1 -1
  14. data/lib/mutant.rb +22 -21
  15. data/lib/mutant/ast.rb +47 -0
  16. data/lib/mutant/cli.rb +7 -4
  17. data/lib/mutant/config.rb +1 -0
  18. data/lib/mutant/context.rb +1 -1
  19. data/lib/mutant/diff.rb +38 -7
  20. data/lib/mutant/env.rb +22 -3
  21. data/lib/mutant/expression.rb +15 -4
  22. data/lib/mutant/integration.rb +1 -1
  23. data/lib/mutant/isolation.rb +2 -4
  24. data/lib/mutant/matcher.rb +1 -1
  25. data/lib/mutant/matcher/method.rb +1 -1
  26. data/lib/mutant/matcher/method/singleton.rb +1 -1
  27. data/lib/mutant/matcher/methods.rb +0 -2
  28. data/lib/mutant/meta/example.rb +0 -2
  29. data/lib/mutant/meta/example/dsl.rb +1 -1
  30. data/lib/mutant/mutator.rb +1 -1
  31. data/lib/mutant/mutator/node.rb +3 -3
  32. data/lib/mutant/mutator/node/begin.rb +1 -1
  33. data/lib/mutant/mutator/node/block.rb +16 -3
  34. data/lib/mutant/mutator/node/if.rb +1 -1
  35. data/lib/mutant/mutator/node/literal/fixnum.rb +1 -1
  36. data/lib/mutant/mutator/node/resbody.rb +0 -2
  37. data/lib/mutant/mutator/node/send.rb +17 -7
  38. data/lib/mutant/mutator/node/send/index.rb +0 -2
  39. data/lib/mutant/mutator/registry.rb +1 -1
  40. data/lib/mutant/mutator/util.rb +1 -1
  41. data/lib/mutant/mutator/util/array.rb +1 -1
  42. data/lib/mutant/reporter.rb +13 -3
  43. data/lib/mutant/reporter/cli.rb +54 -8
  44. data/lib/mutant/reporter/cli/format.rb +197 -0
  45. data/lib/mutant/reporter/cli/printer.rb +402 -22
  46. data/lib/mutant/reporter/cli/tput.rb +27 -0
  47. data/lib/mutant/reporter/null.rb +4 -34
  48. data/lib/mutant/reporter/trace.rb +6 -38
  49. data/lib/mutant/result.rb +44 -56
  50. data/lib/mutant/runner.rb +99 -52
  51. data/lib/mutant/runner/collector.rb +134 -0
  52. data/lib/mutant/subject/method/instance.rb +12 -4
  53. data/lib/mutant/version.rb +1 -1
  54. data/lib/mutant/warning_filter.rb +0 -2
  55. data/lib/mutant/zombifier/file.rb +1 -1
  56. data/meta/block.rb +17 -1
  57. data/meta/send.rb +123 -1
  58. data/mutant-rspec.gemspec +3 -3
  59. data/mutant.gemspec +1 -1
  60. data/spec/integration/mutant/corpus_spec.rb +4 -195
  61. data/spec/integration/mutant/null_spec.rb +1 -3
  62. data/spec/integration/mutant/rspec_spec.rb +1 -3
  63. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +1 -3
  64. data/spec/integration/mutant/zombie_spec.rb +1 -3
  65. data/spec/integrations.yml +7 -0
  66. data/spec/shared/method_matcher_behavior.rb +1 -1
  67. data/spec/spec_helper.rb +1 -0
  68. data/spec/support/compress_helper.rb +1 -0
  69. data/spec/support/corpus.rb +239 -0
  70. data/spec/support/mutation_verifier.rb +2 -4
  71. data/spec/unit/mutant/cli_spec.rb +20 -13
  72. data/spec/unit/mutant/context/root_spec.rb +1 -3
  73. data/spec/unit/mutant/context/scope/root_spec.rb +1 -3
  74. data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +1 -3
  75. data/spec/unit/mutant/diff_spec.rb +37 -19
  76. data/spec/unit/mutant/expression/method_spec.rb +5 -7
  77. data/spec/unit/mutant/expression/methods_spec.rb +5 -7
  78. data/spec/unit/mutant/expression/namespace/flat_spec.rb +6 -8
  79. data/spec/unit/mutant/expression/namespace/recursive_spec.rb +6 -7
  80. data/spec/unit/mutant/expression_spec.rb +14 -5
  81. data/spec/unit/mutant/integration_spec.rb +14 -3
  82. data/spec/unit/mutant/isolation_spec.rb +2 -4
  83. data/spec/unit/mutant/loader/eval_spec.rb +1 -3
  84. data/spec/unit/mutant/matcher/chain_spec.rb +1 -3
  85. data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +21 -0
  86. data/spec/unit/mutant/matcher/compiler_spec.rb +28 -3
  87. data/spec/unit/mutant/matcher/filter_spec.rb +1 -3
  88. data/spec/unit/mutant/matcher/method/instance_spec.rb +3 -5
  89. data/spec/unit/mutant/matcher/method/singleton_spec.rb +22 -4
  90. data/spec/unit/mutant/matcher/methods/instance_spec.rb +7 -6
  91. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +4 -6
  92. data/spec/unit/mutant/matcher/namespace_spec.rb +1 -3
  93. data/spec/unit/mutant/matcher/null_spec.rb +1 -3
  94. data/spec/unit/mutant/mutation_spec.rb +1 -3
  95. data/spec/unit/mutant/mutator/node_spec.rb +1 -3
  96. data/spec/unit/mutant/reporter/cli_spec.rb +444 -206
  97. data/spec/unit/mutant/reporter/null_spec.rb +1 -3
  98. data/spec/unit/mutant/require_highjack_spec.rb +1 -3
  99. data/spec/unit/mutant/runner_spec.rb +42 -28
  100. data/spec/unit/mutant/subject/context_spec.rb +1 -3
  101. data/spec/unit/mutant/subject/method/instance_spec.rb +27 -19
  102. data/spec/unit/mutant/subject/method/singleton_spec.rb +49 -17
  103. data/spec/unit/mutant/subject_spec.rb +1 -3
  104. data/spec/unit/mutant/test_spec.rb +1 -3
  105. data/spec/unit/mutant/warning_expectation.rb +1 -3
  106. data/spec/unit/mutant/warning_filter_spec.rb +1 -3
  107. data/spec/unit/mutant_spec.rb +13 -3
  108. data/test_app/Gemfile.devtools +2 -2
  109. data/test_app/spec/unit/test_app/literal/string_spec.rb +1 -1
  110. metadata +10 -21
  111. data/lib/mutant/matcher/method/finder.rb +0 -72
  112. data/lib/mutant/reporter/cli/progress.rb +0 -10
  113. data/lib/mutant/reporter/cli/progress/config.rb +0 -30
  114. data/lib/mutant/reporter/cli/progress/env.rb +0 -30
  115. data/lib/mutant/reporter/cli/progress/noop.rb +0 -27
  116. data/lib/mutant/reporter/cli/progress/result.rb +0 -12
  117. data/lib/mutant/reporter/cli/progress/result/mutation.rb +0 -45
  118. data/lib/mutant/reporter/cli/progress/result/subject.rb +0 -54
  119. data/lib/mutant/reporter/cli/progress/subject.rb +0 -27
  120. data/lib/mutant/reporter/cli/registry.rb +0 -81
  121. data/lib/mutant/reporter/cli/report.rb +0 -10
  122. data/lib/mutant/reporter/cli/report/env.rb +0 -92
  123. data/lib/mutant/reporter/cli/report/mutation.rb +0 -103
  124. data/lib/mutant/reporter/cli/report/subject.rb +0 -32
  125. data/lib/mutant/reporter/cli/report/test.rb +0 -28
  126. data/lib/mutant/walker.rb +0 -53
  127. data/spec/shared/mutator_behavior.rb +0 -55
@@ -1,72 +0,0 @@
1
- module Mutant
2
- class Matcher
3
- class Method
4
-
5
- # Visitor to find last match inside AST
6
- class Finder
7
-
8
- # Run finder
9
- #
10
- # @param [Parser::AST::Node]
11
- #
12
- # @return [Parser::AST::Node]
13
- # if found
14
- #
15
- # @return [nil]
16
- # otherwise
17
- #
18
- # @api private
19
- #
20
- #
21
- def self.run(root, &predicate)
22
- new(root, predicate).match
23
- end
24
-
25
- private_class_method :new
26
-
27
- # Return match
28
- #
29
- # @return [Parser::AST::Node]
30
- #
31
- # @api private
32
- #
33
- attr_reader :match
34
-
35
- private
36
-
37
- # Initialize object
38
- #
39
- # @param [Parer::AST::Node]
40
- #
41
- # @return [undefined]
42
- #
43
- # @api private
44
- #
45
- #
46
- def initialize(root, predicate)
47
- @root, @predicate = root, predicate
48
- visit(root)
49
- end
50
-
51
- # Visit node
52
- #
53
- # @param [Parser::AST::Node] node
54
- #
55
- # @return [undefined]
56
- #
57
- # @api private
58
- #
59
- def visit(node)
60
- if @predicate.call(node)
61
- @match = node
62
- end
63
-
64
- node.children.each do |child|
65
- visit(child) if child.kind_of?(Parser::AST::Node)
66
- end
67
- end
68
-
69
- end # Finder
70
- end # Method
71
- end # Matcher
72
- end # Mutant
@@ -1,10 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- # Abstract base and namespace class for process printers
5
- class Progress < Printer
6
- include AbstractType, Registry.new
7
- end # Progress
8
- end # CLI
9
- end # Reporter
10
- end # Mutant
@@ -1,30 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Progress
5
- # Progress printer for configuration
6
- class Config < self
7
-
8
- handle(Mutant::Config)
9
-
10
- # Report configuration
11
- #
12
- # @param [Mutant::Config] config
13
- #
14
- # @return [self]
15
- #
16
- # @api private
17
- #
18
- def run
19
- info 'Mutant configuration:'
20
- info 'Matcher: %s', object.matcher_config.inspect
21
- info 'Integration: %s', object.integration.name
22
- info 'Expect Coverage: %0.2f%%', object.expected_coverage.inspect
23
- self
24
- end
25
-
26
- end # Progress
27
- end # Printer
28
- end # CLI
29
- end # Reporter
30
- end # Mutant
@@ -1,30 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Progress
5
- # Progress printer for configuration
6
- class Env < self
7
-
8
- handle Mutant::Env
9
-
10
- delegate :config
11
-
12
- # Report configuration
13
- #
14
- # @param [Mutant::Config] config
15
- #
16
- # @return [self]
17
- #
18
- # @api private
19
- #
20
- def run
21
- visit(config)
22
- info 'Available Subjects: %d', object.matchable_scopes.length
23
- info 'Subjects: %d', object.subjects.length
24
- end
25
-
26
- end # Progress
27
- end # Printer
28
- end # CLI
29
- end # Reporter
30
- end # Mutant
@@ -1,27 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Progress
5
- # Noop CLI progress reporter
6
- class Noop < self
7
-
8
- handle(Mutant::Test)
9
- handle(Mutant::Mutation)
10
- handle(Mutant::Result::Env)
11
- handle(Mutant::Result::Test)
12
-
13
- # Noop progress report
14
- #
15
- # @return [self]
16
- #
17
- # @api private
18
- #
19
- def run
20
- self
21
- end
22
-
23
- end # Noop
24
- end # Progress
25
- end # CLI
26
- end # Reporter
27
- end # Mutant
@@ -1,12 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Progress
5
- # Abstract namespace class for result progress printers
6
- class Result < self
7
- include AbstractType
8
- end # Result
9
- end # Progress
10
- end # CLI
11
- end # Reporter
12
- end # Mutant
@@ -1,45 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Progress
5
- class Result
6
- # Mutation test result progress reporter
7
- class Mutation < self
8
-
9
- handle(Mutant::Result::Mutation)
10
-
11
- SUCCESS = '.'.freeze
12
- FAILURE = 'F'.freeze
13
-
14
- # Run printer
15
- #
16
- # @return [self]
17
- #
18
- # @api private
19
- #
20
- def run
21
- char(success? ? SUCCESS : FAILURE)
22
- self
23
- end
24
-
25
- private
26
-
27
- # Write colorized char
28
- #
29
- # @param [String] char
30
- #
31
- # @return [undefined]
32
- #
33
- # @api private
34
- #
35
- def char(char)
36
- output.write(colorize(status_color, char))
37
- output.flush
38
- end
39
-
40
- end # Mutation
41
- end # Result
42
- end # Progress
43
- end # CLI
44
- end # Reporter
45
- end # Mutant
@@ -1,54 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Progress
5
- class Result
6
- # Reporter for subject runners
7
- class Subject < self
8
-
9
- FORMAT = '(%02d/%02d) %3d%% - killtime: %0.02fs runtime: %0.02fs overhead: %0.02fs'.freeze
10
-
11
- handle(Mutant::Result::Subject)
12
-
13
- # Run printer
14
- #
15
- # @return [self]
16
- #
17
- # @api private
18
- #
19
- def run
20
- print_progress_bar_finish
21
- print_stats
22
- self
23
- end
24
-
25
- delegate :coverage, :runtime, :amount_mutations_killed, :amount_mutations, :killtime, :overhead
26
-
27
- private
28
-
29
- # Print stats
30
- #
31
- # @return [undefined]
32
- #
33
- # @api private
34
- #
35
- def print_stats
36
- status(FORMAT, amount_mutations_killed, amount_mutations, coverage * 100, killtime, runtime, overhead)
37
- end
38
-
39
- # Print progress bar finish
40
- #
41
- # @return [undefined]
42
- #
43
- # @api private
44
- #
45
- def print_progress_bar_finish
46
- puts unless amount_mutations.zero?
47
- end
48
-
49
- end # Subject
50
- end # Result
51
- end # Progress
52
- end # CLI
53
- end # Reporter
54
- end # Mutant
@@ -1,27 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Progress
5
- # CLI progress reporter for subjects
6
- class Subject < self
7
-
8
- handle Mutant::Subject
9
-
10
- # Run printer
11
- #
12
- # @return [undefined]
13
- #
14
- # @api private
15
- #
16
- def run
17
- puts("#{object.identification} mutations: #{object.mutations.length}")
18
- object.tests.each do |test|
19
- puts "- #{test.identification}"
20
- end
21
- end
22
-
23
- end # Subject
24
- end # Progress
25
- end # CLI
26
- end # Reporter
27
- end # Mutant
@@ -1,81 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- # Mixin to generate registry semantics
5
- class Registry < Module
6
- include Concord.new(:registry)
7
-
8
- # Return new registry
9
- #
10
- # @return [Registry]
11
- #
12
- # @api private
13
- #
14
- def self.new
15
- super({})
16
- end
17
-
18
- # Register handler for class
19
- #
20
- # @param [Class] klass
21
- #
22
- # @return [self]
23
- #
24
- # @api private
25
- #
26
- def handle(subject, handler)
27
- raise "Duplicate registration of #{subject}" if registry.key?(subject)
28
- registry[subject] = handler
29
- self
30
- end
31
-
32
- # Lookup handler
33
- #
34
- # @param [Class] subject
35
- #
36
- # @return [Object]
37
- # if found
38
- #
39
- # @raise [RuntimeError]
40
- # otherwise
41
- #
42
- # @api private
43
- #
44
- def lookup(subject)
45
- current = subject
46
- until current.equal?(Object)
47
- if registry.key?(current)
48
- return registry.fetch(current)
49
- end
50
- current = current.superclass
51
- end
52
- raise "No printer for: #{subject}"
53
- end
54
-
55
- # Hook called when module is included
56
- #
57
- # @param [Class,Module] host
58
- #
59
- # @return [undefined]
60
- #
61
- # @api private
62
- #
63
- def included(host)
64
- super
65
-
66
- object = self
67
- host.class_eval do
68
- define_singleton_method(:lookup, &object.method(:lookup))
69
- private_class_method :lookup
70
-
71
- define_singleton_method(:handle) do |subject|
72
- object.handle(subject, self)
73
- end
74
- private_class_method :handle
75
- end
76
- end
77
-
78
- end # Registry
79
- end # CLI
80
- end # Reporter
81
- end # Mutant
@@ -1,10 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- # Abstract base class for process printers
5
- class Report < Printer
6
- include AbstractType, Registry.new
7
- end # Report
8
- end # CLI
9
- end # Reporter
10
- end # Mutant
@@ -1,92 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Report
5
-
6
- # Env result reporter
7
- class Env < self
8
-
9
- handle(Result::Env)
10
-
11
- delegate(
12
- :coverage, :failed_subject_results, :amount_subjects, :amount_mutations,
13
- :amount_mutations_alive, :amount_mutations_killed, :runtime, :killtime, :overhead, :env
14
- )
15
-
16
- # Run printer
17
- #
18
- # @return [self]
19
- #
20
- # @api private
21
- #
22
- def run
23
- visit_collection(failed_subject_results)
24
- info 'Subjects: %s', amount_subjects
25
- info 'Mutations: %s', amount_mutations
26
- info 'Kills: %s', amount_mutations_killed
27
- info 'Alive: %s', amount_mutations_alive
28
- info 'Runtime: %0.2fs', runtime
29
- info 'Killtime: %0.2fs', killtime
30
- info 'Overhead: %0.2f%%', overhead_percent
31
- status 'Coverage: %0.2f%%', coverage_percent
32
- status 'Expected: %0.2f%%', env.config.expected_coverage
33
- print_generic_stats
34
- self
35
- end
36
-
37
- private
38
-
39
- # Print generic stats
40
- #
41
- # @return [undefined]
42
- #
43
- # @api private
44
- #
45
- def print_generic_stats
46
- stats = generic_stats.to_a.sort_by(&:last)
47
- return if stats.empty?
48
- info('Nodes handled by generic mutator (type:occurrences):')
49
- stats.reverse_each do |type, amount|
50
- info('%-10s: %d', type, amount)
51
- end
52
- end
53
-
54
- # Return coverage percent
55
- #
56
- # @return [Float]
57
- #
58
- # @api private
59
- #
60
- def coverage_percent
61
- coverage * 100
62
- end
63
-
64
- # Return overhead percent
65
- #
66
- # @return [Float]
67
- #
68
- # @api private
69
- #
70
- def overhead_percent
71
- (overhead / killtime) * 100
72
- end
73
-
74
- # Return stats for nodes handled by generic mutator
75
- #
76
- # @return [Hash<Symbo, Fixnum>]
77
- #
78
- # @api private
79
- #
80
- def generic_stats
81
- object.subject_results.each_with_object(Hash.new(0)) do |result, stats|
82
- Walker.run(result.subject.node) do |node|
83
- stats[node.type] += 1 if Mutator::Registry.lookup(node).equal?(Mutator::Node::Generic)
84
- end
85
- end
86
- end
87
-
88
- end # Env
89
- end # Report
90
- end # CLI
91
- end # Reporter
92
- end # Mutant