mutant 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +8 -0
  3. data/Gemfile +1 -4
  4. data/Gemfile.shared +3 -0
  5. data/Rakefile +0 -2
  6. data/config/flay.yml +1 -1
  7. data/config/rubocop.yml +8 -0
  8. data/lib/mutant.rb +2 -0
  9. data/lib/mutant/ast/meta/restarg.rb +15 -0
  10. data/lib/mutant/ast/meta/symbol.rb +15 -0
  11. data/lib/mutant/cli.rb +11 -11
  12. data/lib/mutant/config.rb +1 -1
  13. data/lib/mutant/env.rb +1 -1
  14. data/lib/mutant/matcher/config.rb +2 -2
  15. data/lib/mutant/mutator/node/block.rb +16 -0
  16. data/lib/mutant/mutator/node/define.rb +14 -0
  17. data/lib/mutant/mutator/node/send.rb +12 -1
  18. data/lib/mutant/mutator/node/send/binary.rb +25 -1
  19. data/lib/mutant/parallel.rb +2 -2
  20. data/lib/mutant/result.rb +1 -1
  21. data/lib/mutant/runner/sink.rb +2 -2
  22. data/lib/mutant/version.rb +1 -1
  23. data/meta/begin.rb +0 -2
  24. data/meta/block.rb +15 -0
  25. data/meta/def.rb +25 -0
  26. data/meta/or_asgn.rb +9 -0
  27. data/meta/send.rb +41 -1
  28. data/mutant-rspec.gemspec +0 -2
  29. data/mutant.gemspec +5 -6
  30. data/spec/spec_helper.rb +1 -1
  31. data/spec/support/corpus.rb +1 -0
  32. data/spec/support/shared_context.rb +5 -5
  33. data/spec/unit/mutant/cli_spec.rb +6 -6
  34. data/spec/unit/mutant/env/boostrap_spec.rb +3 -3
  35. data/spec/unit/mutant/env_spec.rb +1 -1
  36. data/spec/unit/mutant/matcher/compiler_spec.rb +1 -1
  37. data/spec/unit/mutant/parallel/master_spec.rb +2 -2
  38. data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +1 -1
  39. data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +3 -3
  40. data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +1 -1
  41. data/spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb +2 -2
  42. data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +3 -3
  43. data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +5 -5
  44. data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +5 -5
  45. data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +2 -2
  46. data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +2 -2
  47. data/spec/unit/mutant/reporter/cli_spec.rb +6 -4
  48. data/spec/unit/mutant/result_spec.rb +23 -0
  49. data/spec/unit/mutant/runner/sink/mutation_spec.rb +8 -8
  50. data/spec/unit/mutant/selector/expression_spec.rb +1 -1
  51. data/test_app/Gemfile.rspec3.2 +1 -0
  52. data/test_app/Gemfile.rspec3.3 +1 -0
  53. data/test_app/spec/unit/test_app/literal_spec.rb +0 -2
  54. metadata +27 -18
  55. data/Guardfile +0 -16
  56. data/test_app/Gemfile.rspec3.0 +0 -6
  57. data/test_app/Gemfile.rspec3.1 +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d31268248349a065fe46a960fe2a0d0ace09f0d8
4
- data.tar.gz: c35d18b21c3761d28fece74e573ef7f6ab0dfd69
3
+ metadata.gz: a7008d6d94f2de1e1c8d276c943491b0fb6cfdc1
4
+ data.tar.gz: 70b30707970890aa21961febe6a7657aa1889522
5
5
  SHA512:
