mutant 0.5.26 → 0.6.0

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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.travis.yml +1 -0
  4. data/Changelog.md +16 -3
  5. data/Gemfile +0 -2
  6. data/Gemfile.devtools +2 -2
  7. data/README.md +9 -15
  8. data/bin/mutant +0 -1
  9. data/config/flay.yml +1 -1
  10. data/config/flog.yml +1 -1
  11. data/config/mutant.yml +1 -1
  12. data/config/reek.yml +14 -11
  13. data/config/rubocop.yml +1 -1
  14. data/lib/mutant.rb +22 -21
  15. data/lib/mutant/ast.rb +47 -0
  16. data/lib/mutant/cli.rb +7 -4
  17. data/lib/mutant/config.rb +1 -0
  18. data/lib/mutant/context.rb +1 -1
  19. data/lib/mutant/diff.rb +38 -7
  20. data/lib/mutant/env.rb +22 -3
  21. data/lib/mutant/expression.rb +15 -4
  22. data/lib/mutant/integration.rb +1 -1
  23. data/lib/mutant/isolation.rb +2 -4
  24. data/lib/mutant/matcher.rb +1 -1
  25. data/lib/mutant/matcher/method.rb +1 -1
  26. data/lib/mutant/matcher/method/singleton.rb +1 -1
  27. data/lib/mutant/matcher/methods.rb +0 -2
  28. data/lib/mutant/meta/example.rb +0 -2
  29. data/lib/mutant/meta/example/dsl.rb +1 -1
  30. data/lib/mutant/mutator.rb +1 -1
  31. data/lib/mutant/mutator/node.rb +3 -3
  32. data/lib/mutant/mutator/node/begin.rb +1 -1
  33. data/lib/mutant/mutator/node/block.rb +16 -3
  34. data/lib/mutant/mutator/node/if.rb +1 -1
  35. data/lib/mutant/mutator/node/literal/fixnum.rb +1 -1
  36. data/lib/mutant/mutator/node/resbody.rb +0 -2
  37. data/lib/mutant/mutator/node/send.rb +17 -7
  38. data/lib/mutant/mutator/node/send/index.rb +0 -2
  39. data/lib/mutant/mutator/registry.rb +1 -1
  40. data/lib/mutant/mutator/util.rb +1 -1
  41. data/lib/mutant/mutator/util/array.rb +1 -1
  42. data/lib/mutant/reporter.rb +13 -3
  43. data/lib/mutant/reporter/cli.rb +54 -8
  44. data/lib/mutant/reporter/cli/format.rb +197 -0
  45. data/lib/mutant/reporter/cli/printer.rb +402 -22
  46. data/lib/mutant/reporter/cli/tput.rb +27 -0
  47. data/lib/mutant/reporter/null.rb +4 -34
  48. data/lib/mutant/reporter/trace.rb +6 -38
  49. data/lib/mutant/result.rb +44 -56
  50. data/lib/mutant/runner.rb +99 -52
  51. data/lib/mutant/runner/collector.rb +134 -0
  52. data/lib/mutant/subject/method/instance.rb +12 -4
  53. data/lib/mutant/version.rb +1 -1
  54. data/lib/mutant/warning_filter.rb +0 -2
  55. data/lib/mutant/zombifier/file.rb +1 -1
  56. data/meta/block.rb +17 -1
  57. data/meta/send.rb +123 -1
  58. data/mutant-rspec.gemspec +3 -3
  59. data/mutant.gemspec +1 -1
  60. data/spec/integration/mutant/corpus_spec.rb +4 -195
  61. data/spec/integration/mutant/null_spec.rb +1 -3
  62. data/spec/integration/mutant/rspec_spec.rb +1 -3
  63. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +1 -3
  64. data/spec/integration/mutant/zombie_spec.rb +1 -3
  65. data/spec/integrations.yml +7 -0
  66. data/spec/shared/method_matcher_behavior.rb +1 -1
  67. data/spec/spec_helper.rb +1 -0
  68. data/spec/support/compress_helper.rb +1 -0
  69. data/spec/support/corpus.rb +239 -0
  70. data/spec/support/mutation_verifier.rb +2 -4
  71. data/spec/unit/mutant/cli_spec.rb +20 -13
  72. data/spec/unit/mutant/context/root_spec.rb +1 -3
  73. data/spec/unit/mutant/context/scope/root_spec.rb +1 -3
  74. data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +1 -3
  75. data/spec/unit/mutant/diff_spec.rb +37 -19
  76. data/spec/unit/mutant/expression/method_spec.rb +5 -7
  77. data/spec/unit/mutant/expression/methods_spec.rb +5 -7
  78. data/spec/unit/mutant/expression/namespace/flat_spec.rb +6 -8
  79. data/spec/unit/mutant/expression/namespace/recursive_spec.rb +6 -7
  80. data/spec/unit/mutant/expression_spec.rb +14 -5
  81. data/spec/unit/mutant/integration_spec.rb +14 -3
  82. data/spec/unit/mutant/isolation_spec.rb +2 -4
  83. data/spec/unit/mutant/loader/eval_spec.rb +1 -3
  84. data/spec/unit/mutant/matcher/chain_spec.rb +1 -3
  85. data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +21 -0
  86. data/spec/unit/mutant/matcher/compiler_spec.rb +28 -3
  87. data/spec/unit/mutant/matcher/filter_spec.rb +1 -3
  88. data/spec/unit/mutant/matcher/method/instance_spec.rb +3 -5
  89. data/spec/unit/mutant/matcher/method/singleton_spec.rb +22 -4
  90. data/spec/unit/mutant/matcher/methods/instance_spec.rb +7 -6
  91. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +4 -6
  92. data/spec/unit/mutant/matcher/namespace_spec.rb +1 -3
  93. data/spec/unit/mutant/matcher/null_spec.rb +1 -3
  94. data/spec/unit/mutant/mutation_spec.rb +1 -3
  95. data/spec/unit/mutant/mutator/node_spec.rb +1 -3
  96. data/spec/unit/mutant/reporter/cli_spec.rb +444 -206
  97. data/spec/unit/mutant/reporter/null_spec.rb +1 -3
  98. data/spec/unit/mutant/require_highjack_spec.rb +1 -3
  99. data/spec/unit/mutant/runner_spec.rb +42 -28
  100. data/spec/unit/mutant/subject/context_spec.rb +1 -3
  101. data/spec/unit/mutant/subject/method/instance_spec.rb +27 -19
  102. data/spec/unit/mutant/subject/method/singleton_spec.rb +49 -17
  103. data/spec/unit/mutant/subject_spec.rb +1 -3
  104. data/spec/unit/mutant/test_spec.rb +1 -3
  105. data/spec/unit/mutant/warning_expectation.rb +1 -3
  106. data/spec/unit/mutant/warning_filter_spec.rb +1 -3
  107. data/spec/unit/mutant_spec.rb +13 -3
  108. data/test_app/Gemfile.devtools +2 -2
  109. data/test_app/spec/unit/test_app/literal/string_spec.rb +1 -1
  110. metadata +10 -21
  111. data/lib/mutant/matcher/method/finder.rb +0 -72
  112. data/lib/mutant/reporter/cli/progress.rb +0 -10
  113. data/lib/mutant/reporter/cli/progress/config.rb +0 -30
  114. data/lib/mutant/reporter/cli/progress/env.rb +0 -30
  115. data/lib/mutant/reporter/cli/progress/noop.rb +0 -27
  116. data/lib/mutant/reporter/cli/progress/result.rb +0 -12
  117. data/lib/mutant/reporter/cli/progress/result/mutation.rb +0 -45
  118. data/lib/mutant/reporter/cli/progress/result/subject.rb +0 -54
  119. data/lib/mutant/reporter/cli/progress/subject.rb +0 -27
  120. data/lib/mutant/reporter/cli/registry.rb +0 -81
  121. data/lib/mutant/reporter/cli/report.rb +0 -10
  122. data/lib/mutant/reporter/cli/report/env.rb +0 -92
  123. data/lib/mutant/reporter/cli/report/mutation.rb +0 -103
  124. data/lib/mutant/reporter/cli/report/subject.rb +0 -32
  125. data/lib/mutant/reporter/cli/report/test.rb +0 -28
  126. data/lib/mutant/walker.rb +0 -53
  127. data/spec/shared/mutator_behavior.rb +0 -55
