mutant 0.6.7 → 0.7.1
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.
- checksums.yaml +4 -4
 - data/Changelog.md +10 -0
 - data/README.md +1 -1
 - data/config/flay.yml +1 -1
 - data/config/reek.yml +11 -40
 - data/config/rubocop.yml +1 -1
 - data/lib/mutant.rb +10 -2
 - data/lib/mutant/actor.rb +64 -0
 - data/lib/mutant/actor/actor.rb +50 -0
 - data/lib/mutant/actor/env.rb +35 -0
 - data/lib/mutant/actor/mailbox.rb +53 -0
 - data/lib/mutant/actor/receiver.rb +48 -0
 - data/lib/mutant/actor/sender.rb +27 -0
 - data/lib/mutant/ast/types.rb +1 -1
 - data/lib/mutant/cli.rb +2 -0
 - data/lib/mutant/config.rb +2 -1
 - data/lib/mutant/env.rb +6 -2
 - data/lib/mutant/expression/methods.rb +1 -1
 - data/lib/mutant/integration.rb +11 -1
 - data/lib/mutant/isolation.rb +1 -2
 - data/lib/mutant/meta/example.rb +1 -1
 - data/lib/mutant/mutation.rb +47 -21
 - data/lib/mutant/mutator/node.rb +1 -1
 - data/lib/mutant/mutator/node/literal/symbol.rb +1 -1
 - data/lib/mutant/mutator/node/send.rb +4 -3
 - data/lib/mutant/reporter/cli.rb +2 -0
 - data/lib/mutant/reporter/cli/format.rb +23 -36
 - data/lib/mutant/reporter/cli/printer.rb +66 -27
 - data/lib/mutant/result.rb +45 -58
 - data/lib/mutant/runner.rb +47 -154
 - data/lib/mutant/runner/master.rb +174 -0
 - data/lib/mutant/runner/scheduler.rb +141 -0
 - data/lib/mutant/runner/worker.rb +93 -0
 - data/lib/mutant/subject/method/instance.rb +1 -15
 - data/lib/mutant/test.rb +2 -15
 - data/lib/mutant/version.rb +1 -1
 - data/meta/send.rb +16 -0
 - data/mutant-rspec.gemspec +1 -1
 - data/mutant.gemspec +1 -1
 - data/spec/integration/mutant/rspec_spec.rb +0 -6
 - data/spec/spec_helper.rb +9 -1
 - data/spec/support/fake_actor.rb +93 -0
 - data/spec/support/shared_context.rb +135 -0
 - data/spec/unit/mutant/actor/actor_spec.rb +35 -0
 - data/spec/unit/mutant/actor/binding_spec.rb +32 -0
 - data/spec/unit/mutant/actor/env_spec.rb +49 -0
 - data/spec/unit/mutant/actor/message_spec.rb +23 -0
 - data/spec/unit/mutant/actor/receiver_spec.rb +60 -0
 - data/spec/unit/mutant/actor/sender_spec.rb +22 -0
 - data/spec/unit/mutant/cli_spec.rb +17 -4
 - data/spec/unit/mutant/env_spec.rb +2 -2
 - data/spec/unit/mutant/mailbox_spec.rb +33 -0
 - data/spec/unit/mutant/mutation_spec.rb +52 -18
 - data/spec/unit/mutant/mutator/registry_spec.rb +4 -4
 - data/spec/unit/mutant/reporter/cli_spec.rb +131 -249
 - data/spec/unit/mutant/result/env_spec.rb +55 -0
 - data/spec/unit/mutant/result/subject_spec.rb +43 -0
 - data/spec/unit/mutant/runner/master_spec.rb +199 -0
 - data/spec/unit/mutant/runner/scheduler_spec.rb +161 -0
 - data/spec/unit/mutant/runner/worker_spec.rb +73 -0
 - data/spec/unit/mutant/runner_spec.rb +60 -118
 - data/spec/unit/mutant/subject/method/instance_spec.rb +18 -31
 - data/spec/unit/mutant/warning_filter_spec.rb +1 -1
 - metadata +39 -14
 - data/lib/mutant/runner/collector.rb +0 -133
 - data/lib/mutant/warning_expectation.rb +0 -47
 - data/spec/unit/mutant/runner/collector_spec.rb +0 -198
 - data/spec/unit/mutant/test_spec.rb +0 -23
 - data/spec/unit/mutant/warning_expectation_spec.rb +0 -80
 - data/test_app/Gemfile.rspec2 +0 -6
 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Mutant
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Actor
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                # Sender for messages to acting thread
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Sender
         
     | 
| 
      
 6 
     | 
    
         
            +
                  include Concord.new(:thread, :mutex, :mailbox)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  # Send a message to actor
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # @param [Object] message
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # @return [self]
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #
         
     | 
| 
      
 16 
     | 
    
         
            +
                  def call(message)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    mutex.synchronize do
         
     | 
| 
      
 18 
     | 
    
         
            +
                      mailbox << message
         
     | 
| 
      
 19 
     | 
    
         
            +
                      thread.run
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    self
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                end # Sender
         
     | 
| 
      
 26 
     | 
    
         
            +
              end # Actor
         
     | 
| 
      
 27 
     | 
    
         
            +
            end # Mutant
         
     | 
    
        data/lib/mutant/ast/types.rb
    CHANGED
    
    | 
         @@ -18,7 +18,7 @@ module Mutant 
     | 
|
| 
       18 
18 
     | 
    
         
             
                  INDEX_OPERATORS        = symbolset.(%w[[] []=])
         
     | 
| 
       19 
19 
     | 
    
         
             
                  UNARY_METHOD_OPERATORS = symbolset.(%w[~@ +@ -@ !])
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                  # Operators ruby  
     | 
