Skip to content

Commit

Permalink
Change incremental to perform an additional AST dirtyness check
Browse files Browse the repository at this point in the history
* This avoids situations where no semantic change occured to trigger incremental selection.
  • Loading branch information
mbj committed Mar 6, 2023
1 parent 0a7fcc1 commit 92b522e
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 21 deletions.
2 changes: 2 additions & 0 deletions lib/mutant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ module Mutant
require 'mutant/repository'
require 'mutant/repository/diff'
require 'mutant/repository/diff/ranges'
require 'mutant/repository/file_revision'
require 'mutant/zombifier'
require 'mutant/range'
require 'mutant/license'
Expand Down Expand Up @@ -319,6 +320,7 @@ module Mutant
mutex: Mutex,
object_space: ObjectSpace,
open3: Open3,
parser: Parser.new,
pathname: Pathname,
process: Process,
random: Random,
Expand Down
6 changes: 4 additions & 2 deletions lib/mutant/cli/command/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,13 @@ def add_matcher_options(parser)
parser.on('--start-subject EXPRESSION', 'Start mutation testing at a specific subject') do |pattern|
add_matcher(:start_expressions, @config.expression_parser.call(pattern).from_right)
end
parser.on('--since REVISION', 'Only select subjects touched since REVISION') do |revision|
parser.on('--since REVISION', 'Only select dirty subjects since REVISION') do |revision|
add_matcher(
:subject_filters,
Repository::SubjectFilter.new(
Repository::Diff.new(to: revision, world: world)
diff: Repository::Diff.new(to: revision, world: world),
revision: revision,
world: world
)
)
end
Expand Down
9 changes: 7 additions & 2 deletions lib/mutant/env.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class Env
:integration,
:matchable_scopes,
:mutations,
:parser,
:selector,
:subjects,
:world
Expand Down Expand Up @@ -37,7 +36,6 @@ def self.empty(world, config)
),
matchable_scopes: EMPTY_ARRAY,
mutations: EMPTY_ARRAY,
parser: Parser.new,
selector: Selector::Null.new,
subjects: EMPTY_ARRAY,
world: world
Expand All @@ -64,6 +62,13 @@ def cover_index(mutation_index)
)
end

# The parser
#
# @return [Parser]
def parser
world.parser
end

# The test selections
#
# @return Hash{Mutation => Enumerable<Test>}
Expand Down
2 changes: 1 addition & 1 deletion lib/mutant/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Mutant
module Repository
# Subject filter based on repository diff
class SubjectFilter
include Adamantium, Concord.new(:diff)
include Adamantium, Anima.new(:diff, :revision, :world)

# Test if subject was touched in diff
#
Expand Down
12 changes: 12 additions & 0 deletions lib/mutant/repository/file_revision.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module Mutant
module Repository
class FileRevision
def self.read(world:, revision:, file_name:)
world
.capture_stdout(%w[git show #{revision}:#{file_name}])
end
end # FileRevision
end # Repository
end # Mutant
1 change: 1 addition & 0 deletions lib/mutant/world.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class World
:mutex,
:object_space,
:open3,
:parser,
:pathname,
:process,
:random,
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ def fake_world
mutex: class_double(Mutex),
object_space: class_double(ObjectSpace),
open3: class_double(Open3),
parser: class_double(Mutant::Parser),
pathname: class_double(Pathname),
process: class_double(Process),
random: class_double(Random),
Expand Down
1 change: 1 addition & 0 deletions spec/unit/mutant/bootstrap_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def require(_); end
kernel: kernel,
load_path: load_path,
object_space: object_space,
parser: Mutant::Parser.new,
pathname: Pathname,
recorder: instance_double(Mutant::Segment::Recorder),
timer: timer
Expand Down
18 changes: 11 additions & 7 deletions spec/unit/mutant/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ def self.main_body
Matcher:
--ignore-subject EXPRESSION Ignore subjects that match EXPRESSION as prefix
--start-subject EXPRESSION Start mutation testing at a specific subject
--since REVISION Only select subjects touched since REVISION
--since REVISION Only select dirty subjects since REVISION
MESSAGE

{
Expand Down Expand Up @@ -348,7 +348,7 @@ def self.main_body
Matcher:
--ignore-subject EXPRESSION Ignore subjects that match EXPRESSION as prefix
--start-subject EXPRESSION Start mutation testing at a specific subject
--since REVISION Only select subjects touched since REVISION
--since REVISION Only select dirty subjects since REVISION
MESSAGE

{
Expand Down Expand Up @@ -395,7 +395,7 @@ def self.main_body
Matcher:
--ignore-subject EXPRESSION Ignore subjects that match EXPRESSION as prefix
--start-subject EXPRESSION Start mutation testing at a specific subject
--since REVISION Only select subjects touched since REVISION
--since REVISION Only select dirty subjects since REVISION
MESSAGE

{
Expand Down Expand Up @@ -1290,10 +1290,12 @@ def self.main_body
matcher: file_config.matcher.with(
subject_filters: [
Mutant::Repository::SubjectFilter.new(
Mutant::Repository::Diff.new(
diff: Mutant::Repository::Diff.new(
to: 'reference',
world: world
)
),
revision: 'reference',
world: world
)
]
)
Expand All @@ -1305,10 +1307,12 @@ def self.main_body
matcher: file_config.matcher.with(
subject_filters: [
Mutant::Repository::SubjectFilter.new(
Mutant::Repository::Diff.new(
diff: Mutant::Repository::Diff.new(
to: 'reference',
world: world
)
),
revision: 'reference',
world: world
)
]
)
Expand Down
8 changes: 6 additions & 2 deletions spec/unit/mutant/env_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
integration: integration,
matchable_scopes: [],
mutations: [mutation],
parser: Mutant::Parser.new,
selector: selector,
subjects: subjects,
world: world
Expand Down Expand Up @@ -239,7 +238,6 @@ def apply
integration: integration,
matchable_scopes: Mutant::EMPTY_ARRAY,
mutations: Mutant::EMPTY_ARRAY,
parser: Mutant::Parser.new,
selector: Mutant::Selector::Null.new,
subjects: Mutant::EMPTY_ARRAY,
world: world
Expand Down Expand Up @@ -268,4 +266,10 @@ def apply
expect(events).to eql([%i[test_segment value]])
end
end

describe '#parser' do
it 'returns the world parser' do
expect(subject.parser).to be(world.parser)
end
end
end
26 changes: 19 additions & 7 deletions spec/unit/mutant/repository/subject_filter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@

RSpec.describe Mutant::Repository::SubjectFilter do
context '#call' do
subject { object.call(mutant_subject) }
def apply
subject.call(mutant_subject)
end

let(:object) { described_class.new(diff) }
let(:diff) { instance_double(Mutant::Repository::Diff) }
let(:value) { instance_double(Object, 'value') }
subject do
described_class.new(
diff: diff,
revision: 'revision',
world: fake_world
)
end

let(:diff) { instance_double(Mutant::Repository::Diff) }

let(:mutant_subject) do
double(
Expand All @@ -20,11 +28,15 @@
expect(diff).to receive(:touches?).with(
mutant_subject.source_path,
mutant_subject.source_lines
).and_return(value)
).and_return(touches?)
end

it 'connects return value to repository diff API' do
expect(subject).to be(value)
context 'when subject lines are not touched' do
let(:touches?) { false }

it 'returns false' do
expect(apply).to be(false)
end
end
end
end

0 comments on commit 92b522e

Please sign in to comment.