mutant 0.8.3 → 0.8.4

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 (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
@@ -21,6 +21,15 @@ Mutant::Meta::Example.add do
21
21
  mutation '@a ||= 2'
22
22
  end
23
23
 
24
+ Mutant::Meta::Example.add do
25
+ source '@a ||= self.bar'
26
+
27
+ singleton_mutations
28
+ mutation '@a ||= nil'
29
+ mutation '@a ||= self'
30
+ mutation '@a ||= bar'
31
+ end
32
+
24
33
  Mutant::Meta::Example.add do
25
34
  source 'foo[:bar] ||= 1'
26
35
 
@@ -14,6 +14,32 @@ Mutant::Meta::Example.add do
14
14
  mutation 'b'
15
15
  end
16
16
 
17
+ Mutant::Meta::Example.add do
18
+ source 'A.const_get(:B)'
19
+
20
+ singleton_mutations
21
+ mutation 'A::B'
22
+ mutation 'A.const_get'
23
+ mutation 'A'
24
+ mutation ':B'
25
+ mutation 'A.const_get(nil)'
26
+ mutation 'A.const_get(self)'
27
+ mutation 'A.const_get(:B__mutant__)'
28
+ mutation 'self.const_get(:B)'
29
+ end
30
+
31
+ Mutant::Meta::Example.add do
32
+ source 'A.const_get(bar)'
33
+
34
+ singleton_mutations
35
+ mutation 'A.const_get'
36
+ mutation 'A'
37
+ mutation 'bar'
38
+ mutation 'A.const_get(nil)'
39
+ mutation 'A.const_get(self)'
40
+ mutation 'self.const_get(bar)'
41
+ end
42
+
17
43
  Mutant::Meta::Example.add do
18
44
  source 'a >= b'
19
45
 
@@ -425,7 +451,7 @@ Mutant::Meta::Example.add do
425
451
  mutation 'self[*bar]'
426
452
  end
427
453
 
428
- (Mutant::AST::Types::BINARY_METHOD_OPERATORS - %i[<= >= < > == eql?]).each do |operator|
454
+ (Mutant::AST::Types::BINARY_METHOD_OPERATORS - %i[<= >= < > == != eql?]).each do |operator|
429
455
  Mutant::Meta::Example.add do
430
456
  source "true #{operator} false"
431
457
 
@@ -438,3 +464,17 @@ end
438
464
  mutation "true #{operator} nil"
439
465
  end
440
466
  end
467
+
468
+ Mutant::Meta::Example.add do
469
+ source 'a != b'
470
+
471
+ singleton_mutations
472
+ mutation 'nil != b'
473
+ mutation 'self != b'
474
+ mutation 'a'
475
+ mutation 'b'
476
+ mutation 'a != nil'
477
+ mutation 'a != self'
478
+ mutation '!a.eql?(b)'
479
+ mutation '!a.equal?(b)'
480
+ end
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  require File.expand_path('../lib/mutant/version', __FILE__)
4
2
 
5
3
  Gem::Specification.new do |gem|
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  require File.expand_path('../lib/mutant/version', __FILE__)
4
2
 
5
3
  Gem::Specification.new do |gem|
@@ -27,7 +25,7 @@ Gem::Specification.new do |gem|
27
25
  gem.add_runtime_dependency('ast', '~> 2.1')
28
26
  gem.add_runtime_dependency('diff-lcs', '~> 1.2')
29
27
  gem.add_runtime_dependency('parallel', '~> 1.3')
30
- gem.add_runtime_dependency('morpher', '~> 0.2.4')
28
+ gem.add_runtime_dependency('morpher', '~> 0.2.5')
31
29
  gem.add_runtime_dependency('procto', '~> 0.0.2')
32
30
  gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
33
31
  gem.add_runtime_dependency('unparser', '~> 0.2.4')
@@ -35,9 +33,10 @@ Gem::Specification.new do |gem|
35
33
  gem.add_runtime_dependency('adamantium', '~> 0.2.0')
36
34
  gem.add_runtime_dependency('memoizable', '~> 0.4.2')
37
35
  gem.add_runtime_dependency('equalizer', '~> 0.0.9')
38
- gem.add_runtime_dependency('anima', '~> 0.2.0')
36
+ gem.add_runtime_dependency('anima', '~> 0.3.0')
39
37
  gem.add_runtime_dependency('concord', '~> 0.1.5')
40
38
 
41
- gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
42
- gem.add_development_dependency('ffi', '~> 1.9.6')
39
+ gem.add_development_dependency('devtools', '~> 0.1.1')
40
+ gem.add_development_dependency('bundler', '~> 1.10')
41
+ gem.add_development_dependency('ffi', '~> 1.9.6')
43
42
  end
@@ -33,7 +33,7 @@ $LOAD_PATH << File.join(TestApp.root, 'lib')
33
33
  require 'test_app'
34
34
 
35
35
  module Fixtures
36
- TEST_CONFIG = Mutant::Config::DEFAULT.update(reporter: Mutant::Reporter::Trace.new)
36
+ TEST_CONFIG = Mutant::Config::DEFAULT.with(reporter: Mutant::Reporter::Trace.new)
37
37
  TEST_CACHE = Mutant::Cache.new
38
38
  TEST_ENV = Mutant::Env::Bootstrap.(TEST_CONFIG, TEST_CACHE)
39
39
  end # Fixtures
@@ -134,6 +134,7 @@ module MutantSpec
134
134
  repo_path.join('Gemfile').open('a') do |file|
135
135
  file << "gem 'mutant', path: '#{relative}'\n"
136
136
  file << "gem 'mutant-rspec', path: '#{relative}'\n"
137
+ file << "eval_gemfile File.expand_path('#{relative.join('Gemfile.shared')}')\n"
137
138
  end
138
139
  lockfile = repo_path.join('Gemfile.lock')
139
140
  lockfile.delete if lockfile.exist?
@@ -1,8 +1,8 @@
1
1
  # rubocop:disable ModuleLength
2
2
  module SharedContext
3
- def update(name, &block)
3
+ def with(name, &block)
4
4
  define_method(name) do
5
- super().update(instance_eval(&block))
5
+ super().with(instance_eval(&block))
6
6
  end
7
7
  end
8
8
 
@@ -51,7 +51,7 @@ module SharedContext
51
51
  end
52
52
 
53
53
  let(:config) do
54
- Mutant::Config::DEFAULT.update(
54
+ Mutant::Config::DEFAULT.with(
55
55
  jobs: 1,
56
56
  reporter: Mutant::Reporter::Trace.new
57
57
  )
@@ -120,11 +120,11 @@ module SharedContext
120
120
  end
121
121
 
122
122
  let(:empty_subject_a_result) do
123
- subject_a_result.update(mutation_results: [])
123
+ subject_a_result.with(mutation_results: [])
124
124
  end
125
125
 
126
126
  let(:partial_subject_a_result) do
127
- subject_a_result.update(mutation_results: [mutation_a_result])
127
+ subject_a_result.with(mutation_results: [mutation_a_result])
128
128
  end
129
129
  end
130
130
  end
@@ -73,7 +73,7 @@ RSpec.describe Mutant::CLI do
73
73
 
74
74
  let(:default_matcher_config) do
75
75
  Mutant::Matcher::Config::DEFAULT
76
- .update(match_expressions: expressions.map(&method(:parse_expression)))
76
+ .with(match_expressions: expressions.map(&method(:parse_expression)))
77
77
  end
78
78
 
79
79
  let(:flags) { [] }
@@ -221,13 +221,13 @@ Options:
221
221
  end
222
222
  end
223
223
 
224
- context 'with require flag' do
225
- let(:flags) { %w[--require foo] }
224
+ context 'with require flags' do
225
+ let(:flags) { %w[--require foo --require bar] }
226
226
 
227
227
  it_should_behave_like 'a cli parser'
228
228
 
229
229
  it 'configures requires' do
230
- expect(subject.config.requires).to eql(%w[foo])
230
+ expect(subject.config.requires).to eql(%w[foo bar])
231
231
  end
232
232
  end
233
233
 
@@ -235,7 +235,7 @@ Options:
235
235
  let(:flags) { %w[--since master] }
236
236
 
237
237
  let(:expected_matcher_config) do
238
- default_matcher_config.update(
238
+ default_matcher_config.with(
239
239
  subject_filters: [
240
240
  Mutant::Repository::SubjectFilter.new(Mutant::Repository::Diff.new('HEAD', 'master'))
241
241
  ]
@@ -249,7 +249,7 @@ Options:
249
249
  let(:flags) { %w[--ignore-subject Foo::Bar] }
250
250
 
251
251
  let(:expected_matcher_config) do
252
- default_matcher_config.update(ignore_expressions: [parse_expression('Foo::Bar')])
252
+ default_matcher_config.with(ignore_expressions: [parse_expression('Foo::Bar')])
253
253
  end
254
254
 
255
255
  it_should_behave_like 'a cli parser'
@@ -1,6 +1,6 @@
1
1
  RSpec.describe Mutant::Env::Bootstrap do
2
2
  let(:config) do
3
- Mutant::Config::DEFAULT.update(
3
+ Mutant::Config::DEFAULT.with(
4
4
  jobs: 1,
5
5
  reporter: Mutant::Reporter::Trace.new,
6
6
  includes: [],
@@ -69,7 +69,7 @@ RSpec.describe Mutant::Env::Bootstrap do
69
69
  end
70
70
 
71
71
  context 'when includes are present' do
72
- let(:config) { super().update(includes: %w[foo bar]) }
72
+ let(:config) { super().with(includes: %w[foo bar]) }
73
73
 
74
74
  before do
75
75
  %w[foo bar].each do |component|
@@ -121,7 +121,7 @@ RSpec.describe Mutant::Env::Bootstrap do
121
121
  end
122
122
 
123
123
  let(:expected_env) do
124
- super().update(
124
+ super().with(
125
125
  subjects: subjects,
126
126
  mutations: mutations
127
127
  )
@@ -16,7 +16,7 @@ RSpec.describe Mutant::Env do
16
16
  let(:integration) { integration_class.new(config) }
17
17
 
18
18
  let(:config) do
19
- Mutant::Config::DEFAULT.update(isolation: isolation, integration: integration_class)
19
+ Mutant::Config::DEFAULT.with(isolation: isolation, integration: integration_class)
20
20
  end
21
21
 
22
22
  let(:isolation) { double('Isolation') }
@@ -18,7 +18,7 @@ RSpec.describe Mutant::Matcher::Compiler do
18
18
  end
19
19
 
20
20
  describe '.call' do
21
- subject { object.call(env, matcher_config.update(attributes)) }
21
+ subject { object.call(env, matcher_config.with(attributes)) }
22
22
 
23
23
  let(:matcher_config) { Mutant::Matcher::Config::DEFAULT }
24
24
 
@@ -92,8 +92,8 @@ RSpec.describe Mutant::Parallel::Master do
92
92
  subject { described_class.call(config) }
93
93
 
94
94
  context 'with multiple workers configured' do
95
- let(:config) { super().update(jobs: 2) }
96
- let(:expected_results) { [] }
95
+ let(:config) { super().with(jobs: 2) }
96
+ let(:expected_results) { [] }
97
97
 
98
98
  before do
99
99
  expect(Mutant::Parallel::Worker).to receive(:run).with(
@@ -17,7 +17,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Config do
17
17
  end
18
18
 
19
19
  context 'with non default coverage expectation' do
20
- update(:config) { { expected_coverage: 0.1r } }
20
+ with(:config) { { expected_coverage: 0.1r } }
21
21
 
22
22
  it_reports(<<-REPORT)
23
23
  Mutant configuration:
@@ -1,13 +1,13 @@
1
1
  RSpec.describe Mutant::Reporter::CLI::Printer::EnvProgress do
2
2
  setup_shared_context
3
3
 
4
- update(:config) { { expected_coverage: 0.1r } }
4
+ with(:config) { { expected_coverage: 0.1r } }
5
5
 
6
6
  let(:reportable) { env_result }
7
7
 
8
8
  describe '.call' do
9
9
  context 'without progress' do
10
- update(:subject_a_result) { { mutation_results: [] } }
10
+ with(:subject_a_result) { { mutation_results: [] } }
11
11
 
12
12
  it_reports <<-'STR'
13
13
  Mutant configuration:
@@ -51,7 +51,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::EnvProgress do
51
51
  end
52
52
 
53
53
  context 'on partial coverage' do
54
- update(:mutation_a_test_result) { { passed: true } }
54
+ with(:mutation_a_test_result) { { passed: true } }
55
55
 
56
56
  it_reports <<-'STR'
57
57
  Mutant configuration:
@@ -1,7 +1,7 @@
1
1
  RSpec.describe Mutant::Reporter::CLI::Printer::EnvResult do
2
2
  setup_shared_context
3
3
 
4
- update(:mutation_a_test_result) { { passed: true } }
4
+ with(:mutation_a_test_result) { { passed: true } }
5
5
 
6
6
  let(:reportable) { env_result }
7
7
 
@@ -9,13 +9,13 @@ RSpec.describe Mutant::Reporter::CLI::Printer::MutationProgressResult do
9
9
 
10
10
  describe '.run' do
11
11
  context 'on killed mutant' do
12
- update(:mutation_a_test_result) { { passed: true } }
12
+ with(:mutation_a_test_result) { { passed: true } }
13
13
 
14
14
  it_reports Mutant::Color::RED.format('F')
15
15
  end
16
16
 
17
17
  context 'on alive mutant' do
18
- update(:mutation_a_test_result) { { passed: false } }
18
+ with(:mutation_a_test_result) { { passed: false } }
19
19
 
20
20
  it_reports Mutant::Color::GREEN.format('.')
21
21
  end
@@ -5,7 +5,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::MutationResult do
5
5
 
6
6
  describe '.call' do
7
7
  context 'failed kill' do
8
- update(:mutation_a_test_result) { { passed: true } }
8
+ with(:mutation_a_test_result) { { passed: true } }
9
9
 
10
10
  context 'on evil mutation' do
11
11
  context 'with a diff' do
@@ -61,7 +61,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::MutationResult do
61
61
  end
62
62
 
63
63
  context 'on neutral mutation' do
64
- update(:mutation_a_test_result) { { passed: false } }
64
+ with(:mutation_a_test_result) { { passed: false } }
65
65
 
66
66
  let(:mutation_a) do
67
67
  Mutant::Mutation::Neutral.new(subject_a, s(:true))
@@ -86,7 +86,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::MutationResult do
86
86
  end
87
87
 
88
88
  context 'on noop mutation' do
89
- update(:mutation_a_test_result) { { passed: false } }
89
+ with(:mutation_a_test_result) { { passed: false } }
90
90
 
91
91
  let(:mutation_a) do
92
92
  Mutant::Mutation::Noop.new(subject_a, s(:true))
@@ -5,14 +5,14 @@ RSpec.describe Mutant::Reporter::CLI::Printer::StatusProgressive do
5
5
 
6
6
  describe '.call' do
7
7
  context 'with empty scheduler' do
8
- update(:env_result) { { subject_results: [] } }
8
+ with(:env_result) { { subject_results: [] } }
9
9
 
10
10
  it_reports <<-REPORT
11
11
  (00/02) 100% - killtime: 0.00s runtime: 4.00s overhead: 4.00s
12
12
  REPORT
13
13
 
14
14
  context 'on non default coverage expectation' do
15
- update(:config) { { expected_coverage: 0.1r } }
15
+ with(:config) { { expected_coverage: 0.1r } }
16
16
 
17
17
  it_reports <<-REPORT
18
18
  (00/02) 100% - killtime: 0.00s runtime: 4.00s overhead: 4.00s
@@ -22,7 +22,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::StatusProgressive do
22
22
 
23
23
  context 'with scheduler active on one subject' do
24
24
  context 'without progress' do
25
- update(:status) { { active_jobs: [].to_set } }
25
+ with(:status) { { active_jobs: [].to_set } }
26
26
 
27
27
  it_reports(<<-REPORT)
28
28
  (02/02) 100% - killtime: 2.00s runtime: 4.00s overhead: 2.00s
@@ -30,10 +30,10 @@ RSpec.describe Mutant::Reporter::CLI::Printer::StatusProgressive do
30
30
  end
31
31
 
32
32
  context 'with progress' do
33
- update(:status) { { active_jobs: [job_b, job_a].to_set } }
33
+ with(:status) { { active_jobs: [job_b, job_a].to_set } }
34
34
 
35
35
  context 'on failure' do
36
- update(:mutation_a_test_result) { { passed: true } }
36
+ with(:mutation_a_test_result) { { passed: true } }
37
37
 
38
38
  it_reports(<<-REPORT)
39
39
  (01/02) 50% - killtime: 2.00s runtime: 4.00s overhead: 2.00s
@@ -5,7 +5,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
5
5
 
6
6
  describe '.call' do
7
7
  context 'with empty scheduler' do
8
- update(:env_result) { { subject_results: [] } }
8
+ with(:env_result) { { subject_results: [] } }
9
9
 
10
10
  it_reports <<-REPORT
11
11
  Mutant configuration:
@@ -28,7 +28,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
28
28
  REPORT
29
29
 
30
30
  context 'on non default coverage expectation' do
31
- update(:config) { { expected_coverage: 0.1r } }
31
+ with(:config) { { expected_coverage: 0.1r } }
32
32
 
33
33
  it_reports <<-REPORT
34
34
  Mutant configuration:
@@ -54,7 +54,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
54
54
 
55
55
  context 'with scheduler active on one subject' do
56
56
  context 'without progress' do
57
- update(:status) { { active_jobs: [].to_set } }
57
+ with(:status) { { active_jobs: [].to_set } }
58
58
 
59
59
  it_reports(<<-REPORT)
60
60
  Mutant configuration:
@@ -78,10 +78,10 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do
78
78
  end
79
79
 
80
80
  context 'with progress' do
81
- update(:status) { { active_jobs: [job_b, job_a].to_set } }
81
+ with(:status) { { active_jobs: [job_b, job_a].to_set } }
82
82
 
83
83
  context 'on failure' do
84
- update(:mutation_a_test_result) { { passed: true } }
84
+ with(:mutation_a_test_result) { { passed: true } }
85
85
 
86
86
  it_reports(<<-REPORT)
87
87
  Mutant configuration:
@@ -13,7 +13,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::SubjectProgress do
13
13
  end
14
14
 
15
15
  context 'on partial coverage' do
16
- update(:mutation_a_test_result) { { passed: true } }
16
+ with(:mutation_a_test_result) { { passed: true } }
17
17
 
18
18
  it_reports <<-'STR'
19
19
  subject-a mutations: 2
@@ -23,7 +23,7 @@ RSpec.describe Mutant::Reporter::CLI::Printer::SubjectProgress do
23
23
  end
24
24
 
25
25
  context 'without results' do
26
- update(:subject_a_result) { { mutation_results: [] } }
26
+ with(:subject_a_result) { { mutation_results: [] } }
27
27
 
28
28
  it_reports <<-'STR'
29
29
  subject-a mutations: 2