mutant 0.5.12 → 0.5.13

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +10 -0
  3. data/circle.yml +1 -1
  4. data/config/flay.yml +1 -1
  5. data/config/flog.yml +1 -1
  6. data/config/mutant.yml +1 -2
  7. data/config/reek.yml +12 -3
  8. data/config/rubocop.yml +4 -0
  9. data/lib/mutant.rb +45 -16
  10. data/lib/mutant/constants.rb +11 -11
  11. data/lib/mutant/delegator.rb +50 -0
  12. data/lib/mutant/{differ.rb → diff.rb} +5 -5
  13. data/lib/mutant/killer.rb +29 -106
  14. data/lib/mutant/matcher/method.rb +2 -11
  15. data/lib/mutant/mutation.rb +17 -3
  16. data/lib/mutant/mutation/evil.rb +2 -10
  17. data/lib/mutant/mutation/neutral.rb +4 -30
  18. data/lib/mutant/mutator/node/literal/fixnum.rb +0 -1
  19. data/lib/mutant/mutator/node/literal/float.rb +0 -1
  20. data/lib/mutant/mutator/node/literal/string.rb +0 -1
  21. data/lib/mutant/mutator/node/literal/symbol.rb +6 -2
  22. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +8 -3
  23. data/lib/mutant/mutator/util/symbol.rb +3 -1
  24. data/lib/mutant/node_helpers.rb +1 -3
  25. data/lib/mutant/reporter.rb +10 -0
  26. data/lib/mutant/reporter/cli.rb +15 -2
  27. data/lib/mutant/reporter/cli/printer.rb +12 -105
  28. data/lib/mutant/reporter/cli/progress.rb +12 -0
  29. data/lib/mutant/reporter/cli/progress/config.rb +32 -0
  30. data/lib/mutant/reporter/cli/{printer/killer.rb → progress/mutation.rb} +9 -16
  31. data/lib/mutant/reporter/cli/progress/noop.rb +22 -0
  32. data/lib/mutant/reporter/cli/progress/subject.rb +118 -0
  33. data/lib/mutant/reporter/cli/registry.rb +77 -0
  34. data/lib/mutant/reporter/cli/report.rb +12 -0
  35. data/lib/mutant/reporter/cli/report/config.rb +118 -0
  36. data/lib/mutant/reporter/cli/report/mutation.rb +112 -0
  37. data/lib/mutant/reporter/cli/report/subject.rb +33 -0
  38. data/lib/mutant/reporter/null.rb +13 -0
  39. data/lib/mutant/reporter/trace.rb +41 -0
  40. data/lib/mutant/runner.rb +22 -20
  41. data/lib/mutant/runner/config.rb +6 -5
  42. data/lib/mutant/runner/killer.rb +59 -0
  43. data/lib/mutant/runner/mutation.rb +17 -10
  44. data/lib/mutant/runner/subject.rb +14 -4
  45. data/lib/mutant/strategy.rb +30 -16
  46. data/lib/mutant/subject/method/instance.rb +1 -1
  47. data/lib/mutant/test.rb +86 -0
  48. data/lib/mutant/version.rb +1 -1
  49. data/spec/integration/mutant/null_spec.rb +18 -0
  50. data/spec/integration/mutant/rspec_spec.rb +1 -1
  51. data/spec/spec_helper.rb +0 -2
  52. data/spec/unit/mutant/diff_spec.rb +162 -0
  53. data/spec/unit/mutant/mutation_spec.rb +8 -5
  54. data/spec/unit/mutant/mutator/node/and_asgn_spec.rb +1 -9
  55. data/spec/unit/mutant/mutator/node/block_spec.rb +6 -18
  56. data/spec/unit/mutant/mutator/node/case_spec.rb +10 -16
  57. data/spec/unit/mutant/mutator/node/define_spec.rb +5 -17
  58. data/spec/unit/mutant/mutator/node/dstr_spec.rb +0 -6
  59. data/spec/unit/mutant/mutator/node/dsym_spec.rb +0 -5
  60. data/spec/unit/mutant/mutator/node/if_spec.rb +13 -17
  61. data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -7
  62. data/spec/unit/mutant/mutator/node/literal/float_spec.rb +0 -9
  63. data/spec/unit/mutant/mutator/node/literal/range_spec.rb +0 -10
  64. data/spec/unit/mutant/mutator/node/literal/string_spec.rb +1 -5
  65. data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +1 -5
  66. data/spec/unit/mutant/mutator/node/named_value/access_spec.rb +4 -7
  67. data/spec/unit/mutant/mutator/node/named_value/constant_assignment_spec.rb +1 -5
  68. data/spec/unit/mutant/mutator/node/named_value/variable_assignment_spec.rb +4 -8
  69. data/spec/unit/mutant/mutator/node/op_assgn_spec.rb +0 -7
  70. data/spec/unit/mutant/mutator/node/or_asgn_spec.rb +1 -9
  71. data/spec/unit/mutant/mutator/node/rescue_spec.rb +0 -4
  72. data/spec/unit/mutant/reporter/null_spec.rb +11 -0
  73. data/spec/unit/mutant/runner/config_spec.rb +6 -7
  74. data/spec/unit/mutant/runner/mutation_spec.rb +101 -0
  75. data/spec/unit/mutant/runner/subject_spec.rb +10 -7
  76. data/spec/unit/mutant_spec.rb +53 -0
  77. metadata +65 -62
  78. data/lib/mutant/killer/forked.rb +0 -46
  79. data/lib/mutant/killer/forking.rb +0 -46
  80. data/lib/mutant/killer/static.rb +0 -34
  81. data/lib/mutant/mutator/node/literal/dynamic.rb +0 -27
  82. data/lib/mutant/random.rb +0 -38
  83. data/lib/mutant/reporter/cli/printer/config.rb +0 -154
  84. data/lib/mutant/reporter/cli/printer/mutation.rb +0 -103
  85. data/lib/mutant/reporter/cli/printer/subject.rb +0 -150
  86. data/spec/unit/mutant/differ/diff_spec.rb +0 -123
  87. data/spec/unit/mutant/differ_spec.rb +0 -42
  88. data/spec/unit/mutant/killer/success_predicate_spec.rb +0 -30
  89. data/spec/unit/mutant/rspec/killer_spec.rb +0 -57
  90. data/spec/unit/mutant/runner/mutation/killer_spec.rb +0 -44
