mutant 0.8.1 → 0.8.2
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 +12 -0
- data/README.md +73 -0
- data/Rakefile +14 -9
- data/config/flay.yml +1 -1
- data/config/reek.yml +13 -12
- data/lib/mutant/isolation.rb +2 -1
- data/lib/mutant/matcher/method.rb +3 -2
- data/lib/mutant/mutator/node/binary.rb +28 -8
- data/lib/mutant/mutator/node/defined.rb +4 -3
- data/lib/mutant/mutator/node/send.rb +1 -0
- data/lib/mutant/mutator/node/zsuper.rb +1 -0
- data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -12
- data/lib/mutant/repository.rb +13 -1
- data/lib/mutant/subject.rb +1 -1
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/zombifier.rb +1 -1
- data/meta/and.rb +0 -1
- data/meta/defined.rb +2 -0
- data/meta/or.rb +0 -1
- data/meta/send.rb +9 -0
- data/meta/super.rb +1 -0
- data/spec/shared/method_matcher_behavior.rb +4 -0
- data/spec/support/corpus.rb +2 -1
- data/spec/unit/mutant/isolation_spec.rb +3 -1
- data/spec/unit/mutant/matcher/method/instance_spec.rb +15 -10
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +13 -8
- data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +0 -2
- data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +0 -3
- data/spec/unit/mutant/repository/diff_spec.rb +28 -14
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f16485d23238c84b07b2e62df8a1c4af57badb14
         | 
| 4 | 
            +
              data.tar.gz: e0b9ddb90dccee908622683295235e177d4d7dcf
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 992b3447fda4a045e9462f292f17da506141b386e9c494d94c13a6807450f9b73826f230e468a883f1177df70db409de9b400d107183d053444061c96ba7193f
         | 
| 7 | 
            +
              data.tar.gz: 3c8319ee768ca67e2a0cd9fbf65c5a3652425f73ecc8206bdca143da85f6a16fbf875505f5f14f9038319b5e35615e6a4e8ec0bf5ad2620cca4ed1d8c6e57f0c
         | 
    
        data/Changelog.md
    CHANGED
    
    | @@ -1,3 +1,15 @@ | |
| 1 | 
            +
            # v0.8.2 2015-08-11
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Remove invalid mutation `foo or bar` to `!(foo or bar)` see #287
         | 
| 4 | 
            +
            * Add mutation from `#to_h` to `#to_hash` #218
         | 
| 5 | 
            +
            <<<<<<< 2914e9c8d906540edc1cc7d4bc6393f68db39b8d
         | 
| 6 | 
            +
            * Add mutation from `#defined?` to `true` / `false` #334
         | 
| 7 | 
            +
            * Add mutation from `super` to `super()` #309
         | 
| 8 | 
            +
            =======
         | 
| 9 | 
            +
            * Add mutation from `#defined?` to `true` / `false` #399
         | 
| 10 | 
            +
            * Reduce framed (multiline) progress reporter noise
         | 
| 11 | 
            +
            >>>>>>> Reduce framed progress reporter noise
         | 
| 12 | 
            +
             | 
| 1 13 | 
             
            # v0.8.1 2015-07-24
         | 
| 2 14 |  | 
| 3 15 | 
             
            * Add --since flag to constrain mutated subjects based on
         | 
    
        data/README.md
    CHANGED
    
    | @@ -118,6 +118,79 @@ Example for a subject like `Foo::Bar#baz` it will run all example groups with de | |
| 118 118 | 
             
            `Foo::Bar#baz`, `Foo::Bar` and `Foo`. The order is important, so if mutant finds example groups in the
         | 
| 119 119 | 
             
            current prefix level, these example groups *must* kill the mutation.
         | 
| 120 120 |  | 
| 121 | 
            +
            Reading Reports
         | 
| 122 | 
            +
            ---------------
         | 
| 123 | 
            +
             | 
| 124 | 
            +
            Mutation output is grouped by selection groups. Each group contains three sections:
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            1. An identifier for the current group.
         | 
| 127 | 
            +
             | 
| 128 | 
            +
               **Format**:
         | 
| 129 | 
            +
             | 
| 130 | 
            +
               ```text
         | 
| 131 | 
            +
               [SUBJECT EXPRESSION]:[SOURCE LOCATION]:[LINENO]
         | 
| 132 | 
            +
               ```
         | 
| 133 | 
            +
             | 
| 134 | 
            +
               **Example**:
         | 
| 135 | 
            +
             | 
| 136 | 
            +
               ```text
         | 
| 137 | 
            +
               Book#add_page:Book#add_page:/home/dev/mutant-examples/lib/book.rb:18
         | 
| 138 | 
            +
               ```
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            2. A list of specs that mutant ran to try to kill mutations for the current group.
         | 
| 141 | 
            +
             | 
| 142 | 
            +
               **Format**:
         | 
| 143 | 
            +
             | 
| 144 | 
            +
               ```text
         | 
| 145 | 
            +
               - [INTEGRATION]:0:[SPEC LOCATION]:[SPEC DESCRIPTION]
         | 
| 146 | 
            +
               - [INTEGRATION]:1:[SPEC LOCATION]:[SPEC DESCRIPTION]
         | 
| 147 | 
            +
               ```
         | 