@@ -0,0 +1,134 @@
1
+ module Mutant
2
+ class Runner
3
+ # Parallel process collector
4
+ class Collector
5
+ include Concord::Public.new(:env)
6
+
7
+ # Initialize object
8
+ #
9
+ # @return [undefined]
10
+ #
11
+ # @api private
12
+ #
13
+ def initialize(*)
14
+ super
15
+ @start = Time.now
16
+ @aggregate = Hash.new { |hash, key| hash[key] = [] }
17
+ @activity = Hash.new(0)
18
+ @last_mutation_result = nil
19
+ end
20
+
21
+ # Return last mutation result
22
+ #
23
+ # @return [Result::Mutation]
24
+ # if there is a last mutation result
25
+ #
26
+ # @return [nil]
27
+ # otherwise
28
+ #
29
+ # @api private
30
+ #
31
+ attr_reader :last_mutation_result
32
+
33
+ # Return active subject results
34
+ #
35
+ # @return [Array<Result::Subject>]
36
+ #
37
+ # @api private
38
+ #
39
+ def active_subject_results
40
+ active_subjects.map(&method(:subject_result))
41
+ end
42
+
43
+ # Return current result
44
+ #
45
+ # @return [Result::Env]
46
+ #
47
+ # @api private
48
+ #
49
+ def result
50
+ Result::Env.new(
51
+ env: env,
52
+ runtime: Time.now - @start,
53
+ subject_results: subject_results,
54
+ done: false
55
+ )
56
+ end
57
+
58
+ # Handle mutation start
59
+ #
60
+ # @param [Mutation] mutation
61
+ #
62
+ # @return [self]
63
+ #
64
+ # @api private
65
+ #
66
+ def start(mutation)
67
+ @activity[mutation.subject] += 1
68
+ self
69
+ end
70
+
71
+ # Handle mutation finish
72
+ #
73
+ # @param [Result::Mutation] mutation_result
74
+ #
75
+ # @return [self]
76
+ #
77
+ # @api private
78
+ #
79
+ def finish(mutation_result)
80
+ @last_mutation_result = mutation_result
81
+
82
+ subject = mutation_result.mutation.subject
83
+
84
+ @activity[subject] -= 1
85
+ @aggregate[subject] << mutation_result
86
+
87
+ self
88
+ end
89
+
90
+ private
91
+
92
+ # Return current subject results
93
+ #
94
+ # @return [Array<Result::Subject>]
95
+ #
96
+ # @api private
97
+ #
98
+ def subject_results
99
+ env.subjects.map(&method(:subject_result))
100
+ end
101
+
102
+ # Return active subjects
103
+ #
104
+ # @return [Array<Subject>]
105
+ #
106
+ # @api private
107
+ #
108
+ def active_subjects
109
+ @activity.select do |_subject, count|
110
+ count > 0
111
+ end.map(&:first)
112
+ end
113
+
114
+ # Return current subject result
115
+ #
116
+ # @param [Subject] subject
117
+ #
118
+ # @return [Array<Subject::Result>]
119
+ #
120
+ # @api private
121
+ #
122
+ def subject_result(subject)
123
+ mutation_results = @aggregate[subject].sort_by(&:index)
124
+
125
+ Result::Subject.new(
126
+ subject: subject,
127
+ runtime: mutation_results.map(&:runtime).inject(0.0, :+),
128
+ mutation_results: mutation_results
129
+ )
130
+ end
131
+
132
+ end # Collector
133
+ end # Runner
134
+ end # Mutant
@@ -5,7 +5,15 @@ module Mutant
5
5
  class Instance < self
