mutant 0.7.9 → 0.8.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +11 -1
  3. data/README.md +5 -12
  4. data/bin/mutant +17 -1
  5. data/config/flay.yml +1 -1
  6. data/config/flog.yml +1 -1
  7. data/config/reek.yml +4 -4
  8. data/config/rubocop.yml +21 -3
  9. data/lib/mutant.rb +15 -61
  10. data/lib/mutant/cli.rb +1 -7
  11. data/lib/mutant/color.rb +2 -2
  12. data/lib/mutant/config.rb +1 -1
  13. data/lib/mutant/expression/method.rb +1 -1
  14. data/lib/mutant/expression/methods.rb +1 -1
  15. data/lib/mutant/expression/namespace.rb +1 -1
  16. data/lib/mutant/mutator/node/send.rb +18 -18
  17. data/lib/mutant/reporter/cli.rb +1 -6
  18. data/lib/mutant/reporter/cli/format.rb +2 -2
  19. data/lib/mutant/reporter/cli/printer.rb +5 -500
  20. data/lib/mutant/reporter/cli/printer/config.rb +32 -0
  21. data/lib/mutant/reporter/cli/printer/env_progress.rb +66 -0
  22. data/lib/mutant/reporter/cli/printer/env_result.rb +23 -0
  23. data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +37 -0
  24. data/lib/mutant/reporter/cli/printer/mutation_result.rb +151 -0
  25. data/lib/mutant/reporter/cli/printer/status.rb +60 -0
  26. data/lib/mutant/reporter/cli/printer/status_progressive.rb +52 -0
  27. data/lib/mutant/reporter/cli/printer/subject_progress.rb +90 -0
  28. data/lib/mutant/reporter/cli/printer/subject_result.rb +28 -0
  29. data/lib/mutant/reporter/cli/printer/test_result.rb +33 -0
  30. data/lib/mutant/require_highjack.rb +11 -50
  31. data/lib/mutant/version.rb +1 -1
  32. data/lib/mutant/zombifier.rb +79 -37
  33. data/meta/send.rb +1 -1
  34. data/mutant-rspec.gemspec +1 -1
  35. data/mutant.gemspec +3 -3
  36. data/spec/integration/mutant/corpus_spec.rb +2 -2
  37. data/spec/integration/mutant/rspec_spec.rb +5 -15
  38. data/spec/integrations.yml +3 -3
  39. data/spec/spec_helper.rb +1 -0
  40. data/spec/support/corpus.rb +233 -220
  41. data/spec/support/file_system.rb +60 -0
  42. data/spec/support/rb_bug.rb +1 -1
  43. data/spec/support/ruby_vm.rb +82 -0
  44. data/spec/support/shared_context.rb +19 -10
  45. data/spec/unit/mutant/ast_spec.rb +2 -2
  46. data/spec/unit/mutant/cache_spec.rb +22 -0
  47. data/spec/unit/mutant/cli_spec.rb +1 -30
  48. data/spec/unit/mutant/context_spec.rb +1 -0
  49. data/spec/unit/mutant/expression/method_spec.rb +6 -4
  50. data/spec/unit/mutant/parallel/master_spec.rb +1 -1
  51. data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +33 -0
  52. data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +76 -0
  53. data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +35 -0
  54. data/spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb +23 -0
  55. data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +110 -0
  56. data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +51 -0
  57. data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +145 -0
  58. data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +37 -0
  59. data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +37 -0
  60. data/spec/unit/mutant/reporter/cli/printer/test_result_spec.rb +14 -0
  61. data/spec/unit/mutant/reporter/cli/printer_spec.rb +140 -0
  62. data/spec/unit/mutant/reporter/cli_spec.rb +69 -313
  63. data/spec/unit/mutant/reporter/trace_spec.rb +12 -0
  64. data/spec/unit/mutant/require_highjack_spec.rb +25 -28
  65. data/spec/unit/mutant/warning_filter_spec.rb +7 -0
  66. data/spec/unit/mutant/zombifier_spec.rb +120 -0
  67. data/spec/unit/mutant_spec.rb +0 -43
  68. data/test_app/Gemfile.rspec3.3 +6 -0
  69. metadata +46 -17
  70. data/.travis.yml +0 -20
  71. data/lib/mutant/zombifier/file.rb +0 -100
  72. data/spec/integration/mutant/zombie_spec.rb +0 -6