| 
      
 21 
     | 
    
         
            +
                  # Operators ruby implements as methods
         
     | 
| 
       22 
22 
     | 
    
         
             
                  METHOD_OPERATORS = symbolset.(%w[
         
     | 
| 
       23 
23 
     | 
    
         
             
                    <=> === []= [] <= >= == !~ != =~ <<
         
     | 
| 
       24 
24 
     | 
    
         
             
                    >> ** * % / | ^ & < > + - ~@ +@ -@ !
         
     | 
    
        data/lib/mutant/cli.rb
    CHANGED
    
    | 
         @@ -128,6 +128,8 @@ module Mutant 
     | 
|
| 
       128 
128 
     | 
    
         
             
                def setup_integration(name)
         
     | 
| 
       129 
129 
     | 
    
         
             
                  require "mutant/integration/#{name}"
         
     | 
| 
       130 
130 
     | 
    
         
             
                  update(integration: Integration.lookup(name))
         
     | 
| 
      
 131 
     | 
    
         
            +
                rescue LoadError
         
     | 
| 
      
 132 
     | 
    
         
            +
                  fail Error, "Could not load integration #{name.inspect} (you may want to try installing the gem mutant-#{name})"
         
     | 
| 
       131 
133 
     | 
    
         
             
                end
         
     | 
| 
       132 
134 
     | 
    
         | 
| 
       133 
135 
     | 
    
         
             
                # Add options
         
     | 
    
        data/lib/mutant/config.rb
    CHANGED
    
    
    
        data/lib/mutant/env.rb
    CHANGED
    
    | 
         @@ -3,6 +3,10 @@ module Mutant 
     | 
|
| 
       3 
3 
     | 
    
         
             
              class Env
         
     | 
| 
       4 
4 
     | 
    
         
             
                include Adamantium::Flat, Concord::Public.new(:config, :cache)
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
      
 6 
     | 
    
         
            +
                SEMANTICS_MESSAGE =
         
     | 
| 
      
 7 
     | 
    
         
            +
                  "Fix your lib to follow normal ruby semantics!\n" \
         
     | 
| 
      
 8 
     | 
    
         
            +
                  '{Module,Class}#name should return resolvable constant name as String or nil'.freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       6 
10 
     | 
    
         
             
                # Return new env
         
     | 
| 
       7 
11 
     | 
    
         
             
                #
         
     | 
| 
       8 
12 
     | 
    
         
             
                # @param [Config] config
         
     | 
| 
         @@ -86,7 +90,7 @@ module Mutant 
     | 
|
| 
       86 
90 
     | 
    
         
             
                def scope_name(scope)
         
     | 
| 
       87 
91 
     | 
    
         
             
                  scope.name
         
     | 
| 
       88 
92 
     | 
    
         
             
                rescue => exception
         
     | 
| 
       89 
     | 
    
         
            -
                  warn("#{scope.class}#name from: #{scope.inspect} raised an error: #{exception.inspect}  
     | 
| 
      
 93 
     | 
    
         
            +
                  warn("#{scope.class}#name from: #{scope.inspect} raised an error: #{exception.inspect}. #{SEMANTICS_MESSAGE}")
         
     | 
| 
       90 
94 
     | 
    
         
             
                  nil
         
     | 
| 
       91 
95 
     | 
    
         
             
                end
         
     | 
| 
       92 
96 
     | 
    
         | 
| 
         @@ -106,7 +110,7 @@ module Mutant 
     | 
|
| 
       106 
110 
     | 
    
         
             
                  name = scope_name(scope) or return
         
     | 
| 
       107 
111 
     | 
    
         | 
| 
       108 
112 
     | 
    
         
             
                  unless name.is_a?(String)
         
     | 
| 
       109 
     | 
    
         
            -
                    warn("#{scope.class}#name from: #{scope.inspect} returned #{name.inspect} 
     | 
| 
      
 113 
     | 
    
         
            +
                    warn("#{scope.class}#name from: #{scope.inspect} returned #{name.inspect}. #{SEMANTICS_MESSAGE}")
         
     | 
| 
       110 
114 
     | 
    
         
             
                    return
         
     | 
| 
       111 
115 
     | 
    
         
             
                  end
         
     | 
| 
       112 
116 
     | 
    
         | 
    
        data/lib/mutant/integration.rb
    CHANGED
    
    | 
         @@ -16,7 +16,7 @@ module Mutant 
     | 
|
| 
       16 
16 
     | 
    
         
             
                # @api private
         
     | 
| 
       17 
17 
     | 
    
         
             
                #
         
     | 
| 
       18 
18 
     | 
    
         
             
                def self.lookup(name)
         
     | 
| 
       19 
     | 
    
         
            -
                  REGISTRY.fetch(name). 
     | 
| 
      
 19 
     | 
    
         
            +
                  REGISTRY.fetch(name).new
         
     | 
| 
       20 
20 
     | 
    
         
             
                end
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                # Register integration
         
     | 
| 
         @@ -44,6 +44,16 @@ module Mutant 
     | 
|
| 
       44 
44 
     | 
    
         
             
                  self
         
     | 
| 
       45 
45 
     | 
    
         
             
                end
         
     | 
| 
       46 
46 
     | 
    
         | 
| 
      
 47 
     | 
    
         
            +
                # Return test result for tests
         
     | 
| 
      
 48 
     | 
    
         
            +
                #
         
     | 
| 
      
 49 
     | 
    
         
            +
                # @param [Enumerable<Test>] tests
         
     | 
| 
      
 50 
     | 
    
         
            +
                #
         
     | 
| 
      
 51 
     | 
    
         
            +
                # @return [Result::Test]
         
     | 
| 
      
 52 
     | 
    
         
            +
                #
         
     | 
| 
      
 53 
     | 
    
         
            +
                # @api private
         
     | 
| 
      
 54 
     | 
    
         
            +
                #
         
     | 
| 
      
 55 
     | 
    
         
            +
                abstract_method :call
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
       47 
57 
     | 
    
         
             
                # Return all available tests by integration
         
     | 
| 
       48 
58 
     | 
    
         
             
                #
         
     | 
| 
       49 
59 
     | 
    
         
             
                # @return [Enumerable<Test>]
         
     | 
    
        data/lib/mutant/isolation.rb
    CHANGED
    
    
    
        data/lib/mutant/meta/example.rb
    CHANGED
    
    
    
        data/lib/mutant/mutation.rb
    CHANGED
    
    | 
         @@ -7,21 +7,30 @@ module Mutant 
     | 
|
| 
       7 
7 
     | 
    
         
             
                CODE_DELIMITER = "\0".freeze
         
     | 
| 
       8 
8 
     | 
    
         
             
                CODE_RANGE     = (0..4).freeze
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
                #  
     | 
| 
      
 10 
     | 
    
         
            +
                # Kill mutation under isolation with integration
         
     | 
| 
       11 
11 
     | 
    
         
             
                #
         
     | 
| 
       12 
     | 
    
         
            -
                #  
     | 
| 
       13 
     | 
    
         
            -
                # 
     | 
| 
       14 
     | 
    
         
            -
                #   is a detail of method mutations.
         
     | 
| 
      
 12 
     | 
    
         
            +
                # @param [Isolation] isolation
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @param [Integration] integration
         
     | 
| 
       15 
14 
     | 
    
         
             
                #
         
     | 
| 
       16 
     | 
    
         
            -
                # @return [ 
     | 
| 
      
 15 
     | 
    
         
            +
                # @return [Result::Test]
         
     | 
| 
       17 
16 
     | 
    
         
             
                #
         
     | 
| 
       18 
17 
     | 
    
         
             
                # @api private
         
     | 
| 
       19 
18 
     | 
    
         
             
                #
         
     | 
| 
       20 
     | 
    
         
            -
                def  
     | 
| 
       21 
     | 
    
         
            -
                   
     | 
| 
       22 
     | 
    
         
            -
                  subject. 
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                   
     | 
| 
      
 19 
     | 
    
         
            +
                def kill(isolation, integration)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  start = Time.now
         
     | 
| 
      
 21 
     | 
    
         
            +
                  tests = subject.tests
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  isolation.call do
         
     | 
| 
      
 24 
     | 
    
         
            +
                    insert
         
     | 
| 
      
 25 
     | 
    
         
            +
                    integration.call(tests)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end.update(tests: tests)
         
     | 
| 
      
 27 
     | 
    
         
            +
                rescue Isolation::Error => error
         
     | 
| 
      
 28 
     | 
    
         
            +
                  Result::Test.new(
         
     | 
| 
      
 29 
     | 
    
         
            +
                    tests:   tests,
         
     | 
| 
      
 30 
     | 
    
         
            +
                    output:  error.message,
         
     | 
| 
      
 31 
     | 
    
         
            +
                    runtime: Time.now - start,
         
     | 
| 
      
 32 
     | 
    
         
            +
                    passed:  false
         
     | 
| 
      
 33 
     | 
    
         
            +
                  )
         
     | 
| 
       25 
34 
     | 
    
         
             
                end
         
     | 
| 
       26 
35 
     | 
    
         | 
| 
       27 
36 
     | 
    
         
             
                # Return identification
         
     | 
| 
         @@ -67,20 +76,37 @@ module Mutant 
     | 
|
| 
       67 
76 
     | 
    
         
             
                  subject.source
         
     | 
| 
       68 
77 
     | 
    
         
             
                end
         
     | 
| 
       69 
78 
     | 
    
         | 
| 
       70 
     | 
    
         
            -
                # Test if mutation is killed by test  
     | 
| 
      
 79 
     | 
    
         
            +
                # Test if mutation is killed by test reports
         
     | 
| 
       71 
80 
     | 
    
         
             
                #
         
     | 
| 
       72 
     | 
    
         
            -
                # @param [Report::Test]  
     | 
| 
      
 81 
     | 
    
         
            +
                # @param [Array<Report::Test>] test_reports
         
     | 
| 
       73 
82 
     | 
    
         
             
                #
         
     | 
| 
       74 
83 
     | 
    
         
             
                # @return [Boolean]
         
     | 
| 
       75 
84 
     | 
    
         
             
                #
         
     | 
| 
       76 
85 
     | 
    
         
             
                # @api private
         
     | 
| 
       77 
86 
     | 
    
         
             
                #
         
     | 
| 
       78 
     | 
    
         
            -
                def  
     | 
| 
       79 
     | 
    
         
            -
                  self 
     | 
| 
      
 87 
     | 
    
         
            +
                def self.success?(test_result)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  self::TEST_PASS_SUCCESS.equal?(test_result.passed)
         
     | 
| 
       80 
89 
     | 
    
         
             
                end
         
     | 
| 
       81 
90 
     | 
    
         | 
| 
       82 
91 
     | 
    
         
             
              private
         
     | 
| 
       83 
92 
     | 
    
         | 
| 
      
 93 
     | 
    
         
            +
                # Insert mutated node
         
     | 
| 
      
 94 
     | 
    
         
            +
                #
         
     | 
| 
      
 95 
     | 
    
         
            +
                # FIXME: Cache subject visibility in a better way! Ideally dont mutate it
         
     | 
| 
      
 96 
     | 
    
         
            +
                #   implicitly. Also subject.public? should NOT be a public interface it
         
     | 
| 
      
 97 
     | 
    
         
            +
                #   is a detail of method mutations.
         
     | 
| 
      
 98 
     | 
    
         
            +
                #
         
     | 
| 
      
 99 
     | 
    
         
            +
                # @return [self]
         
     | 
| 
      
 100 
     | 
    
         
            +
                #
         
     | 
| 
      
 101 
     | 
    
         
            +
                # @api private
         
     | 
| 
      
 102 
     | 
    
         
            +
                #
         
     | 
| 
      
 103 
     | 
    
         
            +
                def insert
         
     | 
| 
      
 104 
     | 
    
         
            +
                  subject.public?
         
     | 
| 
      
 105 
     | 
    
         
            +
                  subject.prepare
         
     | 
| 
      
 106 
     | 
    
         
            +
                  Loader::Eval.call(root, subject)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  self
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
       84 
110 
     | 
    
         
             
                # Return sha1 sum of source and subject identification
         
     | 
| 
       85 
111 
     | 
    
         
             
                #
         
     | 
| 
       86 
112 
     | 
    
         
             
                # @return [String]
         
     | 
| 
         @@ -105,24 +131,24 @@ module Mutant 
     | 
|
| 
       105 
131 
     | 
    
         
             
                # Evil mutation that should case mutations to fail tests
         
     | 
| 
       106 
132 
     | 
    
         
             
                class Evil < self
         
     | 
| 
       107 
133 
     | 
    
         | 
| 
       108 
     | 
    
         
            -
                   
     | 
| 
       109 
     | 
    
         
            -
                   
     | 
| 
      
 134 
     | 
    
         
            +
                  SYMBOL            = 'evil'.freeze
         
     | 
| 
      
 135 
     | 
    
         
            +
                  TEST_PASS_SUCCESS = false
         
     | 
| 
       110 
136 
     | 
    
         | 
| 
       111 
137 
     | 
    
         
             
                end # Evil
         
     | 
| 
       112 
138 
     | 
    
         | 
| 
       113 
139 
     | 
    
         
             
                # Neutral mutation that should not cause mutations to fail tests
         
     | 
| 
       114 
140 
     | 
    
         
             
                class Neutral < self
         
     | 
| 
       115 
141 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
                  SYMBOL 
     | 
| 
       117 
     | 
    
         
            -
                   
     | 
| 
      
 142 
     | 
    
         
            +
                  SYMBOL            = 'neutral'.freeze
         
     | 
| 
      
 143 
     | 
    
         
            +
                  TEST_PASS_SUCCESS = true
         
     | 
| 
       118 
144 
     | 
    
         | 
| 
       119 
145 
     | 
    
         
             
                end # Neutral
         
     | 
| 
       120 
146 
     | 
    
         | 
| 
       121 
147 
     | 
    
         
             
                # Noop mutation, special case of neutral
         
     | 
| 
       122 
     | 
    
         
            -
                class Noop <  
     | 
| 
      
 148 
     | 
    
         
            +
                class Noop < Neutral
         
     | 
| 
       123 
149 
     | 
    
         | 
| 
       124 
     | 
    
         
            -
                  SYMBOL 
     | 
| 
       125 
     | 
    
         
            -
                   
     | 
| 
      
 150 
     | 
    
         
            +
                  SYMBOL            = 'noop'.freeze
         
     | 
| 
      
 151 
     | 
    
         
            +
                  TEST_PASS_SUCCESS = true
         
     | 
| 
       126 
152 
     | 
    
         | 
| 
       127 
153 
     | 
    
         
             
                end # Noop
         
     | 
| 
       128 
154 
     | 
    
         | 
    
        data/lib/mutant/mutator/node.rb
    CHANGED
    
    
| 
         @@ -17,7 +17,8 @@ module Mutant 
     | 
|
| 
       17 
17 
     | 
    
         
             
                      reverse_each:  [:each],
         
     | 
| 
       18 
18 
     | 
    
         
             
                      reverse_merge: [:merge],
         
     | 
| 
       19 
19 
     | 
    
         
             
                      map:           [:each],
         
     | 
| 
       20 
     | 
    
         
            -
                      send:          [:public_send],
         
     | 
| 
      
 20 
     | 
    
         
            +
                      send:          [:public_send, :__send__],
         
     | 
| 
      
 21 
     | 
    
         
            +
                      __send__:      [:public_send],
         
     | 
| 
       21 
22 
     | 
    
         
             
                      gsub:          [:sub],
         
     | 
| 
       22 
23 
     | 
    
         
             
                      eql?:          [:equal?],
         
     | 
| 
       23 
24 
     | 
    
         
             
                      to_s:          [:to_str],
         
     | 
| 
         @@ -26,8 +27,8 @@ module Mutant 
     | 
|
| 
       26 
27 
     | 
    
         
             
                      :== =>         [:eql?, :equal?],
         
     | 
| 
       27 
28 
     | 
    
         
             
                      :>= =>         [:>, :==, :eql?, :equal?],
         
     | 
| 
       28 
29 
     | 
    
         
             
                      :<= =>         [:<, :==, :eql?, :equal?],
         
     | 
| 
       29 
     | 
    
         
            -
                      :> =>          [:==, :eql?, :equal?],
         
     | 
| 
       30 
     | 
    
         
            -
                      :< =>          [:==, :eql?, :equal?]
         
     | 
| 
      
 30 
     | 
    
         
            +
                      :> =>          [:==, :>=, :eql?, :equal?],
         
     | 
| 
      
 31 
     | 
    
         
            +
                      :< =>          [:==, :<=, :eql?, :equal?]
         
     | 
| 
       31 
32 
     | 
    
         
             
                    )
         
     | 
| 
       32 
33 
     | 
    
         | 
| 
       33 
34 
     | 
    
         
             
                  private
         
     | 
    
        data/lib/mutant/reporter/cli.rb
    CHANGED
    
    
| 
         @@ -17,7 +17,7 @@ module Mutant 
     | 
|
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
                    # Return progress representation
         
     | 
| 
       19 
19 
     | 
    
         
             
                    #
         
     | 
| 
       20 
     | 
    
         
            -
                    # @param [Runner:: 
     | 
| 
      
 20 
     | 
    
         
            +
                    # @param [Runner::Status] status
         
     | 
| 
       21 
21 
     | 
    
         
             
                    #
         
     | 
| 
       22 
22 
     | 
    
         
             
                    # @return [String]
         
     | 
| 
       23 
23 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -67,6 +67,18 @@ module Mutant 
     | 
|
| 
       67 
67 
     | 
    
         
             
                    # Format for progressive non rewindable output
         
     | 
| 
       68 
68 
     | 
    
         
             
                    class Progressive < self
         
     | 
| 
       69 
69 
     | 
    
         | 
| 
      
 70 
     | 
    
         
            +
                      # Initialize object
         
     | 
| 
      
 71 
     | 
    
         
            +
                      #
         
     | 
| 
      
 72 
     | 
    
         
            +
                      # @return [undefined]
         
     | 
| 
      
 73 
     | 
    
         
            +
                      #
         
     | 
| 
      
 74 
     | 
    
         
            +
                      # @api private
         
     | 
| 
      
 75 
     | 
    
         
            +
                      #
         
     | 
| 
      
 76 
     | 
    
         
            +
                      def initialize(*)
         
     | 
| 
      
 77 
     | 
    
         
            +
                        @seen = Set.new
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                        super
         
     | 
| 
      
 80 
     | 
    
         
            +
                      end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
       70 
82 
     | 
    
         
             
                      # Return start representation
         
     | 
| 
       71 
83 
     | 
    
         
             
                      #
         
     | 
| 
       72 
84 
     | 
    
         
             
                      # @return [String]
         
     | 
| 
         @@ -83,10 +95,13 @@ module Mutant 
     | 
|
| 
       83 
95 
     | 
    
         
             
                      #
         
     | 
| 
       84 
96 
     | 
    
         
             
                      # @api private
         
     | 
| 
       85 
97 
     | 
    
         
             
                      #
         
     | 
| 
       86 
     | 
    
         
            -
                      def progress( 
     | 
| 
       87 
     | 
    
         
            -
                         
     | 
| 
       88 
     | 
    
         
            -
                         
     | 
| 
       89 
     | 
    
         
            -
                         
     | 
| 
      
 98 
     | 
    
         
            +
                      def progress(status)
         
     | 
| 
      
 99 
     | 
    
         
            +
                        current = status.env_result.subject_results.flat_map(&:mutation_results)
         
     | 
| 
      
 100 
     | 
    
         
            +
                        new = current.reject(&@seen.method(:include?))
         
     | 
| 
      
 101 
     | 
    
         
            +
                        @seen = current.to_set
         
     | 
| 
      
 102 
     | 
    
         
            +
                        new.map do |mutation_result|
         
     | 
| 
      
 103 
     | 
    
         
            +
                          format(Printer::MutationProgressResult, mutation_result)
         
     | 
| 
      
 104 
     | 
    
         
            +
                        end.join(EMPTY_STRING)
         
     | 
| 
       90 
105 
     | 
    
         
             
                      end
         
     | 
| 
       91 
106 
     | 
    
         | 
| 
       92 
107 
     | 
    
         
             
                    private
         
     | 
| 
         @@ -109,20 +124,6 @@ module Mutant 
     | 
|
| 
       109 
124 
     | 
    
         | 
| 
       110 
125 
     | 
    
         
             
                      BUFFER_FLAGS = 'a+'.freeze
         
     | 
| 
       111 
126 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                      # Rate per second progress report fires
         
     | 
| 
       113 
     | 
    
         
            -
                      OUTPUT_RATE = 1.0 / 20
         
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                      # Initialize object
         
     | 
| 
       116 
     | 
    
         
            -
                      #
         
     | 
| 
       117 
     | 
    
         
            -
                      # @return [undefined]
         
     | 
| 
       118 
     | 
    
         
            -
                      #
         
     | 
| 
       119 
     | 
    
         
            -
                      # @api private
         
     | 
| 
       120 
     | 
    
         
            -
                      #
         
     | 
| 
       121 
     | 
    
         
            -
                      def initialize(*)
         
     | 
| 
       122 
     | 
    
         
            -
                        super
         
     | 
| 
       123 
     | 
    
         
            -
                        @last_frame = nil
         
     | 
| 
       124 
     | 
    
         
            -
                      end
         
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
127 
     | 
    
         
             
                      # Format start
         
     | 
| 
       127 
128 
     | 
    
         
             
                      #
         
     | 
| 
       128 
129 
     | 
    
         
             
                      # @param [Env] env
         
     | 
| 
         @@ -137,16 +138,14 @@ module Mutant 
     | 
|
| 
       137 
138 
     | 
    
         | 
| 
       138 
139 
     | 
    
         
             
                      # Format progress
         
     | 
| 
       139 
140 
     | 
    
         
             
                      #
         
     | 
| 
       140 
     | 
    
         
            -
                      # @param [Runner:: 
     | 
| 
      
 141 
     | 
    
         
            +
                      # @param [Runner::Status] status
         
     | 
| 
       141 
142 
     | 
    
         
             
                      #
         
     | 
| 
       142 
143 
     | 
    
         
             
                      # @return [String]
         
     | 
| 
       143 
144 
     | 
    
         
             
                      #
         
     | 
| 
       144 
145 
     | 
    
         
             
                      # @api private
         
     | 
| 
       145 
146 
     | 
    
         
             
                      #
         
     | 
| 
       146 
     | 
    
         
            -
                      def progress( 
     | 
| 
       147 
     | 
    
         
            -
                         
     | 
| 
       148 
     | 
    
         
            -
                          format(Printer::Collector, collector)
         
     | 
| 
       149 
     | 
    
         
            -
                        end.to_s
         
     | 
| 
      
 147 
     | 
    
         
            +
                      def progress(status)
         
     | 
| 
      
 148 
     | 
    
         
            +
                        format(Printer::Status, status)
         
     | 
| 
       150 
149 
     | 
    
         
             
                      end
         
     | 
| 
       151 
150 
     | 
    
         | 
| 
       152 
151 
     | 
    
         
             
                    private
         
     | 
| 
         @@ -166,18 +165,6 @@ module Mutant 
     | 
|
| 
       166 
165 
     | 
    
         
             
                        buffer << tput.restore
         
     | 
| 
       167 
166 
     | 
    
         
             
                      end
         
     | 
| 
       168 
167 
     | 
    
         | 
| 
       169 
     | 
    
         
            -
                      # Call block throttled
         
     | 
| 
       170 
     | 
    
         
            -
                      #
         
     | 
| 
       171 
     | 
    
         
            -
                      # @return [self]
         
     | 
| 
       172 
     | 
    
         
            -
                      #
         
     | 
| 
       173 
     | 
    
         
            -
                      # @api private
         
     | 
| 
       174 
     | 
    
         
            -
                      #
         
     | 
| 
       175 
     | 
    
         
            -
                      def throttle
         
     | 
| 
       176 
     | 
    
         
            -
                        now = Time.now
         
     | 
| 
       177 
     | 
    
         
            -
                        return if @last_frame && (now - @last_frame) < OUTPUT_RATE
         
     | 
| 
       178 
     | 
    
         
            -
                        yield.tap { @last_frame = now }
         
     | 
| 
       179 
     | 
    
         
            -
                      end
         
     | 
| 
       180 
     | 
    
         
            -
             
     | 
| 
       181 
168 
     | 
    
         
             
                    end # Framed
         
     | 
| 
       182 
169 
     | 
    
         
             
                  end # Format
         
     | 
| 
       183 
170 
     | 
    
         
             
                end # CLI
         
     | 
| 
         @@ -5,6 +5,8 @@ module Mutant 
     | 
|
| 
       5 
5 
     | 
    
         
             
                  class Printer
         
     | 
| 
       6 
6 
     | 
    
         
             
                    include AbstractType, Delegator, Adamantium::Flat, Concord.new(:output, :object)
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
      
 8 
     | 
    
         
            +
                    delegate(:success?)
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       8 
10 
     | 
    
         
             
                    NL = "\n".freeze
         
     | 
| 
       9 
11 
     | 
    
         | 
| 
       10 
12 
     | 
    
         
             
                    # Run printer on object to output
         
     | 
| 
         @@ -98,16 +100,6 @@ module Mutant 
     | 
|
| 
       98 
100 
     | 
    
         
             
                      output.puts(string)
         
     | 
| 
       99 
101 
     | 
    
         
             
                    end
         
     | 
| 
       100 
102 
     | 
    
         | 
| 
       101 
     | 
    
         
            -
                    # Test if runner was successful
         
     | 
| 
       102 
     | 
    
         
            -
                    #
         
     | 
| 
       103 
     | 
    
         
            -
                    # @return [Boolean]
         
     | 
| 
       104 
     | 
    
         
            -
                    #
         
     | 
| 
       105 
     | 
    
         
            -
                    # @api private
         
     | 
| 
       106 
     | 
    
         
            -
                    #
         
     | 
| 
       107 
     | 
    
         
            -
                    def success?
         
     | 
| 
       108 
     | 
    
         
            -
                      object.success?
         
     | 
| 
       109 
     | 
    
         
            -
                    end
         
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
103 
     | 
    
         
             
                    # Colorize message
         
     | 
| 
       112 
104 
     | 
    
         
             
                    #
         
     | 
| 
       113 
105 
     | 
    
         
             
                    # @param [Color] color
         
     | 
| 
         @@ -142,8 +134,10 @@ module Mutant 
     | 
|
| 
       142 
134 
     | 
    
         
             
                    #
         
     | 
| 
       143 
135 
     | 
    
         
             
                    alias_method :color?, :tty?
         
     | 
| 
       144 
136 
     | 
    
         | 
| 
       145 
     | 
    
         
            -
                    # Printer for  
     | 
| 
       146 
     | 
    
         
            -
                    class  
     | 
| 
      
 137 
     | 
    
         
            +
                    # Printer for runner status
         
     | 
| 
      
 138 
     | 
    
         
            +
                    class Status < self
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                      delegate(:active_jobs, :env_result)
         
     | 
| 
       147 
141 
     | 
    
         | 
| 
       148 
142 
     | 
    
         
             
                      # Print progress for collector
         
     | 
| 
       149 
143 
     | 
    
         
             
                      #
         
     | 
| 
         @@ -152,14 +146,44 @@ module Mutant 
     | 
|
| 
       152 
146 
     | 
    
         
             
                      # @api private
         
     | 
| 
       153 
147 
     | 
    
         
             
                      #
         
     | 
| 
       154 
148 
     | 
    
         
             
                      def run
         
     | 
| 
       155 
     | 
    
         
            -
                        visit(EnvProgress, object. 
     | 
| 
       156 
     | 
    
         
            -
                        active_subject_results = object.active_subject_results
         
     | 
| 
      
 149 
     | 
    
         
            +
                        visit(EnvProgress, object.env_result)
         
     | 
| 
       157 
150 
     | 
    
         
             
                        info('Active subjects:    %d', active_subject_results.length)
         
     | 
| 
       158 
151 
     | 
    
         
             
                        visit_collection(SubjectProgress, active_subject_results)
         
     | 
| 
      
 152 
     | 
    
         
            +
                        job_status
         
     | 
| 
       159 
153 
     | 
    
         
             
                        self
         
     | 
| 
       160 
154 
     | 
    
         
             
                      end
         
     | 
| 
       161 
155 
     | 
    
         | 
| 
       162 
     | 
    
         
            -
                     
     | 
| 
      
 156 
     | 
    
         
            +
                    private
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                      # Print worker status
         
     | 
| 
      
 159 
     | 
    
         
            +
                      #
         
     | 
| 
      
 160 
     | 
    
         
            +
                      # @return [undefined]
         
     | 
| 
      
 161 
     | 
    
         
            +
                      #
         
     | 
| 
      
 162 
     | 
    
         
            +
                      # @api private
         
     | 
| 
      
 163 
     | 
    
         
            +
                      #
         
     | 
| 
      
 164 
     | 
    
         
            +
                      def job_status
         
     | 
| 
      
 165 
     | 
    
         
            +
                        return if active_jobs.empty?
         
     | 
| 
      
 166 
     | 
    
         
            +
                        info('Active Jobs:')
         
     | 
| 
      
 167 
     | 
    
         
            +
                        object.active_jobs.sort_by(&:index).each do |job|
         
     | 
| 
      
 168 
     | 
    
         
            +
                          info('%d: %s', job.index, job.mutation.identification)
         
     | 
| 
      
 169 
     | 
    
         
            +
                        end
         
     | 
| 
      
 170 
     | 
    
         
            +
                      end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                      # Return active subject results
         
     | 
| 
      
 173 
     | 
    
         
            +
                      #
         
     | 
| 
      
 174 
     | 
    
         
            +
                      # @return [Array<Result::Subject>]
         
     | 
| 
      
 175 
     | 
    
         
            +
                      #
         
     | 
| 
      
 176 
     | 
    
         
            +
                      # @api private
         
     | 
| 
      
 177 
     | 
    
         
            +
                      #
         
     | 
| 
      
 178 
     | 
    
         
            +
                      def active_subject_results
         
     | 
| 
      
 179 
     | 
    
         
            +
                        active_subjects = active_jobs.map(&:mutation).flat_map(&:subject).to_set
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                        env_result.subject_results.select do |subject_result|
         
     | 
| 
      
 182 
     | 
    
         
            +
                          active_subjects.include?(subject_result.subject)
         
     | 
| 
      
 183 
     | 
    
         
            +
                        end
         
     | 
| 
      
 184 
     | 
    
         
            +
                      end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                    end # Status
         
     | 
| 
       163 
187 
     | 
    
         | 
| 
       164 
188 
     | 
    
         
             
                    # Progress printer for configuration
         
     | 
| 
       165 
189 
     | 
    
         
             
                    class Config < self
         
     | 
| 
         @@ -406,9 +430,9 @@ module Mutant 
     | 
|
| 
       406 
430 
     | 
    
         
             
                    # Reporter for mutation results
         
     | 
| 
       407 
431 
     | 
    
         
             
                    class MutationResult < self
         
     | 
| 
       408 
432 
     | 
    
         | 
| 
       409 
     | 
    
         
            -
                      delegate :mutation, : 
     | 
| 
      
 433 
     | 
    
         
            +
                      delegate :mutation, :test_result
         
     | 
| 
       410 
434 
     | 
    
         | 
| 
       411 
     | 
    
         
            -
                      DIFF_ERROR_MESSAGE = 'BUG: Mutation NOT resulted in exactly one diff. Please report a reproduction!'.freeze
         
     | 
| 
      
 435 
     | 
    
         
            +
                      DIFF_ERROR_MESSAGE = 'BUG: Mutation NOT resulted in exactly one diff hunk. Please report a reproduction!'.freeze
         
     | 
| 
       412 
436 
     | 
    
         | 
| 
       413 
437 
     | 
    
         
             
                      MAP = {
         
     | 
| 
       414 
438 
     | 
    
         
             
                        Mutant::Mutation::Evil    => :evil_details,
         
     | 
| 
         @@ -424,13 +448,13 @@ module Mutant 
     | 
|
| 
       424 
448 
     | 
    
         
             
                        "%s\n" \
         
     | 
| 
       425 
449 
     | 
    
         
             
                        "Unparsed Source:\n" \
         
     | 
| 
       426 
450 
     | 
    
         
             
                        "%s\n" \
         
     | 
| 
       427 
     | 
    
         
            -
                        "Test  
     | 
| 
      
 451 
     | 
    
         
            +
                        "Test Result:\n".freeze
         
     | 
| 
       428 
452 
     | 
    
         | 
| 
       429 
453 
     | 
    
         
             
                      NOOP_MESSAGE    =
         
     | 
| 
       430 
454 
     | 
    
         
             
                        "---- Noop failure -----\n" \
         
     | 
| 
       431 
455 
     | 
    
         
             
                        "No code was inserted. And the test did NOT PASS.\n" \
         
     | 
| 
       432 
456 
     | 
    
         
             
                        "This is typically a problem of your specs not passing unmutated.\n" \
         
     | 
| 
       433 
     | 
    
         
            -
                        "Test  
     | 
| 
      
 457 
     | 
    
         
            +
                        "Test Result:\n".freeze
         
     | 
| 
       434 
458 
     | 
    
         | 
| 
       435 
459 
     | 
    
         
             
                      FOOTER = '-----------------------'.freeze
         
     | 
| 
       436 
460 
     | 
    
         | 
| 
         @@ -479,8 +503,8 @@ module Mutant 
     | 
|
| 
       479 
503 
     | 
    
         
             
                      # @api private
         
     | 
| 
       480 
504 
     | 
    
         
             
                      #
         
     | 
| 
       481 
505 
     | 
    
         
             
                      def noop_details
         
     | 
| 
       482 
     | 
    
         
            -
                        info(NOOP_MESSAGE 
     | 
| 
       483 
     | 
    
         
            -
                         
     | 
| 
      
 506 
     | 
    
         
            +
                        info(NOOP_MESSAGE)
         
     | 
| 
      
 507 
     | 
    
         
            +
                        visit_test_result
         
     | 
| 
       484 
508 
     | 
    
         
             
                      end
         
     | 
| 
       485 
509 
     | 
    
         | 
| 
       486 
510 
     | 
    
         
             
                      # Neutral details
         
     | 
| 
         @@ -490,8 +514,8 @@ module Mutant 
     | 
|
| 
       490 
514 
     | 
    
         
             
                      # @api private
         
     | 
| 
       491 
515 
     | 
    
         
             
                      #
         
     | 
| 
       492 
516 
     | 
    
         
             
                      def neutral_details
         
     | 
| 
       493 
     | 
    
         
            -
                        info(NEUTRAL_MESSAGE, mutation.subject.node.inspect, mutation.source 
     | 
| 
       494 
     | 
    
         
            -
                         
     | 
| 
      
 517 
     | 
    
         
            +
                        info(NEUTRAL_MESSAGE, mutation.subject.node.inspect, mutation.source)
         
     | 
| 
      
 518 
     | 
    
         
            +
                        visit_test_result
         
     | 
| 
       495 
519 
     | 
    
         
             
                      end
         
     | 
| 
       496 
520 
     | 
    
         | 
| 
       497 
521 
     | 
    
         
             
                      # Visit failed test results
         
     | 
| 
         @@ -500,8 +524,8 @@ module Mutant 
     | 
|
| 
       500 
524 
     | 
    
         
             
                      #
         
     | 
| 
       501 
525 
     | 
    
         
             
                      # @api private
         
     | 
| 
       502 
526 
     | 
    
         
             
                      #
         
     | 
| 
       503 
     | 
    
         
            -
                      def  
     | 
| 
       504 
     | 
    
         
            -
                         
     | 
| 
      
 527 
     | 
    
         
            +
                      def visit_test_result
         
     | 
| 
      
 528 
     | 
    
         
            +
                        visit(TestResult, test_result)
         
     | 
| 
       505 
529 
     | 
    
         
             
                      end
         
     | 
| 
       506 
530 
     | 
    
         | 
| 
       507 
531 
     | 
    
         
             
                    end # MutationResult
         
     | 
| 
         @@ -509,7 +533,7 @@ module Mutant 
     | 
|
| 
       509 
533 
     | 
    
         
             
                    # Test result reporter
         
     | 
| 
       510 
534 
     | 
    
         
             
                    class TestResult < self
         
     | 
| 
       511 
535 
     | 
    
         | 
| 
       512 
     | 
    
         
            -
                      delegate : 
     | 
| 
      
 536 
     | 
    
         
            +
                      delegate :tests, :runtime
         
     | 
| 
       513 
537 
     | 
    
         | 
| 
       514 
538 
     | 
    
         
             
                      # Run test result reporter
         
     | 
| 
       515 
539 
     | 
    
         
             
                      #
         
     | 
| 
         @@ -518,11 +542,26 @@ module Mutant 
     | 
|
| 
       518 
542 
     | 
    
         
             
                      # @api private
         
     | 
| 
       519 
543 
     | 
    
         
             
                      #
         
     | 
| 
       520 
544 
     | 
    
         
             
                      def run
         
     | 
| 
       521 
     | 
    
         
            -
                        status('- % 
     | 
| 
      
 545 
     | 
    
         
            +
                        status('- %d @ runtime: %s', tests.length, runtime)
         
     | 
| 
      
 546 
     | 
    
         
            +
                        tests.each do |test|
         
     | 
| 
      
 547 
     | 
    
         
            +
                          puts("  - #{test.identification}")
         
     | 
| 
      
 548 
     | 
    
         
            +
                        end
         
     | 
| 
       522 
549 
     | 
    
         
             
                        puts('Test Output:')
         
     | 
| 
       523 
550 
     | 
    
         
             
                        puts(object.output)
         
     | 
| 
       524 
551 
     | 
    
         
             
                      end
         
     | 
| 
       525 
552 
     | 
    
         | 
| 
      
 553 
     | 
    
         
            +
                      # Test if test result is successful
         
     | 
| 
      
 554 
     | 
    
         
            +
                      #
         
     | 
| 
      
 555 
     | 
    
         
            +
                      # Only used to determine color.
         
     | 
| 
      
 556 
     | 
    
         
            +
                      #
         
     | 
| 
      
 557 
     | 
    
         
            +
                      # @return [false]
         
     | 
| 
      
 558 
     | 
    
         
            +
                      #
         
     | 
| 
      
 559 
     | 
    
         
            +
                      # @api private
         
     | 
| 
      
 560 
     | 
    
         
            +
                      #
         
     | 
| 
      
 561 
     | 
    
         
            +
                      def success?
         
     | 
| 
      
 562 
     | 
    
         
            +
                        false
         
     | 
| 
      
 563 
     | 
    
         
            +
                      end
         
     | 
| 
      
 564 
     | 
    
         
            +
             
     | 
| 
       526 
565 
     | 
    
         
             
                    end # TestResult
         
     | 
| 
       527 
566 
     | 
    
         
             
                  end # Printer
         
     | 
| 
       528 
567 
     | 
    
         
             
                end # CLI
         
     |