6
6
 
7
7
  NAME_INDEX = 0
8
- SYMBOL = '#'.freeze
8
+ SYMBOL = '#'.freeze
9
+
10
+ # A list of methods that will warn when they are undefined
11
+ WARN_METHODS_UNDEFINED =
12
+ if RUBY_ENGINE.eql?('ruby')
13
+ [:initialize, :__send__, :object_id].freeze
14
+ else
15
+ EMPTY_ARRAY
16
+ end
9
17
 
10
18
  # Test if method is public
11
19
  #
@@ -26,10 +34,10 @@ module Mutant
26
34
  #
27
35
  def prepare
28
36
  expected_warnings =
29
- if RUBY_ENGINE.eql?('ruby') && name.equal?(:initialize)
30
- ["#{__FILE__}:#{__LINE__ + 5}: warning: undefining `initialize' may cause serious problems\n"]
37
+ if WARN_METHODS_UNDEFINED.include?(name)
38
+ ["#{__FILE__}:#{__LINE__ + 5}: warning: undefining `#{name}' may cause serious problems\n"]
31
39
  else
32
- []
40
+ EMPTY_ARRAY
33
41
  end
34
42
  WarningExpectation.new(expected_warnings).execute do
35
43
  scope.send(:undef_method, name)
@@ -1,4 +1,4 @@
1
1
  module Mutant