@@ -0,0 +1,28 @@
1
+ module Mutant
2
+ class Reporter
3
+ class CLI
4
+ class Printer
5
+ # Subject result printer
6
+ class SubjectResult < self
7
+
8
+ delegate :subject, :alive_mutation_results, :tests
9
+
10
+ # Run report printer
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def run
17
+ status(subject.identification)
18
+ tests.each do |test|
19
+ puts("- #{test.identification}")
20
+ end
21
+ visit_collection(MutationResult, alive_mutation_results)
22
+ end
23
+
24
+ end # SubjectResult
25
+ end # Printer
26
+ end # CLI
27
+ end # Reporter
28
+ end # Mutant
@@ -0,0 +1,33 @@
1
+ module Mutant
2
+ class Reporter
3
+ class CLI
4
+ class Printer
5
+ # Test result reporter
6
+ class TestResult < self
7
+
8
+ delegate :tests, :runtime
9
+
10
+ STATUS_FORMAT = '- %d @ runtime: %s'.freeze
11
+ OUTPUT_HEADER = 'Test Output:'.freeze
12
+ TEST_FORMAT = ' - %s'.freeze
13
+
14
+ # Run test result reporter
15
+ #
16
+ # @return [undefined]
17
+ #
18
+ # @api private
19
+ #
20
+ def run
21
+ info(STATUS_FORMAT, tests.length, runtime)
22
+ tests.each do |test|
23
+ info(TEST_FORMAT, test.identification)
24
+ end
25
+ puts(OUTPUT_HEADER)
26
+ puts(object.output)
27
+ end
28
+
29
+ end # TestResult
30
+ end # Printer
31
+ end # CLI
32
+ end # Reporter
33
+ end # Mutant
@@ -1,62 +1,23 @@
1
1
  module Mutant
2
2
  # Require highjack
3
- class RequireHighjack
4
- include Concord.new(:target, :callback)
3
+ module RequireHighjack
5
4
 
6
- # Return original method
5
+ # Install require callback
7
6
  #
8
- # @return [#call]
9
- #
10
- # @api private
11
- #
12
- attr_reader :original
13
-
14
- # Run block with highjacked require
15
- #
16
- # @return [self]
17
- #
18
- # @api private
19
- #
20
- def run
21
- infect
22
- yield
23
- self
24
- ensure
25
- disinfect
26
- end
27
-
28
- # Infect kernel with highjack
29
- #
30
- # @return [self]
31
- #
32
- # @api private
33
- #
34
- def infect
35
- callback = @callback
36
- @original = target.method(:require)
37
- target.module_eval do
38
- undef :require
39
- define_method(:require) do |logical_name|
40
- callback.call(logical_name)
41
- end
42
- module_function :require
43
- end
44
- end
45
-
46
- # Imperfectly disinfect kernel from highjack
7
+ # @param [Module] target
8
+ # @param [#call] callback
47
9
  #
48
- # @return [self]
10
+ # @return [#call]
11
+ # the original implementation on singleton
49
12
  #
50
13
  # @api private
51
14
  #
52
- def disinfect
53
- original = @original
54
- target.module_eval do
55
- undef :require
56
- define_method(:require) do |logical_name|
57
- original.call(logical_name)
15
+ def self.call(target, callback)
16
+ target.method(:require).tap do
17
+ target.module_eval do
18
+ define_method(:require, &callback)
19
+ public :require
58
20
  end
59
- module_function :require
60
21
  end
61
22
  end
62
23
 
@@ -1,4 +1,4 @@
1
1
  module Mutant
2
2
  # The current mutant version
3
- VERSION = '0.7.9'.freeze
3
+ VERSION = '0.8.0'.freeze
4
4
  end # Mutant
@@ -1,20 +1,19 @@
1
1
  module Mutant
2
2
  # Zombifier namespace
3
3
  class Zombifier
4
- include Adamantium::Flat, Concord.new(:namespace)
4
+ include Anima.new(
5
+ :includes,
6
+ :namespace,
7
+ :load_path,
8
+ :kernel,
9
+ :require_highjack,
10
+ :root_require,
11
+ :pathname
12
+ )
5
13
 