| 148 | 
            +
             | 
| 149 | 
            +
               **Example**:
         | 
| 150 | 
            +
             | 
| 151 | 
            +
               ```text
         | 
| 152 | 
            +
               - rspec:0:./spec/unit/book_spec.rb:9/Book#add_page should return self
         | 
| 153 | 
            +
               - rspec:1:./spec/unit/book_spec.rb:13/Book#add_page should add page to book
         | 
| 154 | 
            +
               ```
         | 
| 155 | 
            +
             | 
| 156 | 
            +
            3. A list of unkilled mutations diffed against the original unparsed source
         | 
| 157 | 
            +
             | 
| 158 | 
            +
               **Format**:
         | 
| 159 | 
            +
             | 
| 160 | 
            +
               ```text
         | 
| 161 | 
            +
               [MUTATION TYPE]:[SUBJECT EXPRESSION]:[SOURCE LOCATION]:[SOURCE LINENO]:[IDENTIFIER]
         | 
| 162 | 
            +
               [DIFF]
         | 
| 163 | 
            +
               -----------------------
         | 
| 164 | 
            +
               ```
         | 
| 165 | 
            +
             | 
| 166 | 
            +
               - `[MUTATION TYPE]` will be one of the following:
         | 
| 167 | 
            +
                  - `evil` - a mutation of your source was not killed by your tests
         | 
| 168 | 
            +
                  - `neutral` your original source was injected and one or more tests failed
         | 
| 169 | 
            +
               - `[IDENTIFIER]` - Unique identifier for this mutation
         | 
| 170 | 
            +
             | 
| 171 | 
            +
               **Example**:
         | 
| 172 | 
            +
             | 
| 173 | 
            +
               ```diff
         | 
| 174 | 
            +
               evil:Book#add_page:Book#add_page:/home/dev/mutant-examples/lib/book.rb:18:01f69
         | 
| 175 | 
            +
               @@ -1,6 +1,6 @@
         | 
| 176 | 
            +
                def add_page(page)
         | 
| 177 | 
            +
               -  @pages << page
         | 
| 178 | 
            +
               +  @pages
         | 
| 179 | 
            +
                  @index[page.number] = page
         | 
| 180 | 
            +
                  self
         | 
| 181 | 
            +
                end
         | 
| 182 | 
            +
               -----------------------
         | 
| 183 | 
            +
               evil:Book#add_page:Book#add_page:/home/dev/mutant-examples/lib/book.rb:18:b1ff2
         | 
| 184 | 
            +
               @@ -1,6 +1,6 @@
         | 
| 185 | 
            +
                def add_page(page)
         | 
| 186 | 
            +
               -  @pages << page
         | 
| 187 | 
            +
               +  self
         | 
| 188 | 
            +
                  @index[page.number] = page
         | 
| 189 | 
            +
                  self
         | 
| 190 | 
            +
                end
         | 
| 191 | 
            +
               -----------------------
         | 
| 192 | 
            +
               ```
         | 
| 193 | 
            +
             | 
| 121 194 | 
             
            Rails
         | 
| 122 195 | 
             
            -------
         | 
| 123 196 |  | 
    
        data/Rakefile
    CHANGED
    
    | @@ -4,16 +4,21 @@ require 'devtools' | |
| 4 4 |  | 
| 5 5 | 
             
            Devtools.init_rake_tasks
         | 
| 6 6 |  | 
| 7 | 
            -
             | 
| 8 | 
            -
            # See: https://github.com/mbj/mutant/issues/265
         | 
| 9 | 
            -
            if ENV['CI']
         | 
| 10 | 
            -
              Rake.application.load_imports
         | 
| 7 | 
            +
            Rake.application.load_imports
         | 
| 11 8 |  | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 9 | 
            +
            task('metrics:mutant').clear
         | 
| 10 | 
            +
            namespace :metrics do
         | 
| 11 | 
            +
              task :mutant => :coverage do
         | 
| 12 | 
            +
                success = Kernel.system(*%w[
         | 
| 13 | 
            +
                  bundle exec mutant
         | 
| 14 | 
            +
                  --zombie
         | 
| 15 | 
            +
                  --use rspec
         | 
| 16 | 
            +
                  --include lib
         | 
| 17 | 
            +
                  --require mutant
         | 
| 18 | 
            +
                  --since HEAD~1
         | 
| 19 | 
            +
                  --
         | 
| 20 | 
            +
                  Mutant*
         | 
| 21 | 
            +
                ]) or fail 'Mutant task is not successful'
         | 
| 17 22 | 
             
              end
         | 
| 18 23 | 
             
            end
         | 
| 19 24 |  | 
    
        data/config/flay.yml
    CHANGED
    
    
    
        data/config/reek.yml
    CHANGED
    
    | @@ -43,12 +43,12 @@ NestedIterators: | |
| 43 43 | 
             
              - Mutant#self.singleton_subclass_instance
         | 
| 44 44 | 
             
              - Mutant::CLI#parse
         | 
| 45 45 | 
             
              - Mutant::Isolation::Fork#self.call
         | 
| 46 | 
            -
              - Mutant::Mutator::Util::Array::Element#dispatch
         | 