@@ -1,46 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Killer
5
-
6
- # Killer that executes other killer in forked environment
7
- class Forked < self
8
-
9
- # Initialize object
10
- #
11
- # @param [Killer] killer
12
- # @param [Strategy] strategy
13
- # @param [Mutation] mutation
14
- #
15
- # @api private
16
- #
17
- def initialize(killer, strategy, mutation)
18
- @killer = killer
19
- super(strategy, mutation)
20
- end
21
-
22
- private
23
-
24
- # Run killer
25
- #
26
- # @return [true]
27
- # if mutant was killed
28
- #
29
- # @return [false]
30
- # otherwise
31
- #
32
- # @api private
33
- #
34
- def run
35
- pid = fork do
36
- killer = @killer.new(strategy, mutation)
37
- exit(killer.killed? ? CLI::EXIT_SUCCESS : CLI::EXIT_FAILURE)
38
- end
39
-
40
- status = Process.wait2(pid).last
41
- status.exited? && status.success?
42
- end
43
-
44
- end # Forked
45
- end # Killer
46
- end # Mutant
@@ -1,46 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Killer
5
-
6
- # A killer that executes other killer in forked environemnts
7
- class Forking < self
8
- include Equalizer.new(:killer)
9
-
10
- # Return killer
11
- #
12
- # @return [Killer]
13
- #
14
- # @api private
15
- #
16
- attr_reader :killer
17
-
18
- # Initalize killer
19
- #
20
- # @param [Killer] killer
21
- # the killer that will be used
22
- #
23
- # @return [undefined]
24
- #
25
- # @api private
26
- #
27
- def initialize(killer)
28
- @killer = killer
29
- end
30
-
31
- # Return killer instance
32
- #
33
- # @param [Strategy] strategy
34
- # @param [Mutation] mutation
35
- #
36
- # @return [Killer::Forked]
37
- #
38
- # @api private
39
- #
40
- def new(strategy, mutation)
41
- Forked.new(killer, strategy, mutation)
42
- end
43
-
44
- end # Forking
45
- end # Killer
46
- end # Mutant
@@ -1,34 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Killer
5
- # Abstract base class for killer with static result
6
- class Static < self
7
-
8
- # Return result
9
- #
10
- # @return [true]
11
- # if mutation was killed
12
- #
13
- # @return [false]
14
- # otherwise
15
- #
16
- # @api private
17
- #
18
- def run
19
- self.class::RESULT
20
- end
21
-
22
- # Killer that is always successful
23
- class Success < self
24
- RESULT = true
25
- end # Success
26
-
27
- # Killer that always fails
28
- class Fail < self
29
- RESULT = false
30
- end # Fail
31
-
32
- end # Static
33
- end # Killer
34
- end # Mutant
@@ -1,27 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Mutator
5
- class Node
6
- class Literal
7
- # Abstract mutations on dynamic literals
8
- class Dynamic < self
9
- include AbstractType
10
-
11
- private
12
-
13
- # Emit mutants
14
- #
15
- # @return [undefined]
16
- #
17
- # @api private
18
- #
19
- def dispatch
20
- emit_nil
21
- end
22
-
23
- end # Dynamic
24
- end # Literal
25
- end # Node
26
- end # Mutator
27
- end # Mutant
@@ -1,38 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- # Module for generating random values
5
- module Random
6
-
7
- # Return random hex string
8
- #
9
- # @return [String]
10
- #
11
- # @api private
12
- #
13
- def self.hex_string
14
- SecureRandom.hex(10)
15
- end
16
-
17
- # Return random fixnum
18
- #
19
- # @return [Fixnum]
20
- #
21
- # @api private
22
- #
23
- def self.fixnum
24
- ::Random.rand(1000)
25
- end
26
-
27
- # Return random float
28
- #
29
- # @return [Float]
30
- #
31
- # @api private
32
- #
33
- def self.float
34
- ::Random.rand
35
- end
36
-
37
- end # Random
38
- end # Mutant
@@ -1,154 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Reporter
5
- class CLI
6
- class Printer
7
-
8
- # Printer for configuration
9
- class Config < self
10
-
11
- handle(Mutant::Config)
12
-
13
- delegate :matcher, :strategy, :expected_coverage
14
-
15
- # Report configuration
16
- #
17
- # @param [Mutant::Config] config
18
- #
19
- # @return [self]
20
- #
21
- # @api private
22
- #
23
- def run
24
- info 'Mutant configuration:'
25
- info 'Matcher: %s', matcher.inspect
26
- info 'Strategy: %s', strategy.inspect
27
- info 'Expect Coverage: %02f%%', expected_coverage.inspect
28
- self
29
- end
30
-
31
- # Config results printer
32
- class Runner < self
33
-
34
- handle(Mutant::Runner::Config)
35
-
36
- delegate(
37
- :amount_kills, :amount_mutations, :amount_kils,
38
- :coverage, :subjects, :failed_subjects, :runtime, :mutations
39
- )
40
-
41
- # Run printer
42
- #
43
- # @return [self]
44
- #
45
- # @api private
46
- #
47
- def run
48
- print_mutations
49
- info 'Subjects: %s', amount_subjects
50
- info 'Mutations: %s', amount_mutations
51
- info 'Kills: %s', amount_kills
52
- info 'Alive: %s', amount_alive
53
- info 'Runtime: %0.2fs', runtime
54
- info 'Killtime: %0.2fs', killtime
55
- info 'Overhead: %0.2f%%', overhead
56
- status 'Coverage: %0.2f%%', coverage
57
- status 'Expected: %0.2f%%', object.config.expected_coverage
58
- print_generic_stats
59
- self
60
- end
61
-
62
- private
63
-
64
- # Print generic stats
65
- #
66
- # @return [undefined]
67
- #
68
- # @api private
69
- #
70
- def print_generic_stats
71
- stats = generic_stats.to_a.sort_by(&:last)
72
- return if stats.empty?
73
- info('Nodes handled by generic mutator (type:occurrences):')
74
- stats.reverse_each do |type, amount|
75
- info('%-10s: %d', type, amount)
76
- end
77
- end
78
-
79
- # Return stats for nodes handled by generic mutator
80
- #
81
- # @return [Hash<Symbo, Fixnum>]
82
- #
83
- # @api private
84
- #
85
- def generic_stats
86
- subjects.each_with_object(Hash.new(0)) do |runner, stats|
87
- Walker.run(runner.subject.node) do |node|
88
- if Mutator::Registry.lookup(node) == Mutator::Node::Generic
89
- stats[node.type] += 1
90
- end
91
- end
92
- end
93
- end
94
-
95
- # Return amount of subjects
96
- #
97
- # @return [Fixnum]
98
- #
99
- # @api private
100
- #
101
- def amount_subjects
102
- subjects.length
103
- end
104
-
105
- # Print mutations
106
- #
107
- # @return [undefined]
108
- #
109
- # @api private
110
- #
111
- def print_mutations
112
- failed_subjects.each do |subject|
113
- Subject::Runner::Details.run(subject, output)
114
- end
115
- end
116
-
117
- # Return amount of time in killers
118
- #
119
- # @return [Float]
120
- #
121
- # @api private
122
- #
123
- def killtime
124
- mutations.map(&:runtime).inject(0, :+)
125
- end
126
- memoize :killtime
127
-
128
- # Return mutant overhead
129
- #
130
- # @return [Float]
131
- #
132
- # @api private
133
- #
134
- def overhead
135
- return 0 if runtime.zero?
136
- Rational(runtime - killtime, runtime) * 100
137
- end
138
-
139
- # Return amount of alive mutations
140
- #
141
- # @return [Fixnum]
142
- #
143
- # @api private
144
- #
145
- def amount_alive
146
- object.amount_mutations - amount_kills
147
- end
148
-
149
- end # Runner
150
- end # Config
151
- end # Printer
152
- end # CLI
153
- end # Reporter
154
- end # Mutant
@@ -1,103 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Mutant
4
- class Reporter
5
- class CLI
6
- class Printer
7
- # Mutation printer
8
- class Mutation < self
9
-
10
- handle(Runner::Mutation)
11
-
12
- # Build printer
13
- #
14
- # @param [Runner::Mutation] runner
15
- # @param [IO] output
16
- #
17
- # @return [Printer::Mutation]
18
- #
19
- # @api private
20
- #
21
- def self.build(runner, output)
22
- mutation = runner.mutation
23
- lookup(mutation.class).new(runner, output)
24
- end
25
-
26
- # Run mutation printer
27
- #
28
- # @return [undefined]
29
- #
30
- # @api private
31
- #
32
- def run
33
- status('%s', mutation.identification)
34
- puts(details)
35
- end
36
-
37
- private
38
-
39
- # Return mutation
40
- #
41
- # @return [Mutation]
42
- #
43
- # @api private
44
- #
45
- def mutation
46
- object.mutation
47
- end
48
-
49
- # Reporter for noop mutations
50
- class Noop < self
51
-
52
- handle(Mutant::Mutation::Neutral::Noop)
53
-
54
- MESSAGE = [
55
- 'Parsed subject AST:',
56
- '%s',
57
- 'Unparsed source:',
58
- '%s'
59
- ].join("\n")
60
-
61
- private
62
-
63
- # Return details
64
- #
65
- # @return [String]
66
- #
67
- # @api private
68
- #
69
- def details
70
- sprintf(
71
- MESSAGE,
72
- mutation.subject.node.inspect,
73
- mutation.original_source
74
- )
75
- end
76
-
77
- end # Noop
78
-
79
- # Reporter for neutral and evil mutations
80
- class Diff < self
81
-
82
- handle(Mutant::Mutation::Neutral)
83
- handle(Mutant::Mutation::Evil)
84
-
85
- # Return diff
86
- #
87
- # @return [String]
88
- #
89
- # @api private
90
- #
91
- def details
92
- original, current = mutation.original_source, mutation.source
93
- differ = Differ.build(original, current)
94
- color? ? differ.colorized_diff : differ.diff
95
- end
96
-
97
- end # Evil
98
-
99
- end # Mutantion
100
- end # Printer
101
- end # CLI
102
- end # Reporter
103
- end # Mutant