6
- metadata.gz: 3aec0dac703c7e91f164c60baa26d941e9a2d2149bd4542fcaac33f8e4794d9431ce4e226a5af29b88ec13e77f1ab2e32b6c4431a2a514ea4f2e1cb4200ea3bd
7
- data.tar.gz: 9fb92420b95b0ae6fd1df55941e3df971b89d80ff7bef55a06c9823d1c96d6b4d50aedb88814a1c308ca57f99aa30e8d12ddc6275a6036073c21ca16d6d74aa9
6
+ metadata.gz: b9fe654b8233c2666adadd104d7b6cfe4a5409b81913d9d446364424920a659becb763659c24e308915263a1a6a52e20ea8d7895ca27effb057ea169b1d51f79
7
+ data.tar.gz: 5ea82f2c27289e2f307a5809f6c21a8d95315191069f240488419d6c5a65d360bc64ccf8a5d8f8b1f7eca4f23d283107c3a37768472d6a3970d52a9c2e114571
@@ -1,3 +1,11 @@
1
+ # v0.8.4 2015-09-10
2
+
3
+ * Add mutation from `a != b` to `!a.eql?(b)` and `!a.equal?(b)` #417
4
+ * Add mutation `A.const_get(:B)` -> `A::B` #426
5
+ * Add mutation `def foo(*args); end` into `def foo(*args); args = []; end` #423
6
+ * Add mutation from `foo.baz { bar }` to `foo.bar` #416
7
+ * Update anima dependency to 0.3.0
8
+
1
9
  # v0.8.3 2015-09-01
2
10
 
3
11
  * Remove invalid mutation `super(...)` to `super`
data/Gemfile CHANGED
@@ -1,8 +1,5 @@
1
- # encoding: utf-8
2
-
3
1
  source 'https://rubygems.org'
4
2
 
5
3
  gemspec name: 'mutant'
6
4
 
7
- gem 'morpher', git: 'https://github.com/mbj/morpher.git'
8
- gem 'devtools', git: 'https://github.com/rom-rb/devtools.git'
5
+ eval_gemfile File.expand_path('../Gemfile.shared', __FILE__)
@@ -0,0 +1,3 @@
1
+ # Place for shared git sources, used for developing updates to depedencies
2
+ # where the git sources (without this file) need to be consistently edited
3
+ # into multiple Gemfiles.
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'devtools'
4
2
 
5
3
  Devtools.init_rake_tasks
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 18
3
- total_score: 1200
3
+ total_score: 1234
@@ -132,3 +132,11 @@ SpaceAroundOperators:
132
132
  # We use parallel assignments with great success
133
133
  ParallelAssignment:
134
134
  Enabled: false
135
+
136
+ # Allow additional specs
137
+ ExtraSpacing:
138
+ Enabled: false
139
+
140
+ # Buggy
141
+ FormatParameterMismatch:
142
+ Enabled: false
@@ -49,8 +49,10 @@ require 'mutant/ast/named_children'
49
49
  require 'mutant/ast/node_predicates'
50
50
  require 'mutant/ast/meta'
51
51
  require 'mutant/ast/meta/send'
52
+ require 'mutant/ast/meta/symbol'
52
53
  require 'mutant/ast/meta/optarg'
53
54
  require 'mutant/ast/meta/resbody'
55
+ require 'mutant/ast/meta/restarg'
54
56
  require 'mutant/actor'
55
57
  require 'mutant/actor/receiver'
56
58
  require 'mutant/actor/sender'
@@ -0,0 +1,15 @@
1
+ module Mutant
2
+ module AST
3
+ # Node meta information mixin
4
+ module Meta
5
+
6
+ # Metadata for restarg nodes
7
+ class Restarg
8
+ include NamedChildren, Concord.new(:node)
9
+
10
+ children :name
11
+ end # Restarg
12
+
13
+ end # Meta
14
+ end # AST
15
+ end # Mutant
@@ -0,0 +1,15 @@
1
+ module Mutant
2
+ module AST
3
+ # Node meta information mixin
4
+ module Meta
5
+
6
+ # Metadata for symbol nodes
7
+ class Symbol
8
+ include NamedChildren, Concord.new(:node)
9
+
10
+ children :name
11
+
12
+ end # Symbol
13
+ end # Meta
14
+ end # AST
15
+ end # Mutant
@@ -98,7 +98,7 @@ module Mutant
98
98
  def add_environment_options(opts)
99
99
  opts.separator('Environment:')
100
100
  opts.on('--zombie', 'Run mutant zombified') do
101
- update(zombie: true)
101
+ with(zombie: true)
102
102
  end
103
103
  opts.on('-I', '--include DIRECTORY', 'Add DIRECTORY to $LOAD_PATH') do |directory|
104
104
  add(:includes, directory)
@@ -107,7 +107,7 @@ module Mutant
107
107
  add(:requires, name)
108
108
  end