| 47 | 
            -
              - Mutant::Mutator::Node::Resbody#mutate_captures
         | 
| 48 46 | 
             
              - Mutant::Mutator::Node::Arguments#emit_argument_mutations
         | 
| 47 | 
            +
              - Mutant::Mutator::Node::Resbody#mutate_captures
         | 
| 48 | 
            +
              - Mutant::Mutator::Util::Array::Element#dispatch
         | 
| 49 | 
            +
              - Mutant::Parallel::Master#run
         | 
| 49 50 | 
             
              - Mutant::RequireHighjack#self.call
         | 
| 50 51 | 
             
              - Mutant::Selector::Expression#call
         | 
| 51 | 
            -
              - Mutant::Parallel::Master#run
         | 
| 52 52 | 
             
              - Parser::Lexer#self.new
         | 
| 53 53 | 
             
              max_allowed_nesting: 1
         | 
| 54 54 | 
             
              ignore_iterators: []
         | 
| @@ -70,26 +70,26 @@ TooManyMethods: | |
| 70 70 | 
             
              enabled: true
         | 
| 71 71 | 
             
              exclude:
         | 
| 72 72 | 
             
              - Mutant::CLI
         | 
| 73 | 
            -
              - Mutant::Mutator::Node
         | 
| 74 73 | 
             
              - Mutant::Meta::Example::Verification
         | 
| 74 | 
            +
              - Mutant::Mutator::Node
         | 
| 75 75 | 
             
              - Mutant::Parallel::Master
         | 
| 76 76 | 
             
              max_methods: 10
         | 
| 77 77 | 
             
            TooManyStatements:
         | 
| 78 78 | 
             
              enabled: true
         | 
| 79 79 | 
             
              exclude:
         | 
| 80 | 
            +
              - Mutant::CLI#add_debug_options
         | 
| 81 | 
            +
              - Mutant::CLI#add_environment_options
         | 
| 80 82 | 
             
              - Mutant::Isolation::Fork#self.call
         | 
| 81 | 
            -
              - Mutant::Reporter::CLI::Printer::EnvProgress#run
         | 
| 82 83 | 
             
              - Mutant::Reporter::CLI::Printer::Config#run
         | 
| 83 | 
            -
              - Mutant:: | 
| 84 | 
            -
              - Mutant::CLI#add_environment_options
         | 
| 85 | 
            -
              - Mutant::CLI#add_debug_options
         | 
| 84 | 
            +
              - Mutant::Reporter::CLI::Printer::EnvProgress#run
         | 
| 86 85 | 
             
              - Mutant::Runner#run_driver
         | 
| 86 | 
            +
              - Mutant::Zombifier::File#self.find
         | 
| 87 87 | 
             
              max_statements: 7
         | 
| 88 88 | 
             
            UncommunicativeMethodName:
         | 
| 89 89 | 
             
              enabled: true
         | 
| 90 90 | 
             
              exclude:
         | 
| 91 | 
            -
              - Mutant::Mutation#sha1
         | 
| 92 91 | 
             
              - Mutant::AST::Sexp#s
         | 
| 92 | 
            +
              - Mutant::Mutation#sha1
         | 
| 93 93 | 
             
              reject:
         | 
| 94 94 | 
             
              - !ruby/regexp /^[a-z]$/
         | 
| 95 95 | 
             
              - !ruby/regexp /[0-9]$/
         | 
| @@ -124,14 +124,15 @@ UnusedParameters: | |
| 124 124 | 
             
            UtilityFunction:
         | 
| 125 125 | 
             
              enabled: true
         | 
| 126 126 | 
             
              exclude:
         | 
| 127 | 
            -
              - Mutant::Actor::Env#new_mailbox
         | 
| 128 127 | 
             
              - Mutant::AST::Sexp#s
         | 
| 128 | 
            +
              - Mutant::Actor::Env#new_mailbox
         | 
| 129 129 | 
             
              - Mutant::CLI#reporter
         | 
| 130 130 | 
             
              - Mutant::Integration::Null#call
         | 
| 131 131 | 
             
              - Mutant::Integration::Rspec#parse_example
         | 
| 132 | 
            +
              - Mutant::Integration::Rspec#parse_expression # intentional, private
         | 
| 132 133 | 
             
              - Mutant::Meta::Example::Verification#format_mutation
         | 
| 133 | 
            -
              - Mutant::Repository::Diff#tracks? # intentional, private
         | 
| 134 134 | 
             
              - Mutant::Reporter::CLI::Format::Progressive#new_buffer
         | 
| 135 135 | 
             
              - Mutant::Reporter::CLI::Printer::StatusProgressive#object # False positive calls super
         | 
| 136 | 
            -
              - Mutant:: | 
| 136 | 
            +
              - Mutant::Repository::Diff#tracks? # intentional, private
         | 
| 137 | 
            +
              - Mutant::Repository::Diff#within_working_directory? # intentional, private
         | 
| 137 138 | 
             
              max_helper_calls: 0
         | 
    
        data/lib/mutant/isolation.rb
    CHANGED
    
    | @@ -39,9 +39,10 @@ module Mutant | |
| 39 39 | 
             
                  # @api private
         | 
| 40 40 | 
             
                  def self.call(&block)
         | 