6
- # Excluded into zombification
7
- includes = %w[
8
- mutant
9
- unparser
10
- morpher
11
- adamantium
12
- equalizer
13
- anima
14
- concord
15
- ]
14
+ include AST::Sexp
16
15
 
17
- INCLUDES = %r{\A#{Regexp.union(includes)}(?:/.*)?\z}.freeze
16
+ LoadError = Class.new(::LoadError)
18
17
 
19
18
  # Initialize object
20
19
  #
@@ -24,37 +23,28 @@ module Mutant
24
23
  #
25
24
  # @api private
26
25
  #
27
- def initialize(namespace)
26
+ def initialize(*)
27
+ super
28
+ @includes = %r{\A#{Regexp.union(includes)}(?:/.*)?\z}
28
29
  @zombified = Set.new
29
- @highjack = RequireHighjack.new(Kernel, method(:require))
30
- super(namespace)
31
30
  end
32
31
 
33
- # Perform zombification of target library
34
- #
35
- # @param [String] logical_name
36
- # @param [Symbol] namespace
37
- #
38
- # @return [self]
39
- #
40
- # @api private
41
- #
42
- def self.run(logical_name, namespace)
43
- new(namespace).run(logical_name)
32
+ def self.call(*args)
33
+ new(*args).__send__(:call)
44
34
  self
45
35
  end
46
36
 
37
+ private
38
+
47
39
  # Run zombifier
48
40
  #
49
- # @param [String] logical_name
50
- #
51
41
  # @return [undefined]
52
42
  #
53
43
  # @api private
54
44
  #
55
- def run(logical_name)
56
- @highjack.infect
57
- require(logical_name)
45
+ def call
46
+ @original = require_highjack.call(method(:require))
47
+ require(root_require)
58
48
  end
59
49
 
60
50
  # Test if logical name is subjected to zombification
@@ -64,25 +54,77 @@ module Mutant
64
54
  # @api private
65
55
  #
66
56
  def include?(logical_name)
67
- !@zombified.include?(logical_name) && INCLUDES =~ logical_name
57
+ !@zombified.include?(logical_name) && @includes =~ logical_name
68
58
  end
69
59
 
70
60
  # Require file in zombie namespace
71
61
  #
72
62
  # @param [#to_s] logical_name
73
63
  #
74
- # @return [self]
64
+ # @return [undefined]
75
65
  #
76
66
  # @api private
77
67
  #
78
68
  def require(logical_name)
79
69
  logical_name = logical_name.to_s
80
- @highjack.original.call(logical_name)
70
+ @original.call(logical_name)
81
71
  return unless include?(logical_name)
82
72
  @zombified << logical_name
83
- file = File.find(logical_name)
84
- file.zombify(namespace) if file
85
- self
73
+ zombify(find(logical_name))
74
+ end
75
+
76
+ # Find file by logical path
77
+ #
78
+ # @param [String] logical_name
79
+ #
80
+ # @return [File]
81
+ #
82
+ # @raise [LoadError]
83
+ # otherwise
84
+ #
85
+ # @api private
86
+ #
87
+ def find(logical_name)
88
+ file_name = "#{logical_name}.rb"
89
+
90
+ load_path.each do |path|
91
+ path = pathname.new(path).join(file_name)
92
+ return path if path.file?
93
+ end
94
+
95
+ fail LoadError, "Cannot find file #{file_name.inspect} in load path"
96
+ end
97
+
98
+ # Zombify contents of file
99
+ #
100
+ # Probably the 2nd valid use of eval ever. (First one is inserting mutants!).
101
+ #
102
+ # @param [Pathname] source_path
103
+ #
104
+ # @return [undefined]
105
+ #
106
+ # @api private
107
+ #
108
+ # rubocop:disable Lint/Eval
109
+ #
110
+ def zombify(source_path)
111
+ kernel.eval(
112
+ Unparser.unparse(namespaced_node(source_path)),
113
+ TOPLEVEL_BINDING,
114
+ source_path.to_s
115
+ )
116
+ end
117
+
118
+ # Return namespaced root
119
+ #
120
+ # @param [Symbol] namespace
121
+ #
122
+ # @return [Parser::AST::Node]
123
+ #
124
+ # @api private
125
+ #
126
+ def namespaced_node(source_path)
127
+ s(:module, s(:const, nil, namespace), Parser::CurrentRuby.parse(source_path.read))
86
128
  end
87
129
 
88
130
  end # Zombifier
data/meta/send.rb CHANGED
@@ -408,7 +408,7 @@ Mutant::Meta::Example.add do
408
408
  mutation 'self[*bar]'
409
409
  end
410
410
 
411
- (Mutant::AST::Types::BINARY_METHOD_OPERATORS - [:<=, :>=, :<, :>, :==, :eql?]).each do |operator|
411
+ (Mutant::AST::Types::BINARY_METHOD_OPERATORS - %i[<= >= < > == eql?]).each do |operator|
412
412
  Mutant::Meta::Example.add do
413
413
  source "true #{operator} false"
414
414
 
data/mutant-rspec.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
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', '>= 3.0.0', '< 3.3.0')
21
+ gem.add_runtime_dependency('rspec-core', '>= 3.2.0', '< 3.4.0')
22
22
 
23
23
  gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
24
24
  end
data/mutant.gemspec CHANGED
@@ -21,16 +21,16 @@ Gem::Specification.new do |gem|
21
21
  gem.extra_rdoc_files = %w[TODO LICENSE]
22
22
  gem.executables = %w[mutant]
23
23
 
24
- gem.required_ruby_version = '>= 1.9.3'
24
+ gem.required_ruby_version = '>= 2.1'
25
25
 
26
- gem.add_runtime_dependency('parser', '~> 2.2', '>= 2.2.0.2')
26
+ gem.add_runtime_dependency('parser', '~> 2.2.2')
27
27
  gem.add_runtime_dependency('ast', '~> 2.0')
28
28
  gem.add_runtime_dependency('diff-lcs', '~> 1.2')
29
29
  gem.add_runtime_dependency('parallel', '~> 1.3')
30
30
  gem.add_runtime_dependency('morpher', '~> 0.2.3')
31
31
  gem.add_runtime_dependency('procto', '~> 0.0.2')
32
32
  gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
33
- gem.add_runtime_dependency('unparser', '~> 0.2.2')
33
+ gem.add_runtime_dependency('unparser', '~> 0.2.4')
34
34
  gem.add_runtime_dependency('ice_nine', '~> 0.11.1')
35
35
  gem.add_runtime_dependency('adamantium', '~> 0.2.0')
36
36
  gem.add_runtime_dependency('memoizable', '~> 0.4.2')
@@ -5,13 +5,13 @@ RSpec.describe 'Mutant on ruby corpus', mutant: false do
5
5
  skip 'Corpus test is deactivated on RBX' if RUBY_ENGINE.eql?('rbx')
6
6
  end
7
7
 
8
- Corpus::Project::ALL.select(&:mutation_generation).each do |project|
8
+ MutantSpec::Corpus::Project::ALL.select(&:mutation_generation).each do |project|
9
9
  specify "#{project.name} does not fail on mutation generation" do
10
10
  project.verify_mutation_generation
11
11
  end
12
12
  end
13
13
 
14
- Corpus::Project::ALL.select(&:mutation_coverage).each do |project|
14
+ MutantSpec::Corpus::Project::ALL.select(&:mutation_coverage).each do |project|
15
15
  specify "#{project.name} does have expected mutation coverage" do
16
16
  project.verify_mutation_coverage
17
17
  end
@@ -2,21 +2,11 @@ RSpec.describe 'rspec integration', mutant: false do
2
2
 
3
3
  let(:base_cmd) { 'bundle exec mutant -I lib --require test_app --use rspec' }
4
4
 
5
- context 'RSpec 3.0' do
6
- let(:gemfile) { 'Gemfile.rspec3.0' }
5
+ %w[3.2 3.3].each do |version|
6
+ context "RSpec #{version}" do
7
+ let(:gemfile) { "Gemfile.rspec#{version}" }
7
8
 
8
- it_behaves_like 'framework integration'
9
- end
10
-
11
- context 'RSpec 3.1' do
12
- let(:gemfile) { 'Gemfile.rspec3.1' }
13
-
14
- it_behaves_like 'framework integration'
15
- end
16
-
17
- context 'RSpec 3.2' do
18
- let(:gemfile) { 'Gemfile.rspec3.2' }
19
-
20
- it_behaves_like 'framework integration'
9
+ it_behaves_like 'framework integration'
10
+ end
21
11
  end
22
12
  end
@@ -4,7 +4,7 @@
4
4
  repo_uri: 'https://github.com/rubyspec/rubyspec.git'
5
5
  mutation_coverage: false
6
6
  mutation_generation: true
7
- expect_coverage: 0.0 # not run
7
+ expect_coverage: 0 # not run
8
8
  exclude:
9
9
  # Binary encoded source subjected to limitations see README of unparser
10
10
  - core/array/pack/{b,h,u}_spec.rb
@@ -31,11 +31,11 @@
31
31
  mutation_coverage: true
32
32
  mutation_generation: true
33
33
  exclude: []
34
- expect_coverage: 100.0
34
+ expect_coverage: 1
35
35
  - name: axiom
36
36
  namespace: Axiom
37
37
  repo_uri: 'https://github.com/dkubb/axiom.git'
38
38
  mutation_coverage: false
39
39
  mutation_generation: true
40
40
  exclude: []
41
- expect_coverage: 100.0
41
+ expect_coverage: 1
data/spec/spec_helper.rb CHANGED
@@ -20,6 +20,7 @@ end
20
20
 
21
21
  require 'tempfile'
22
22
  require 'concord'
23
+ require 'anima'
23
24
  require 'adamantium'
24
25
  require 'devtools/spec_helper'
25
26
  require 'unparser/cli'
@@ -2,240 +2,253 @@ require 'morpher'
2
2
  require 'anima'
3
3
  require 'mutant'
4
4
 
5
- # Namespace module for corpus testing
6
- module Corpus
7
- # Project under corpus test
8
- # rubocop:disable ClassLength
9
- ROOT = Pathname.new(__FILE__).parent.parent.parent
10
- TMP = ROOT.join('tmp').freeze
11
-
12
- class Project
13
- MUTEX = Mutex.new
14
- include Adamantium, Anima.new(
15
- :name,
16
- :repo_uri,
17
- :exclude,
18
- :mutation_coverage,
19
- :mutation_generation,
20
- :namespace,
21
- :expect_coverage
22
- )
23
-
24
- # Verify mutation coverage
25
- #
26
- # @return [self]
27
- # if successful
28
- #
29
- # @raise [Exception]
30
- #
31
- def verify_mutation_coverage
32
- checkout
33
- Dir.chdir(repo_path) do
34
- Bundler.with_clean_env do
35
- install_mutant
36
- system(%W[bundle exec mutant --use rspec -I lib -r #{name} --score #{expect_coverage} #{namespace}*])
5
+ module MutantSpec
6
+ # Namespace module for corpus testing
7
+ #
8
+ # rubocop:disable MethodLength
9
+ module Corpus
10
+ # Project under corpus test
11
+ # rubocop:disable ClassLength
12
+ ROOT = Pathname.new(__FILE__).parent.parent.parent
13
+ TMP = ROOT.join('tmp').freeze
14
+
15
+ class Project
16
+ MUTEX = Mutex.new
17
+ include Adamantium, Anima.new(
18
+ :name,
19
+ :repo_uri,
20
+ :exclude,
21
+ :mutation_coverage,
22
+ :mutation_generation,
23
+ :namespace,
24
+ :expect_coverage
25
+ )
26
+
27
+ # Verify mutation coverage
28
+ #
29
+ # @return [self]
30
+ # if successful
31
+ #
32
+ # @raise [Exception]
33
+ #
34
+ def verify_mutation_coverage
35
+ checkout
36
+ Dir.chdir(repo_path) do
37
+ Bundler.with_clean_env do
38
+ install_mutant
39
+ system(
40
+ %W[
41
+ bundle exec mutant
42
+ --use rspec
43
+ --include lib
44
+ --require #{name}
45
+ --expected-coverage #{expect_coverage}
46
+ #{namespace}*
47
+ ]
48
+ )
49
+ end
37
50
  end
38
51
  end
39
- end
40
-
41
- # Verify mutation generation
42
- #
43
- # @return [self]
44
- # if successful
45
- #
46
- # @raise [Exception]
47
- # otherwise
48
- #
49
- # rubocop:disable MethodLength
50
- # rubocop:disable AbcSize
51
- #
52
- def verify_mutation_generation
53
- checkout
54
- start = Time.now
55
- paths = Pathname.glob(repo_path.join('**/*.rb')).sort_by(&:size).reverse
56
- options = {
57
- finish: method(:finish),
58
- start: method(:start),
59
- in_processes: parallel_processes
60
- }
61
- total = Parallel.map(paths, options) do |path|
62
- count = 0
63
- node =
64
- begin
65
- Parser::CurrentRuby.parse(path.read)
66
- rescue EncodingError, ArgumentError
67
- nil # Make rubocop happy
52
+
53
+ # Verify mutation generation
54
+ #
55
+ # @return [self]
56
+ # if successful
57
+ #
58
+ # @raise [Exception]
59
+ # otherwise
60
+ #
61
+ # rubocop:disable AbcSize
62
+ #
63
+ def verify_mutation_generation
64
+ checkout
65
+ start = Time.now
66
+ paths = Pathname.glob(repo_path.join('**/*.rb')).sort_by(&:size).reverse
67
+ options = {
68
+ finish: method(:finish),
69
+ start: method(:start),
70
+ in_processes: parallel_processes
71
+ }
72
+ total = Parallel.map(paths, options) do |path|
73
+ count = 0
74
+ node =
75
+ begin
76
+ Parser::CurrentRuby.parse(path.read)
77
+ rescue EncodingError, ArgumentError
78
+ nil # Make rubocop happy
79
+ end
80
+ if node
81
+ Mutant::Mutator::Node.each(node) do
82
+ count += 1
83
+ end
68
84
  end
69
- if node
70
- Mutant::Mutator::Node.each(node) do
71
- count += 1
85
+ count
86
+ end.inject(0, :+)
87
+ took = Time.now - start
88
+ puts format(
89
+ 'Total Mutations/Time/Parse-Errors: %s/%0.2fs - %0.2f/s',
90
+ total,
91
+ took,
92
+ total / took
93
+ )
94
+ self
95
+ end
96
+
97
+ # Checkout repository
98
+ #
99
+ # @return [self]
100
+ #
101
+ # @api private
102
+ #
103
+ def checkout
104
+ return self if noinstall?
105
+ TMP.mkdir unless TMP.directory?
106
+ if repo_path.exist?
107
+ Dir.chdir(repo_path) do
108
+ system(%w[git fetch origin])
109
+ system(%w[git reset --hard])
110
+ system(%w[git clean -f -d -x])
111
+ system(%w[git checkout origin/master])
112
+ system(%w[git reset --hard])
113
+ system(%w[git clean -f -d -x])
72
114
  end
115
+ else
116
+ system(%W[git clone #{repo_uri} #{repo_path}])
73
117
  end
74
- count
75
- end.inject(0, :+)
76
- took = Time.now - start
77
- puts format(
78
- 'Total Mutations/Time/Parse-Errors: %s/%0.2fs - %0.2f/s',
79
- total,
80
- took,
81
- total / took
82
- )
83
- self
84
- end
85
-
86
- # Checkout repository
87
- #
88
- # @return [self]
89
- #
90
- # @api private
91
- #
92
- def checkout
93
- return self if noinstall?
94
- TMP.mkdir unless TMP.directory?
95
- if repo_path.exist?
96
- Dir.chdir(repo_path) do
97
- system(%w[git fetch origin])
98
- system(%w[git reset --hard])
99
- system(%w[git clean -f -d -x])
100
- system(%w[git checkout origin/master])
101
- system(%w[git reset --hard])
102
- system(%w[git clean -f -d -x])
118
+ self
119
+ end
120
+ memoize :checkout
121
+
122
+ private
123
+
124
+ # Install mutant
125
+ #
126
+ # @return [undefined]
127
+ #
128
+ # @api private
129
+ #
130
+ def install_mutant
131
+ return if noinstall?
132
+ relative = ROOT.relative_path_from(repo_path)
133
+ repo_path.join('Gemfile').open('a') do |file|
134
+ file << "gem 'mutant', path: '#{relative}'\n"
135
+ file << "gem 'mutant-rspec', path: '#{relative}'\n"
136
+ end
137
+ lockfile = repo_path.join('Gemfile.lock')
138
+ lockfile.delete if lockfile.exist?
139
+ system('bundle install')
140
+ end
141
+
142
+ # Not in the docs. Number from chatting with their support.
143
+ CIRCLE_CI_CONTAINER_PROCESSES = 2
144
+
145
+ # Return number of parallel processes to use
146
+ #
147
+ # @return [Fixnum]
148
+ #
149
+ # @api private
150
+ #
151
+ def parallel_processes
152
+ if ENV['CI']
153
+ Mutant::Config::DEFAULT.jobs
154
+ else
155
+ Parallel.processor_count
103
156
  end
104
- else
105
- system(%W[git clone #{repo_uri} #{repo_path}])
106
157
  end
107
- self
108
- end
109
- memoize :checkout
110
-
111
- private
112
-
113
- # Install mutant
114
- #
115
- # @return [undefined]
116
- #
117
- # @api private
118
- #
119
- def install_mutant
120
- return if noinstall?
121
- relative = ROOT.relative_path_from(repo_path)
122
- repo_path.join('Gemfile').open('a') do |file|
123
- file << "gem 'mutant', path: '#{relative}'\n"
124
- file << "gem 'mutant-rspec', path: '#{relative}'\n"
158
+
159
+ # Return repository path
160
+ #
161
+ # @return [Pathname]
162
+ #
163
+ # @api private
164
+ #
165
+ def repo_path
166
+ TMP.join(name)
125
167
  end
126
- lockfile = repo_path.join('Gemfile.lock')
127
- lockfile.delete if lockfile.exist?
128
- system('bundle install')
129
- end
130
-
131
- # Not in the docs. Number from chatting with their support.
132
- CIRCLE_CI_CONTAINER_PROCESSES = 2
133
-
134
- # Return number of parallel processes to use
135
- #
136
- # @return [Fixnum]
137
- #
138
- # @api private
139
- #
140
- def parallel_processes
141
- if ENV['CI']
142
- Mutant::Config::DEFAULT.jobs
143
- else
144
- Parallel.processor_count
168
+
169
+ # Test if installation should be skipped
170
+ #
171
+ # @return [Boolean]
172
+ #
173
+ # @api private
174
+ #
175
+ def noinstall?
176
+ ENV.key?('NOINSTALL')
145
177
  end
146
- end
147
-
148
- # Return repository path
149
- #
150
- # @return [Pathname]
151
- #
152
- # @api private
153
- #
154
- def repo_path
155
- TMP.join(name)
156
- end
157
-
158
- # Test if installation should be skipped
159
- #
160
- # @return [Boolean]
161
- #
162
- # @api private
163
- #
164
- def noinstall?
165
- ENV.key?('NOINSTALL')
166
- end
167
-
168
- # Print start progress
169
- #
170
- # @param [Pathname] path
171
- # @param [Fixnum] _index
172
- #
173
- # @return [undefined]
174
- #
175
- def start(path, _index)
176
- MUTEX.synchronize do
177
- puts format('Starting - %s', path)
178
+
179
+ # Print start progress
180
+ #
181
+ # @param [Pathname] path
182
+ # @param [Fixnum] _index
183
+ #
184
+ # @return [undefined]
185
+ #
186
+ def start(path, _index)
187
+ MUTEX.synchronize do
188
+ puts format('Starting - %s', path)
189
+ end
178
190
  end
179
- end
180
-
181
- # Print finish progress
182
- #
183
- # @param [Pathname] path
184
- # @param [Fixnum] _index
185
- # @param [Fixnum] count
186
- #
187
- # @return [undefined]
188
- #
189
- def finish(path, _index, count)
190
- MUTEX.synchronize do
191
- puts format('Mutations - %4i - %s', count, path)
191
+
192
+ # Print finish progress
193
+ #
194
+ # @param [Pathname] path
195
+ # @param [Fixnum] _index
196
+ # @param [Fixnum] count
197
+ #
198
+ # @return [undefined]
199
+ #
200
+ def finish(path, _index, count)
201
+ MUTEX.synchronize do
202
+ puts format('Mutations - %4i - %s', count, path)
203
+ end
192
204
  end
193
- end
194
-
195
- # Helper method to execute system commands
196
- #
197
- # @param [Array<String>] arguments
198
- #
199
- # @api private
200
- #
201
- def system(arguments)
202
- return if Kernel.system(*arguments)
203
- if block_given?
204
- yield
205
- else
206
- fail 'System command failed!'
205
+
206
+ # Helper method to execute system commands
207
+ #
208
+ # @param [Array<String>] arguments
209
+ #
210
+ # @api private
211
+ #
212
+ def system(arguments)
213
+ return if Kernel.system(*arguments)
214
+ if block_given?
215
+ yield
216
+ else
217
+ fail 'System command failed!'
218
+ end
207
219
  end
208
- end
209
-
210
- LOADER = Morpher.build do
211
- s(:block,
212
- s(:guard, s(:primitive, Array)),
213
- s(:map,
214
- s(:block,
215
- s(:guard, s(:primitive, Hash)),
216
- s(:hash_transform,
217
- s(:key_symbolize, :repo_uri, s(:guard, s(:primitive, String))),
218
- s(:key_symbolize, :name, s(:guard, s(:primitive, String))),
219
- s(:key_symbolize, :namespace, s(:guard, s(:primitive, String))),
220
- s(:key_symbolize, :expect_coverage, s(:guard, s(:primitive, Float))),
221
- s(:key_symbolize, :mutation_coverage,
222
- s(:guard, s(:or, s(:primitive, TrueClass), s(:primitive, FalseClass)))),
223
- s(:key_symbolize, :mutation_generation,
224
- s(:guard, s(:or, s(:primitive, TrueClass), s(:primitive, FalseClass)))),
225
- s(:key_symbolize, :exclude, s(:map, s(:guard, s(:primitive, String))))
226
- ),
227
- s(:load_attribute_hash,
228
- # NOTE: The domain param has no DSL currently!
229
- Morpher::Evaluator::Transformer::Domain::Param.new(
230
- Project,
231
- [:repo_uri, :name, :exclude, :mutation_coverage, :mutation_generation]
220
+
221
+ # rubocop:disable ClosingParenthesisIndentation
222
+ LOADER = Morpher.build do
223
+ s(:block,
224
+ s(:guard, s(:primitive, Array)),
225
+ s(:map,
226
+ s(:block,
227
+ s(:guard, s(:primitive, Hash)),
228
+ s(:hash_transform,
229
+ s(:key_symbolize, :repo_uri, s(:guard, s(:primitive, String))),
230
+ s(:key_symbolize, :name, s(:guard, s(:primitive, String))),
231
+ s(:key_symbolize, :namespace, s(:guard, s(:primitive, String))),
232
+ s(:key_symbolize, :expect_coverage, s(:guard, s(:primitive, Fixnum))),
233
+ s(:key_symbolize, :mutation_coverage,
234
+ s(:guard, s(:or, s(:primitive, TrueClass), s(:primitive, FalseClass)))),
235
+ s(:key_symbolize, :mutation_generation,
236
+ s(:guard, s(:or, s(:primitive, TrueClass), s(:primitive, FalseClass)))),
237
+ s(:key_symbolize, :exclude, s(:map, s(:guard, s(:primitive, String))))
238
+ ),
239
+ s(:load_attribute_hash,
240
+ # NOTE: The domain param has no DSL currently!
241
+ Morpher::Evaluator::Transformer::Domain::Param.new(
242
+ Project,
243
+ %i[repo_uri name exclude mutation_coverage mutation_generation]
244
+ )
232
245
  )
233
246
  )
234
247
  )
235
248
  )
236
- )
237
- end
249
+ end
238
250
 
239
- ALL = LOADER.call(YAML.load_file(ROOT.join('spec', 'integrations.yml')))
240
- end # Project
241
- end # Corpus
251
+ ALL = LOADER.call(YAML.load_file(ROOT.join('spec', 'integrations.yml')))
252
+ end # Project
253
+ end # Corpus
254
+ end # MutantSpec