109
109
  opts.on('-j', '--jobs NUMBER', 'Number of kill jobs. Defaults to number of processors.') do |number|
110
- update(jobs: Integer(number))
110
+ with(jobs: Integer(number))
111
111
  end
112
112
  end
113
113
 
@@ -119,7 +119,7 @@ module Mutant
119
119
  #
120
120
  # @api private
121
121
  def setup_integration(name)
122
- update(integration: Integration.setup(name))
122
+ with(integration: Integration.setup(name))
123
123
  rescue LoadError
124
124
  raise Error, "Could not load integration #{name.inspect} (you may want to try installing the gem mutant-#{name})"
125
125
  end
@@ -139,7 +139,7 @@ module Mutant
139
139
  '--expected-coverage COVERAGE',
140
140
  'Fail unless COVERAGE is not reached exactly, parsed via Rational()'
141
141
  ) do |coverage|
142
- update(expected_coverage: Rational(coverage))
142
+ with(expected_coverage: Rational(coverage))
143
143
  end
144
144
  opts.on('--use INTEGRATION', 'Use INTEGRATION to kill mutations', &method(:setup_integration))
145
145
  end
@@ -169,14 +169,14 @@ module Mutant
169
169
  # @api private
170
170
  def add_debug_options(opts)
171
171
  opts.on('--fail-fast', 'Fail fast') do
172
- update(fail_fast: true)
172
+ with(fail_fast: true)
173
173
  end
174
174
  opts.on('--version', 'Print mutants version') do
175
175
  puts("mutant-#{VERSION}")
176
176
  Kernel.exit(EXIT_SUCCESS)
177
177
  end
178
178
  opts.on('-d', '--debug', 'Enable debugging output') do
179
- update(debug: true)
179
+ with(debug: true)
180
180
  end
181
181
  opts.on_tail('-h', '--help', 'Show this message') do
182
182
  puts(opts.to_s)
@@ -184,15 +184,15 @@ module Mutant
184
184
  end
185
185
  end
186
186
 
187
- # Update configuration
187
+ # With configuration
188
188
  #
189
189
  # @param [Hash<Symbol, Object>] attributes
190
190
  #
191
191
  # @return [undefined]
192
192
  #
193
193
  # @api private
194
- def update(attributes)
195
- @config = @config.update(attributes)
194
+ def with(attributes)
195
+ @config = @config.with(attributes)
196
196
  end
197
197
 
198
198
  # Add configuration
@@ -207,7 +207,7 @@ module Mutant
207
207
  #
208
208
  # @api private
209
209
  def add(attribute, value)
210
- update(attribute => config.public_send(attribute).dup << value)
210
+ with(attribute => config.public_send(attribute) + [value])
211
211
  end
212
212
 
213
213
  # Add matcher configuration
@@ -222,7 +222,7 @@ module Mutant
222
222
  #
223
223
  # @api private
224
224
  def add_matcher(attribute, value)
225
- update(matcher: config.matcher.add(attribute, value))
225
+ with(matcher: config.matcher.add(attribute, value))
226
226
  end
227
227
 
228
228
  end # CLI
@@ -4,7 +4,7 @@ module Mutant
4
4
  # Does not reference any "external" volatile state. The configuration applied
5
5
  # to current environment is being represented by the Mutant::Env object.
6
6
  class Config