| 41 41 | 
             
                    IO.pipe(binmode: true) do |reader, writer|
         | 
| 42 | 
            +
                      writer.binmode
         | 
| 42 43 | 
             
                      begin
         | 
| 43 44 | 
             
                        pid = Process.fork do
         | 
| 44 | 
            -
                          File.open(File::NULL,  | 
| 45 | 
            +
                          File.open(File::NULL, File::WRONLY) do |file|
         | 
| 45 46 | 
             
                            $stderr.reopen(file)
         | 
| 46 47 | 
             
                            reader.close
         | 
| 47 48 | 
             
                            writer.write(Marshal.dump(block.call))
         | 
| @@ -77,12 +77,13 @@ module Mutant | |
| 77 77 |  | 
| 78 78 | 
             
                  # Path to source
         | 
| 79 79 | 
             
                  #
         | 
| 80 | 
            -
                  # @return [ | 
| 80 | 
            +
                  # @return [Pathname]
         | 
| 81 81 | 
             
                  #
         | 
| 82 82 | 
             
                  # @api private
         | 
| 83 83 | 
             
                  def source_path
         | 
| 84 | 
            -
                    source_location.first
         | 
| 84 | 
            +
                    Pathname.new(source_location.first)
         | 
| 85 85 | 
             
                  end
         | 
| 86 | 
            +
                  memoize :source_path
         | 
| 86 87 |  | 
| 87 88 | 
             
                  # Source file line
         | 
| 88 89 | 
             
                  #
         | 
| @@ -22,10 +22,9 @@ module Mutant | |
| 22 22 | 
             
                    # @api private
         | 
| 23 23 | 
             
                    def dispatch
         | 
| 24 24 | 
             
                      emit_singletons
         | 
| 25 | 
            -
                       | 
| 26 | 
            -
                       | 
| 27 | 
            -
                       | 
| 28 | 
            -
                      mutate_operands
         | 
| 25 | 
            +
                      emit_promotions
         | 
| 26 | 
            +
                      emit_operator_mutations
         | 
| 27 | 
            +
                      emit_left_negation
         | 
| 29 28 | 
             
                      emit_left_mutations
         | 
| 30 29 | 
             
                      emit_right_mutations
         | 
| 31 30 | 
             
                    end
         | 
| @@ -35,18 +34,39 @@ module Mutant | |
| 35 34 | 
             
                    # @return [undefined]
         | 
| 36 35 | 
             
                    #
         | 
| 37 36 | 
             
                    # @api private
         | 
| 38 | 
            -
                    def  | 
| 37 | 
            +
                    def emit_operator_mutations
         | 
| 39 38 | 
             
                      emit(s(INVERSE.fetch(node.type), left, right))
         | 
| 40 39 | 
             
                    end
         | 
| 41 40 |  | 
| 42 | 
            -
                    # Emit  | 
| 41 | 
            +
                    # Emit promotions
         | 
| 42 | 
            +
                    #
         | 
| 43 | 
            +
                    # @return [undefined]
         | 
| 44 | 
            +
                    #
         | 
| 45 | 
            +
                    # @api private
         | 
| 46 | 
            +
                    #
         | 
| 47 | 
            +
                    def emit_promotions
         | 
| 48 | 
            +
                      emit(left)
         | 
| 49 | 
            +
                      emit(right)
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    # Emit left negation
         | 
| 53 | 
            +
                    #
         | 
| 54 | 
            +
                    # We do not emit right negation as the `and` and `or` nodes
         | 
| 55 | 
            +
                    # in ruby are also used for control flow.
         | 
| 56 | 
            +
                    #
         | 
| 57 | 
            +
                    # Irrespectable of their syntax, aka `||` parses internally to `or`.
         | 
| 58 | 
            +
                    #
         | 
| 59 | 
            +
                    # `do_a or do_b`. Negating left makes sense, negating right
         | 
| 60 | 
            +
                    # only when the result is actualy used.
         | 
| 61 | 
            +
                    #
         | 
| 62 | 
            +
                    # It *would* be possible to emit the right negation in case the use of the result is proved.
         | 
| 63 | 
            +
                    # Like parent is an assignment to an {l,i}var. Dunno if we ever get the time to do that.
         | 
| 43 64 | 
             
                    #
         | 
| 44 65 | 
             
                    # @return [undefined]
         | 
| 45 66 | 
             
                    #
         | 
| 46 67 | 
             
                    # @api private
         | 
| 47 | 
            -
                    def  | 
| 68 | 
            +
                    def emit_left_negation
         | 
| 48 69 | 
             
                      emit(s(node.type, n_not(left), right))
         | 
| 49 | 
            -
                      emit(n_not(node))
         | 
| 50 70 | 
             
                    end
         | 
| 51 71 |  | 
| 52 72 | 
             
                  end # Binary
         | 
| @@ -28,7 +28,6 @@ module Mutant | |
| 28 28 | 
             
                        print_mutation_results
         | 
| 29 29 | 
             
                        print_progress_bar_finish
         | 
| 30 30 | 
             
                        print_stats
         | 
| 31 | 
            -
                        print_tests
         | 
| 32 31 | 
             
                      end
         | 
| 33 32 |  | 
| 34 33 | 
             
                    private
         | 
| @@ -50,17 +49,6 @@ module Mutant | |
| 50 49 | 
             
                        )
         | 
