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
@@ -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