2
2
  # The current mutant version
3
- VERSION = '0.5.26'.freeze
3
+ VERSION = '0.6.0'.freeze
4
4
  end # Mutant
@@ -1,5 +1,3 @@
1
- # encoding: UTF-8
2
-
3
1
  module Mutant
4
2
  # Stream filter for warnings
5
3
  class WarningFilter
@@ -1,6 +1,6 @@
1
1
  module Mutant
2
2
  class Zombifier
3
- # File containing source beeing zombified
3
+ # File containing source being zombified
4
4
  class File
5
5
  include Adamantium::Flat, Concord::Public.new(:path), AST::Sexp
6
6
 
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  Mutant::Meta::Example.add do
4
- source 'foo() { a; b }'
4
+ source 'foo { a; b }'
5
5
 
6
6
  singleton_mutations
7
7
  mutation 'foo { a }'
@@ -13,6 +13,7 @@ Mutant::Meta::Example.add do
13
13
  mutation 'foo { nil; b }'
14
14
  mutation 'foo { self; b }'
15
15
  mutation 'foo'
16
+ mutation 'a; b'
16
17
  end
17
18
 
18
19
  Mutant::Meta::Example.add do
@@ -45,6 +46,21 @@ Mutant::Meta::Example.add do
45
46
  mutation 'foo'
46
47
  end
47
48
 
49
+ Mutant::Meta::Example.add do
50
+ source 'foo(a, b) {}'
51
+
52
+ singleton_mutations
53
+ mutation 'foo(a, nil) {}'
54
+ mutation 'foo(nil, b) {}'
55
+ mutation 'foo(self, b) {}'
56
+ mutation 'foo(a, self) {}'
57
+ mutation 'foo(a, b)'
58
+ mutation 'foo(a, b) { raise }'
59
+ mutation 'foo(a) {}'
60
+ mutation 'foo(b) {}'
61
+ mutation 'foo {}'
62
+ end
63
+
48
64
  Mutant::Meta::Example.add do
49
65
  source 'foo { |(a)| }'
50
66
 
@@ -1,5 +1,67 @@
1
1
  # encoding: utf-8
2
2
 
3
+ Mutant::Meta::Example.add do
4
+ source 'a > b'
5
+
6
+ singleton_mutations
7
+ mutation 'a == b'
8
+ mutation 'a.eql?(b)'
9
+ mutation 'a.equal?(b)'
10
+ mutation 'nil > b'
11
+ mutation 'self > b'
12
+ mutation 'a > nil'
13
+ mutation 'a > self'
14
+ mutation 'a'
15
+ mutation 'b'
16
+ end
17
+
18
+ Mutant::Meta::Example.add do
19
+ source 'a >= b'
20
+
21
+ singleton_mutations
22
+ mutation 'a > b'
23
+ mutation 'a == b'
24
+ mutation 'a.eql?(b)'
25
+ mutation 'a.equal?(b)'
26
+ mutation 'nil >= b'
27
+ mutation 'self >= b'
28
+ mutation 'a >= nil'
29
+ mutation 'a >= self'
30
+ mutation 'a'
31
+ mutation 'b'
32
+ end
33
+
34
+ Mutant::Meta::Example.add do
35
+ source 'a <= b'
36
+
37
+ singleton_mutations
38
+ mutation 'a < b'
39
+ mutation 'a == b'
40
+ mutation 'a.eql?(b)'
41
+ mutation 'a.equal?(b)'
42
+ mutation 'nil <= b'
43
+ mutation 'self <= b'
44
+ mutation 'a <= nil'
45
+ mutation 'a <= self'
46
+ mutation 'a'
47
+ mutation 'b'
48
+ end
49
+
50
+ Mutant::Meta::Example.add do
51
+ source 'a < b'
52
+
53
+ singleton_mutations
54
+ mutation 'a == b'
55
+ mutation 'a.eql?(b)'
56
+ mutation 'a.equal?(b)'
57
+ mutation 'nil < b'
58
+ mutation 'self < b'
59
+ mutation 'a < nil'
60
+ mutation 'a < self'
61
+ mutation 'a'
62
+ mutation 'b'
63
+ end
64
+
3
65
  Mutant::Meta::Example.add do