| 51 50 | 
             
                      end
         | 
| 52 51 |  | 
| 53 | 
            -
                      # Print tests
         | 
| 54 | 
            -
                      #
         | 
| 55 | 
            -
                      # @return [undefined]
         | 
| 56 | 
            -
                      #
         | 
| 57 | 
            -
                      # @api private
         | 
| 58 | 
            -
                      def print_tests
         | 
| 59 | 
            -
                        tests.each do |test|
         | 
| 60 | 
            -
                          puts "- #{test.identification}"
         | 
| 61 | 
            -
                        end
         | 
| 62 | 
            -
                      end
         | 
| 63 | 
            -
             | 
| 64 52 | 
             
                      # Print progress bar finish
         | 
| 65 53 | 
             
                      #
         | 
| 66 54 | 
             
                      # @return [undefined]
         | 
    
        data/lib/mutant/repository.rb
    CHANGED
    
    | @@ -48,7 +48,7 @@ module Mutant | |
| 48 48 | 
             
                  #
         | 
| 49 49 | 
             
                  # @api private
         | 
| 50 50 | 
             
                  def touches?(path, line_range)
         | 
| 51 | 
            -
                    return false unless tracks?(path)
         | 
| 51 | 
            +
                    return false unless within_working_directory?(path) && tracks?(path)
         | 
| 52 52 |  | 
| 53 53 | 
             
                    command = %W[
         | 
| 54 54 | 
             
                      git log
         | 
| @@ -83,6 +83,18 @@ module Mutant | |
| 83 83 | 
             
                    )
         | 
| 84 84 | 
             
                  end
         | 
| 85 85 |  | 
| 86 | 
            +
                  # Test if the path is within the current working directory
         | 
| 87 | 
            +
                  #
         | 
| 88 | 
            +
                  # @param [Pathname] path
         | 
| 89 | 
            +
                  #
         | 
| 90 | 
            +
                  # @return [TrueClass, nil]
         | 
| 91 | 
            +
                  #
         | 
| 92 | 
            +
                  # @api private
         | 
| 93 | 
            +
                  def within_working_directory?(path)
         | 
| 94 | 
            +
                    working_directory = Pathname.pwd
         | 
| 95 | 
            +
                    path.ascend { |parent| return true if working_directory.eql?(parent) }
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
             | 
| 86 98 | 
             
                end # Diff
         | 
| 87 99 | 
             
              end # Repository
         | 
| 88 100 | 
             
            end # Mutant
         | 
    
        data/lib/mutant/subject.rb
    CHANGED
    
    
    
        data/lib/mutant/version.rb
    CHANGED
    
    
    
        data/lib/mutant/zombifier.rb
    CHANGED
    
    
    
        data/meta/and.rb
    CHANGED
    
    
    
        data/meta/defined.rb
    CHANGED
    
    
    
        data/meta/or.rb
    CHANGED
    
    
    
        data/meta/send.rb
    CHANGED
    
    | @@ -118,6 +118,15 @@ Mutant::Meta::Example.add do | |
| 118 118 | 
             
              mutation 'foo.to_int'
         | 
| 119 119 | 
             
            end
         | 
| 120 120 |  | 
| 121 | 
            +
            Mutant::Meta::Example.add do
         | 
| 122 | 
            +
              source 'foo.to_h'
         | 
| 123 | 
            +
             | 
| 124 | 
            +
              singleton_mutations
         | 
| 125 | 
            +
              mutation 'foo'
         | 
| 126 | 
            +
              mutation 'self.to_h'
         | 
| 127 | 
            +
              mutation 'foo.to_hash'
         | 
| 128 | 
            +
            end
         | 
| 129 | 
            +
             | 
| 121 130 | 
             
            Mutant::Meta::Example.add do
         | 
| 122 131 | 
             
              source 'foo == bar'
         | 
| 123 132 |  | 
    
        data/meta/super.rb
    CHANGED
    
    
| @@ -28,6 +28,10 @@ RSpec.shared_examples_for 'a method matcher' do | |
| 28 28 | 
             
                expect(context.scope).to eql(scope)
         | 
| 29 29 | 
             
              end
         | 
| 30 30 |  | 
| 31 | 
            +
              it 'should have the correct source path in context' do
         | 
| 32 | 
            +
                expect(context.source_path).to eql(source_path)
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 31 35 | 
             
              it 'should have the correct node type' do
         | 
| 32 36 | 
             
                expect(node.type).to be(type)
         | 
| 33 37 | 
             
              end
         | 
    
        data/spec/support/corpus.rb
    CHANGED
    
    | @@ -3,13 +3,14 @@ require 'anima' | |
| 3 3 | 
             
            require 'mutant'
         | 
| 4 4 |  | 
| 5 5 | 
             
            module MutantSpec
         | 
| 6 | 
            +
              ROOT = Pathname.new(__FILE__).parent.parent.parent
         | 
| 7 | 
            +
             | 
| 6 8 | 
             
              # Namespace module for corpus testing
         | 
| 7 9 | 
             
              #
         | 
| 8 10 | 
             
              # rubocop:disable MethodLength
         | 
| 9 11 | 
             
              module Corpus
         | 
