mutant 0.5.12 → 0.5.13

Sign up to get free protection for your applications and to get access to all the features.
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