4
66
  source 'reverse_each'
5
67
 
@@ -7,6 +69,13 @@ Mutant::Meta::Example.add do
7
69
  mutation 'each'
8
70
  end
9
71
 
72
+ Mutant::Meta::Example.add do
73
+ source 'reverse_merge'
74
+
75
+ singleton_mutations
76
+ mutation 'merge'
77
+ end
78
+
10
79
  Mutant::Meta::Example.add do
11
80
  source 'reverse_map'
12
81
 
@@ -22,6 +91,33 @@ Mutant::Meta::Example.add do
22
91
  mutation 'each'
23
92
  end
24
93
 
94
+ Mutant::Meta::Example.add do
95
+ source 'foo.to_s'
96
+
97
+ singleton_mutations
98
+ mutation 'foo'
99
+ mutation 'self.to_s'
100
+ mutation 'foo.to_str'
101
+ end
102
+
103
+ Mutant::Meta::Example.add do
104
+ source 'foo.to_a'
105
+
106
+ singleton_mutations
107
+ mutation 'foo'
108
+ mutation 'self.to_a'
109
+ mutation 'foo.to_ary'
110
+ end
111
+
112
+ Mutant::Meta::Example.add do
113
+ source 'foo.to_i'
114
+
115
+ singleton_mutations
116
+ mutation 'foo'
117
+ mutation 'self.to_i'
118
+ mutation 'foo.to_int'
119
+ end
120
+
25
121
  Mutant::Meta::Example.add do
26
122
  source 'foo == bar'
27
123
 
@@ -36,6 +132,32 @@ Mutant::Meta::Example.add do
36
132
  mutation 'foo.equal?(bar)'
37
133
  end
38
134
 
135
+ Mutant::Meta::Example.add do
136
+ source 'foo.is_a?(bar)'
137
+
138
+ singleton_mutations
139
+ mutation 'foo'
140
+ mutation 'bar'
141
+ mutation 'foo.is_a?'
142
+ mutation 'foo.is_a?(nil)'
143
+ mutation 'foo.is_a?(self)'
144
+ mutation 'self.is_a?(bar)'
145
+ mutation 'foo.instance_of?(bar)'
146
+ end
147
+
148
+ Mutant::Meta::Example.add do
149
+ source 'foo.kind_of?(bar)'
150
+
151
+ singleton_mutations
152
+ mutation 'foo'
153
+ mutation 'bar'
154
+ mutation 'foo.kind_of?'
155
+ mutation 'foo.kind_of?(nil)'
156
+ mutation 'foo.kind_of?(self)'
157
+ mutation 'self.kind_of?(bar)'
158
+ mutation 'foo.instance_of?(bar)'
159
+ end
160
+
39
161
  Mutant::Meta::Example.add do
40
162
  source 'foo.gsub(a, b)'
41
163
 
@@ -259,7 +381,7 @@ Mutant::Meta::Example.add do
259
381
  mutation 'self[*bar]'
260
382
  end
261
383
 
262
- (Mutant::AST::Types::BINARY_METHOD_OPERATORS - [:==, :eql?]).each do |operator|
384
+ (Mutant::AST::Types::BINARY_METHOD_OPERATORS - [:<=, :>=, :<, :>, :==, :eql?]).each do |operator|
263
385
  Mutant::Meta::Example.add do
264
386
  source "true #{operator} false"
265
387
 
@@ -13,12 +13,12 @@ Gem::Specification.new do |gem|
13
13
  gem.license = 'MIT'
14
14
 
15
15
  gem.require_paths = %w[lib]