| 10 12 | 
             
                # Project under corpus test
         | 
| 11 13 | 
             
                # rubocop:disable ClassLength
         | 
| 12 | 
            -
                ROOT = Pathname.new(__FILE__).parent.parent.parent
         | 
| 13 14 | 
             
                TMP = ROOT.join('tmp').freeze
         | 
| 14 15 |  | 
| 15 16 | 
             
                class Project
         | 
| @@ -72,13 +72,15 @@ RSpec.describe Mutant::Isolation::Fork do | |
| 72 72 | 
             
                    expect(IO).to receive(:pipe).with(binmode: true).ordered do |&block|
         | 
| 73 73 | 
             
                      block.call([reader, writer])
         | 
| 74 74 | 
             
                    end
         | 
| 75 | 
            +
                    expect(writer).to receive(:binmode).ordered
         | 
| 75 76 | 
             
                  end
         | 
| 76 77 |  | 
| 77 78 | 
             
                  it 'when fork succeeds' do
         | 
| 78 79 | 
             
                    pid = double('PID')
         | 
| 79 80 | 
             
                    expect(Process).to receive(:fork).ordered.and_yield.and_return(pid)
         | 
| 80 81 | 
             
                    file = double('file')
         | 
| 81 | 
            -
                    expect(File).to receive(:open).ordered | 
| 82 | 
            +
                    expect(File).to receive(:open).ordered
         | 
| 83 | 
            +
                      .with(File::NULL, File::WRONLY).and_yield(file)
         | 
| 82 84 | 
             
                    expect($stderr).to receive(:reopen).ordered.with(file)
         | 
| 83 85 | 
             
                    expect(reader).to receive(:close).ordered
         | 
| 84 86 | 
             
                    expect(writer).to receive(:write).ordered.with(Marshal.dump(:foo))
         | 
| @@ -41,38 +41,43 @@ RSpec.describe Mutant::Matcher::Method::Instance do | |
| 41 41 | 
             
                end
         | 
| 42 42 |  | 
| 43 43 | 
             
                context 'when method is defined once' do
         | 