7
- include Adamantium::Flat, Anima::Update, Anima.new(
7
+ include Adamantium::Flat, Anima.new(
8
8
  :debug,
9
9
  :integration,
10
10
  :matcher,
@@ -1,7 +1,7 @@
1
1
  module Mutant
2
2
  # Abstract base class for mutant environments
3
3
  class Env
4
- include Adamantium::Flat, Anima::Update, Anima.new(
4
+ include Adamantium::Flat, Anima.new(
5
5
  :config,
6
6
  :actor_env,
7
7
  :cache,
@@ -2,7 +2,7 @@ module Mutant
2
2
  class Matcher
3
3
  # Subject matcher configuration
4
4
  class Config
5
- include Adamantium, Anima::Update, Anima.new(
5
+ include Adamantium, Anima.new(
6
6
  :match_expressions,
7
7
  :ignore_expressions,
8
8
  :subject_filters
@@ -41,7 +41,7 @@ module Mutant
41
41
  #
42
42
  # @api private
43
43
  def add(attribute, value)
44
- update(attribute => public_send(attribute).dup << value)
44
+ with(attribute => public_send(attribute) + [value])
45
45
  end
46
46
 
47
47
  private
@@ -36,6 +36,22 @@ module Mutant
36
36
  return unless body
37
37
  emit(body)
38
38
  emit_body_mutations
39
+
40
+ mutate_body_receiver
41
+ end
42
+
43
+ # Mutate method send in body scope of `send`
44
+ #
45
+ # @return [undefined]
46
+ #
47
+ # @api private
48
+ def mutate_body_receiver
49
+ return unless n_send?(body)
50
+
51
+ body_meta = AST::Meta::Send.new(body)
52
+ send_meta = AST::Meta::Send.new(send)
53
+
54
+ emit(s(:send, send_meta.receiver, body_meta.selector, *body_meta.arguments))
39
55
  end
40
56
 
41
57
  end # Block
@@ -14,6 +14,7 @@ module Mutant
14
14
  def dispatch
15
15
  emit_arguments_mutations
16
16
  emit_optarg_body_assignments
17
+ emit_restarg_body_mutation
17
18
  emit_body(N_RAISE)
18
19
  emit_body(nil)
19
20
  emit_body_mutations if body
@@ -32,6 +33,19 @@ module Mutant
32
33
  end
33
34
  end
34
35
 
36
+ # Emit mutation with arg splat as empty array signment in method
37
+ #
38
+ # @return [undefined]
39
+ #
40
+ # @api private
41
+ def emit_restarg_body_mutation
42
+ arguments.children.each do |argument|
43
+ next unless n_restarg?(argument) && argument.children.one?
44
+
45
+ emit_body_prepend(s(:lvasgn, AST::Meta::Restarg.new(argument).name, s(:array)))
46
+ end
47
+ end
48
+
35
49
  # Emit valid body ASTs depending on instance body
36
50
  #
37
51
  # @param node [Parser::AST::Node]
@@ -90,11 +90,23 @@ module Mutant
90
90
  def normal_dispatch
91
91
  emit_naked_receiver
92
92
  emit_selector_replacement
93
+ emit_const_get_mutation
93
94
  emit_argument_propagation
94
95
  mutate_receiver
95
96
  mutate_arguments
96
97
  end
97
98
 
99
+ # Emit mutation from `const_get` to const literal
100
+ #
101
+ # @return [undefined]
102
+ #
103
+ # @api private
104
+ def emit_const_get_mutation
105
+ return unless selector.equal?(:const_get) && n_sym?(arguments.first)
106
+
107
+ emit(s(:const, receiver, AST::Meta::Symbol.new(arguments.first).name))
108
+ end
109
+
98
110
  # Emit selector replacement
99
111
  #
100
112
  # @return [undefined]
@@ -158,7 +170,6 @@ module Mutant
158
170
  emit_receiver(nil) if n_self?(receiver) && !(
159
171
  KEYWORDS.include?(selector) ||
160
172
  METHOD_OPERATORS.include?(selector) ||
161
- OP_ASSIGN.include?(parent_type) ||
162
173
  meta.attribute_assignment?
163
174
  )
164
175
  end
@@ -19,8 +19,32 @@ module Mutant
19
19
  emit(left)
20
20
  emit_left_mutations
21
21
  emit_selector_replacement
22
- emit(right) unless n_splat?(right)
22
+ emit(right)
23
23
  emit_right_mutations
24
+ emit_not_equality_mutations
25
+ end
26
+
27
+ # Emit mutations for `!=`
28
+ #
29
+ # @return [undefined]
30
+ #
31
+ # @api private
32
+ def emit_not_equality_mutations
33
+ return unless operator.equal?(:'!=')
34
+
35
+ emit_not_equality_mutation(:eql?)
36
+ emit_not_equality_mutation(:equal?)
37
+ end
38
+
39
+ # Emit negated method sends with specified operator
40
+ #
41
+ # @param new_operator [Symbol] selector to be negated
42
+ #
43
+ # @return [undefined]
44
+ #
45
+ # @api private
46
+ def emit_not_equality_mutation(new_operator)
47
+ emit(n_not(s(:send, left, new_operator, right)))
24
48
  end
25
49
 
26
50
  end # Binary
@@ -75,12 +75,12 @@ module Mutant
75
75
 
76
76
  # Parallel run configuration
77
77
  class Config
78
- include Anima::Update, Adamantium::Flat, Anima.new(:env, :processor, :source, :sink, :jobs)
78
+ include Adamantium::Flat, Anima.new(:env, :processor, :source, :sink, :jobs)
79
79
  end # Config
80
80
 
81
81
  # Parallel execution status
82
82
  class Status
83
- include Adamantium::Flat, Anima::Update, Anima.new(:payload, :done, :active_jobs)
83
+ include Adamantium::Flat, Anima.new(:payload, :done, :active_jobs)
84
84
  end
85
85
 
86
86
  end # Parallel
@@ -67,7 +67,7 @@ module Mutant
67
67
  # @api private
68
68
  def self.included(host)
69
69
  host.class_eval do
70
- include Adamantium, Anima::Update
70
+ include Adamantium
71
71
  extend ClassMethods
72
72
  end
73
73
  end
@@ -78,8 +78,8 @@ module Mutant
78
78
 
79
79
  original = @subject_results[mutation.subject]
80
80
 
81
- @subject_results[mutation.subject] = original.update(
82
- mutation_results: (original.mutation_results.dup << mutation_result),
81
+ @subject_results[mutation.subject] = original.with(
82
+ mutation_results: (original.mutation_results + [mutation_result]),
83
83
  tests: mutation_result.test_result.tests
84
84
  )
85
85
 
@@ -1,4 +1,4 @@
1
1
  module Mutant
2
2
  # Current mutant version
3
- VERSION = '0.8.3'.freeze
3
+ VERSION = '0.8.4'.freeze
4
4
  end # Mutant
@@ -12,8 +12,6 @@ Mutant::Meta::Example.add do
12
12
  mutation 'false'
13
13
  end
14
14
 
15
- # encoding: utf-8
16
-
17
15
  Mutant::Meta::Example.add do
18
16
 
19
17
  source s(:begin, s(:true))
@@ -69,3 +69,18 @@ Mutant::Meta::Example.add do
69
69
  mutation 'foo { |(_a)| }'
70
70
  mutation 'foo'
71
71
  end
72
+
73
+ Mutant::Meta::Example.add do
74
+ source 'self.foo { bar(nil) }'
75
+
76
+ singleton_mutations
77
+ mutation 'self.foo'
78
+ mutation 'foo { bar(nil) }'
79
+ mutation 'self.foo { bar }'
80
+ mutation 'self.foo { nil }'
81
+ mutation 'self.foo {}'
82
+ mutation 'self.foo { self }'
83
+ mutation 'self.foo { raise }'
84
+ mutation 'bar(nil)'
85
+ mutation 'self.bar(nil)'
86
+ end
@@ -5,6 +5,31 @@ Mutant::Meta::Example.add do
5
5
  mutation 'remove_method :foo'
6
6
  end
7
7
 
8
+ Mutant::Meta::Example.add do
9
+ source 'def foo(a, *b); nil; end'
10
+
11
+ mutation 'def foo(_a, *b); nil; end'
12
+ mutation 'def foo; nil; end'
13
+ mutation 'def foo(a, *b); end'
14
+ mutation 'def foo(a, *b); raise; end'
15
+ mutation 'def foo(a); nil; end'
16
+ mutation 'def foo(*b); nil; end'
17
+ mutation 'def foo(a, *b); b = []; nil; end'
18
+ mutation 'remove_method :foo'
19
+ end
20
+
21
+ Mutant::Meta::Example.add do
22
+ source 'def foo(a, *); nil; end'
23
+
24
+ mutation 'def foo(_a, *); nil; end'
25
+ mutation 'def foo; nil; end'
26
+ mutation 'def foo(a, *); end'
27
+ mutation 'def foo(a, *); raise; end'
28
+ mutation 'def foo(a); nil; end'
29
+ mutation 'def foo(*); nil; end'
30
+ mutation 'remove_method :foo'
31
+ end
32
+
8
33
  Mutant::Meta::Example.add do
9
34
  source 'def foo; foo; rescue; end'
10
35