16
- gem.files = `git ls-files -- lib/mutant/integration/rspec{,2,3}.rb`.split("\n")
17
- gem.test_files = `git ls-files -- spec/{unit/mutant/rspec,integration/rspec}`.split("\n")
16
+ gem.files = `git ls-files -- lib/mutant/integration/rspec.rb`.split("\n")
17
+ gem.test_files = `git ls-files -- spec/{unit,integration}/mutant/rspec/**/*.rb}`.split("\n")
18
18
  gem.extra_rdoc_files = %w[TODO LICENSE]
19
19
 
20
20
  gem.add_runtime_dependency('mutant', "~> #{gem.version}")
21
- gem.add_runtime_dependency('rspec-core', '>= 2.14.1', '<= 3.0.0')
21
+ gem.add_runtime_dependency('rspec-core', '>= 2.14.1', '< 3.1.0')
22
22
 
23
23
  gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
24
24
  end
@@ -37,7 +37,7 @@ Gem::Specification.new do |gem|
37
37
  gem.add_runtime_dependency('inflecto', '~> 0.0.2')
38
38
  gem.add_runtime_dependency('anima', '~> 0.2.0')
39
39
  gem.add_runtime_dependency('concord', '~> 0.1.5')
40
- gem.add_runtime_dependency('parallel', '~> 1.0.0')
40
+ gem.add_runtime_dependency('parallel', '~> 1.2.0')
41
41
 
42
42
  gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
43
43
  end
@@ -1,209 +1,18 @@
1
- # encoding: UTF-8
2
-
3
- require 'parallel'
4
- require 'spec_helper'
5
-
6
- describe 'Mutant on ruby corpus' do
7
-
8
- ROOT = Pathname.new(__FILE__).parent.parent.parent.parent
9
-
10
- TMP = ROOT.join('tmp').freeze
1
+ RSpec.describe 'Mutant on ruby corpus' do
11
2
 
12
3
  before do
13
4
  skip 'Corpus test is deactivated on 1.9.3' if RUBY_VERSION.eql?('1.9.3')
14
5
  skip 'Corpus test is deactivated on RBX' if RUBY_ENGINE.eql?('rbx')
15
6
  end
16
7
 