| 44 | 
            -
                  let(:scope)       { base::DefinedOnce | 
| 45 | 
            -
                  let(: | 
| 44 | 
            +
                  let(:scope)       { base::DefinedOnce                                 }
         | 
| 45 | 
            +
                  let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
         | 
| 46 | 
            +
                  let(:method_line) { 10                                                }
         | 
| 46 47 |  | 
| 47 48 | 
             
                  it_should_behave_like 'a method matcher'
         | 
| 48 49 | 
             
                end
         | 
| 49 50 |  | 
| 50 51 | 
             
                context 'when method is defined once with a memoizer' do
         | 
| 51 | 
            -
                  let(:scope)       { base::WithMemoizer | 
| 52 | 
            -
                  let(: | 
| 52 | 
            +
                  let(:scope)       { base::WithMemoizer                                }
         | 
| 53 | 
            +
                  let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
         | 
| 54 | 
            +
                  let(:method_line) { 15                                                }
         | 
| 53 55 |  | 
| 54 56 | 
             
                  it_should_behave_like 'a method matcher'
         | 
| 55 57 | 
             
                end
         | 
| 56 58 |  | 
| 57 59 | 
             
                context 'when method is defined multiple times' do
         | 
| 58 60 | 
             
                  context 'on different lines' do
         | 
| 59 | 
            -
                    let(:scope)        { base::DefinedMultipleTimes::DifferentLines | 
| 60 | 
            -
                    let(: | 
| 61 | 
            -
                    let(: | 
| 61 | 
            +
                    let(:scope)        { base::DefinedMultipleTimes::DifferentLines        }
         | 
| 62 | 
            +
                    let(:source_path)  { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
         | 
| 63 | 
            +
                    let(:method_line)  { 24                                                }
         | 
| 64 | 
            +
                    let(:method_arity) { 1                                                 }
         | 
| 62 65 |  | 
| 63 66 | 
             
                    it_should_behave_like 'a method matcher'
         | 
| 64 67 | 
             
                  end
         | 
| 65 68 |  | 
| 66 69 | 
             
                  context 'on the same line' do
         | 
| 67 | 
            -
                    let(:scope)        { base::DefinedMultipleTimes::SameLineSameScope | 
| 68 | 
            -
                    let(: | 
| 69 | 
            -
                    let(: | 
| 70 | 
            +
                    let(:scope)        { base::DefinedMultipleTimes::SameLineSameScope     }
         | 
| 71 | 
            +
                    let(:source_path)  { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
         | 
| 72 | 
            +
                    let(:method_line)  { 29                                                }
         | 
| 73 | 
            +
                    let(:method_arity) { 1                                                 }
         | 
| 70 74 |  | 
| 71 75 | 
             
                    it_should_behave_like 'a method matcher'
         | 
| 72 76 | 
             
                  end
         | 
| 73 77 |  | 
| 74 78 | 
             
                  context 'on the same line with different scope' do
         | 
| 75 79 | 
             
                    let(:scope)        { base::DefinedMultipleTimes::SameLineDifferentScope }
         | 
| 80 | 
            +
                    let(:source_path)  { MutantSpec::ROOT.join('test_app/lib/test_app.rb')  }
         | 
| 76 81 | 
             
                    let(:method_line)  { 33                                                 }
         | 
| 77 82 | 
             
                    let(:method_arity) { 1                                                  }
         | 
| 78 83 |  | 
| @@ -21,8 +21,9 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do | |
| 21 21 | 
             
              context 'on singleton methods' do
         | 
| 22 22 |  | 
| 23 23 | 
             
                context 'when also defined on lvar' do
         | 
| 24 | 
            -
                  let(:scope)       { base::AlsoDefinedOnLvar | 
| 25 | 
            -
                  let(: | 
| 24 | 
            +
                  let(:scope)       { base::AlsoDefinedOnLvar                           }
         | 
| 25 | 
            +
                  let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
         | 
| 26 | 
            +
                  let(:method_line) { 66                                                }
         | 
| 26 27 |  | 
| 27 28 | 
             
                  it_should_behave_like 'a method matcher'
         | 
| 28 29 |  | 
| @@ -35,8 +36,9 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do | |
| 35 36 | 
             
                end
         | 
| 36 37 |  | 
| 37 38 | 
             
                context 'when defined on self' do
         | 
| 38 | 
            -
                  let(:scope)       { base::DefinedOnSelf | 
| 39 | 
            -
                  let(: | 
| 39 | 
            +
                  let(:scope)       { base::DefinedOnSelf                               }
         | 
| 40 | 
            +
                  let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
         | 
| 41 | 
            +
                  let(:method_line) { 61                                                }
         | 
| 40 42 |  | 
| 41 43 | 
             
                  it_should_behave_like 'a method matcher'
         | 
| 42 44 | 
             
                end
         | 
| @@ -44,15 +46,17 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do | |
| 44 46 | 
             
                context 'when defined on constant' do
         | 
| 45 47 |  | 
| 46 48 | 
             
                  context 'inside namespace' do
         | 
| 47 | 
            -
                    let(:scope)       { base::DefinedOnConstant::InsideNamespace | 
| 48 | 
            -
                    let(: | 
| 49 | 
            +
                    let(:scope)       { base::DefinedOnConstant::InsideNamespace          }
         | 
| 50 | 
            +
                    let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
         | 
| 51 | 
            +
                    let(:method_line) { 71                                                }
         | 
| 49 52 |  | 
| 50 53 | 
             
                    it_should_behave_like 'a method matcher'
         | 
| 51 54 | 
             
                  end
         | 
| 52 55 |  | 
| 53 56 | 
             
                  context 'outside namespace' do
         | 
| 54 | 
            -
                    let(: | 
| 55 | 
            -
                    let(: | 
| 57 | 
            +
                    let(:scope)       { base::DefinedOnConstant::OutsideNamespace         }
         | 
| 58 | 
            +
                    let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
         | 
| 59 | 
            +
                    let(:method_line) { 78                                                }
         | 
| 56 60 |  | 
| 57 61 | 
             
                    it_should_behave_like 'a method matcher'
         | 
| 58 62 | 
             
                  end
         | 
| @@ -61,6 +65,7 @@ RSpec.describe Mutant::Matcher::Method::Singleton, '#each' do | |
| 61 65 | 
             
                context 'when defined multiple times in the same line' do
         | 
| 62 66 | 
             
                  context 'with method on different scope' do
         | 
| 63 67 | 
             
                    let(:scope)        { base::DefinedMultipleTimes::SameLine::DifferentScope }
         | 
| 68 | 
            +
                    let(:source_path)  { MutantSpec::ROOT.join('test_app/lib/test_app.rb')    }
         | 
| 64 69 | 
             
                    let(:method_line)  { 97                                                   }
         | 
| 65 70 | 
             
                    let(:method_arity) { 1                                                    }
         | 
| 66 71 |  | 
| @@ -107,7 +107,6 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do | |
| 107 107 | 
             
                        subject-a mutations: 2
         | 
| 108 108 | 
             
                        F.
         | 
| 109 109 | 
             
                        (01/02)  50% - killtime: 2.00s runtime: 2.00s overhead: 0.00s
         | 
| 110 | 
            -
                        - test-a
         | 
| 111 110 | 
             
                      REPORT
         | 
| 112 111 | 
             
                    end
         | 
| 113 112 |  | 
| @@ -136,7 +135,6 @@ RSpec.describe Mutant::Reporter::CLI::Printer::Status do | |
| 136 135 | 
             
                        subject-a mutations: 2
         | 
| 137 136 | 
             
                        ..
         | 
| 138 137 | 
             
                        (02/02) 100% - killtime: 2.00s runtime: 2.00s overhead: 0.00s
         | 
| 139 | 
            -
                        - test-a
         | 
| 140 138 | 
             
                      REPORT
         | 
| 141 139 | 
             
                    end
         | 
| 142 140 | 
             
                  end
         | 
| @@ -9,7 +9,6 @@ RSpec.describe Mutant::Reporter::CLI::Printer::SubjectProgress do | |
| 9 9 | 
             
                    subject-a mutations: 2
         | 
| 10 10 | 
             
                    ..
         | 
| 11 11 | 
             
                    (02/02) 100% - killtime: 2.00s runtime: 2.00s overhead: 0.00s
         | 
| 12 | 
            -
                    - test-a
         | 
| 13 12 | 
             
                  STR
         | 
| 14 13 | 
             
                end
         | 
| 15 14 |  | 
| @@ -20,7 +19,6 @@ RSpec.describe Mutant::Reporter::CLI::Printer::SubjectProgress do | |
| 20 19 | 
             
                    subject-a mutations: 2
         | 
| 21 20 | 
             
                    F.
         | 
| 22 21 | 
             
                    (01/02)  50% - killtime: 2.00s runtime: 2.00s overhead: 0.00s
         | 
| 23 | 
            -
                    - test-a
         | 
| 24 22 | 
             
                  STR
         | 
| 25 23 | 
             
                end
         | 
| 26 24 |  | 
| @@ -30,7 +28,6 @@ RSpec.describe Mutant::Reporter::CLI::Printer::SubjectProgress do | |
| 30 28 | 
             
                  it_reports <<-'STR'
         | 
| 31 29 | 
             
                    subject-a mutations: 2
         | 
| 32 30 | 
             
                    (00/02) 100% - killtime: 0.00s runtime: 0.00s overhead: 0.00s
         | 
| 33 | 
            -
                    - test-a
         | 
| 34 31 | 
             
                  STR
         | 
| 35 32 | 
             
                end
         | 
| 36 33 | 
             
              end
         | 
| @@ -8,25 +8,39 @@ describe Mutant::Repository::Diff do | |
| 8 8 | 
             
              end
         | 
| 9 9 |  | 
| 10 10 | 
             
              describe '#touches?' do
         | 
| 11 | 
            -
                let(:object) | 
| 12 | 
            -
                let(:path) | 
| 13 | 
            -
                let(:line_range) | 
| 11 | 
            +
                let(:object)     { described_class.new('from_rev', 'to_rev') }
         | 
| 12 | 
            +
                let(:path)       { Pathname.pwd.join('foo.rb')               }
         | 
| 13 | 
            +
                let(:line_range) { 1..2                                      }
         | 
| 14 14 |  | 
| 15 15 | 
             
                subject { object.touches?(path, line_range) }
         | 
| 16 16 |  | 
| 17 | 
            -
                 | 
| 18 | 
            -
                   | 
| 19 | 
            -
                    . | 
| 20 | 
            -
             | 
| 21 | 
            -
                       | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 17 | 
            +
                shared_context 'test if git tracks the file' do
         | 
| 18 | 
            +
                  before do
         | 
| 19 | 
            +
                    expect(Kernel).to receive(:system)
         | 
| 20 | 
            +
                      .ordered
         | 
| 21 | 
            +
                      .with(
         | 
| 22 | 
            +
                        *%W[git ls-files --error-unmatch -- #{path}],
         | 
| 23 | 
            +
                        out: File::NULL,
         | 
| 24 | 
            +
                        err: File::NULL
         | 
| 25 | 
            +
                      ).and_return(git_ls_success?)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                context 'when file is in a different subdirectory' do
         | 
| 30 | 
            +
                  let(:path) { Pathname.new('/foo.rb') }
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  before do
         | 
| 33 | 
            +
                    expect(Kernel).to_not receive(:system)
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  it { should be(false) }
         | 
| 25 37 | 
             
                end
         | 
| 26 38 |  | 
| 27 39 | 
             
                context 'when file is NOT tracked in repository' do
         | 
| 28 40 | 
             
                  let(:git_ls_success?) { false }
         | 
| 29 41 |  | 
| 42 | 
            +
                  include_context 'test if git tracks the file'
         | 
| 43 | 
            +
             | 
| 30 44 | 
             
                  it { should be(false) }
         | 
| 31 45 | 
             
                end
         | 
| 32 46 |  | 
| @@ -36,6 +50,8 @@ describe Mutant::Repository::Diff do | |
| 36 50 | 
             
                  let(:stdout)          { double('Stdout', empty?: stdout_empty?) }
         | 
| 37 51 | 
             
                  let(:stdout_empty?)   { false                                   }
         | 
| 38 52 |  | 
| 53 | 
            +
                  include_context 'test if git tracks the file'
         | 
| 54 | 
            +
             | 
| 39 55 | 
             
                  before do
         | 
| 40 56 | 
             
                    expect(Open3).to receive(:capture2)
         | 
| 41 57 | 
             
                      .ordered
         | 
| @@ -44,9 +60,7 @@ describe Mutant::Repository::Diff do | |
| 44 60 | 
             
                  end
         | 
| 45 61 |  | 
| 46 62 | 
             
                  let(:expected_git_log_command) do
         | 
| 47 | 
            -
                    % | 
| 48 | 
            -
                      git log from_rev...to_rev -L 1,2:foo.rb
         | 
| 49 | 
            -
                    ]
         | 
| 63 | 
            +
                    %W[git log from_rev...to_rev -L 1,2:#{path}]
         | 
| 50 64 | 
             
                  end
         | 
| 51 65 |  | 
| 52 66 | 
             
                  context 'on failure of git log command' do
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: mutant
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.8. | 
| 4 | 
            +
              version: 0.8.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Markus Schirp
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2015- | 
| 11 | 
            +
            date: 2015-08-11 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: parser
         |