17
- MUTEX = Mutex.new
18
-
19
- class Project
20
- include Adamantium, Anima.new(
21
- :name,
22
- :repo_uri,
23
- :exclude,
24
- :mutation_coverage,
25
- :mutation_generation,
26
- :namespace,
27
- :expect_coverage
28
- )
29
-
30
- # Verify mutation coverage
31
- #
32
- # @return [self]
33
- # if successufl
34
- #
35
- # @raise [Exception]
36
- #
37
- def verify_mutation_coverage
38
- checkout
39
- Dir.chdir(repo_path) do
40
- relative = ROOT.relative_path_from(repo_path)
41
- devtools = ROOT.join('Gemfile.devtools').read
42
- devtools << "gem 'mutant', path: '#{relative}'\n"
43
- devtools << "gem 'mutant-rspec', path: '#{relative}'\n"
44
- File.write(repo_path.join('Gemfile.devtools'), devtools)
45
- lockfile = repo_path.join('Gemfile.lock')
46
- lockfile.delete if lockfile.exist?
47
- Bundler.with_clean_env do
48
- system('bundle install')
49
- system(%W[bundle exec mutant -I lib -r #{name} --score #{expect_coverage} --use rspec #{namespace}*])
50
- end
51
- end
52
- end
53
-
54
- # Verify mutation generation
55
- #
56
- # @return [self]
57
- # if successful
58
- #
59
- # @raise [Exception]
60
- # otherwise
61
- #
62
- # rubocop:disable MethodLength
63
- def verify_mutation_generation
64
- checkout
65
- start = Time.now
66
- paths = Pathname.glob(repo_path.join('**/*.rb')).sort_by(&:size).reverse
67
- total = Parallel.map(paths, finish: method(:finish), start: method(:start)) do |path|
68
- count = 0
69
- node =
70
- begin
71
- Parser::CurrentRuby.parse(path.read)
72
- rescue EncodingError, ArgumentError
73
- nil # Make rubocop happy
74
- end
75
- if node
76
- Mutant::Mutator::Node.each(node) do
77
- count += 1
78
- end
79
- end
80
- count
81
- end.inject(0, :+)
82
- took = Time.now - start
83
- puts format(
84
- 'Total Mutations/Time/Parse-Errors: %s/%0.2fs - %0.2f/s',
85
- total,
86
- took,
87
- total / took
88
- )
89
- self
90
- end
91
-
92
- # Checkout repository
93
- #
94
- # @return [self]
95
- #
96
- # @api private
97
- #
98
- def checkout
99
- TMP.mkdir unless TMP.directory?
100
- if repo_path.exist?
101
- Dir.chdir(repo_path) do
102
- system(%w[git pull -f origin master])
103
- system(%w[git clean -f -d -x])
104
- end
105
- else
106
- system(%W[git clone #{repo_uri} #{repo_path}])
107
- end
108
- self
109
- end
110
- memoize :checkout
111
-
112
- private
113
-
114
- # Return repository path
115
- #
116
- # @return [Pathname]
117
- #
118
- # @api private
119
- #
120
- def repo_path
121
- TMP.join(name)
122
- end
123
-
124
- # Print start progress
125
- #
126
- # @param [Pathname] path
127
- # @param [Fixnum] _index
128
- # @param [Fixnum] count
129
- #
130
- # @return [undefined]
131
- #
132
- def start(path, _index)
133
- MUTEX.synchronize do
134
- puts format('Starting - %s', path)
135
- end
136
- end
137
-
138
- # Print finish progress
139
- #
140
- # @param [Pathname] path
141
- # @param [Fixnum] _index
142
- # @param [Fixnum] count
143
- #
144
- # @return [undefined]
145
- #
146
- def finish(path, _index, count)
147
- MUTEX.synchronize do
148
- puts format('Mutations - %4i - %s', count, path)
149
- end
150
- end
151
-
152
- # Helper method to execute system commands
153
- #
154
- # @param [Array<String>] arguments
155
- #
156
- # @api private
157
- #
158
- def system(arguments)
159
- return if Kernel.system(*arguments)
160
- if block_given?
161
- yield
162
- else
163
- fail 'System command failed!'
164
- end
165
- end
166
-
167
- LOADER = Morpher.build do
168
- s(:block,
169
- s(:guard, s(:primitive, Array)),
170
- s(:map,
171
- s(:block,
172
- s(:guard, s(:primitive, Hash)),
173
- s(:hash_transform,
174
- s(:key_symbolize, :repo_uri, s(:guard, s(:primitive, String))),
175
- s(:key_symbolize, :name, s(:guard, s(:primitive, String))),
176
- s(:key_symbolize, :namespace, s(:guard, s(:primitive, String))),
177
- s(:key_symbolize, :expect_coverage, s(:guard, s(:primitive, Float))),
178
- s(:key_symbolize, :mutation_coverage,
179
- s(:guard, s(:or, s(:primitive, TrueClass), s(:primitive, FalseClass)))),
180
- s(:key_symbolize, :mutation_generation,
181
- s(:guard, s(:or, s(:primitive, TrueClass), s(:primitive, FalseClass)))),
182
- s(:key_symbolize, :exclude, s(:map, s(:guard, s(:primitive, String))))
183
- ),
184
- s(:load_attribute_hash,
185
- # NOTE: The domain param has no DSL currently!
186
- Morpher::Evaluator::Transformer::Domain::Param.new(
187
- Project,
188
- [:repo_uri, :name, :exclude, :mutation_coverage, :mutation_generation]
189
- )
190
- )
191
- )
192
- )
193
- )
194
- end
195
-
196
- ALL = LOADER.call(YAML.load_file(ROOT.join('spec', 'integrations.yml')))
197
- end
198
-
199
- Project::ALL.select(&:mutation_generation).each do |project|
8
+ Corpus::Project::ALL.select(&:mutation_generation).each do |project|
200
9
  specify "#{project.name} does not fail on mutation generation" do
201
10
  project.verify_mutation_generation
202
11
  end
203
12
  end
204
13
 
205
- Project::ALL.select(&:mutation_coverage).each do |project|
206
- specify "#{project.name} does have expected mutaiton coverage" do
14
+ Corpus::Project::ALL.select(&:mutation_coverage).each do |project|
15
+ specify "#{project.name} does have expected mutation coverage" do
207
16
  project.verify_mutation_coverage
208
17
  end
209
18
  end