Merge pull request #775 from mbj/add/clock-monotonic

Add Mutant::Timer
This commit is contained in:
Markus Schirp 2018-11-25 22:09:25 +00:00 committed by GitHub
commit 0303f647d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 93 additions and 15 deletions

View file

@ -1,3 +1,7 @@
# v0.8.20 2018-11-25
* Replace internal timers with monotonic ones.
# v0.8.19 2018-11-06
* Drop support for Ruby < 2.5

View file

@ -177,6 +177,7 @@ require 'mutant/expression/method'
require 'mutant/expression/methods'
require 'mutant/expression/namespace'
require 'mutant/test'
require 'mutant/timer'
require 'mutant/integration'
require 'mutant/selector'
require 'mutant/selector/expression'

View file

@ -42,7 +42,7 @@ module Mutant
#
# rubocop:disable MethodLength
def run_mutation_tests(mutation)
start = Time.now
start = Timer.now
tests = selector.call(mutation.subject)
config.isolation.call do
@ -53,7 +53,7 @@ module Mutant
Result::Test.new(
output: error.message,
passed: false,
runtime: Time.now - start,
runtime: Timer.now - start,
tests: tests
)
end

View file

@ -82,7 +82,7 @@ module Mutant
def call(tests)
test_cases = tests.map(&all_tests_index.method(:fetch))
output = StringIO.new
start = Time.now
start = Timer.now
reporter = ::Minitest::SummaryReporter.new(output)
@ -98,7 +98,7 @@ module Mutant
passed: reporter.passed?,
tests: tests,
output: output.read,
runtime: Time.now - start
runtime: Timer.now - start
)
end

View file

@ -61,13 +61,13 @@ module Mutant
def call(tests)
examples = tests.map(&all_tests_index.method(:fetch))
filter_examples(&examples.method(:include?))
start = Time.now
start = Timer.now
passed = @runner.run_specs(@world.ordered_example_groups).equal?(EXIT_SUCCESS)
@output.rewind
Result::Test.new(
output: @output.read,
passed: passed,
runtime: Time.now - start,
runtime: Timer.now - start,
tests: tests
)
end

View file

@ -10,7 +10,7 @@ module Mutant
# @return [undefined]
def initialize(*)
super
@start = Time.now
@start = Timer.now
@subject_results = {}
end
@ -20,7 +20,7 @@ module Mutant
def status
Result::Env.new(
env: env,
runtime: Time.now - @start,
runtime: Timer.now - @start,
subject_results: @subject_results.values
)
end

21
lib/mutant/timer.rb Normal file
View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
module Mutant
module Timer
# Monotonic elapsed time of block execution
#
# @return [Float]
def self.elapsed
start = now
yield
now - start
end
# The now monotonic time
#
# @return [Float]
def self.now
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
end # Timer
end # Mutant

View file

@ -79,7 +79,7 @@ module MutantSpec
# otherwise
def verify_mutation_generation
checkout
start = Time.now
start = Mutant::Timer.now
options = {
finish: method(:finish),
@ -90,7 +90,7 @@ module MutantSpec
total = Parallel.map(effective_ruby_paths, options, &method(:count_mutations_and_check_errors))
.inject(DEFAULT_MUTATION_COUNT, :+)
took = Time.now - start
took = Mutant::Timer.now - start
puts MUTATION_GENERATION_MESSAGE % [total, took, total / took]
self
end

View file

@ -0,0 +1,52 @@
# frozen_string_literal: true
RSpec.describe Mutant::Timer do
let(:events) { [] }
let(:times) { [1.0, 2.0] }
before do
allow(Process).to receive(:clock_gettime) do |argument|
expect(argument).to be(Process::CLOCK_MONOTONIC)
events << :clock_gettime
times.fetch(events.count(:clock_gettime).pred)
end
end
describe '.elapsed' do
def apply
described_class.elapsed { events << :yield }
end
it 'executes events in expected sequence' do
expect { apply }
.to change(events, :to_a)
.from([])
.to(%i[clock_gettime yield clock_gettime])
end
it 'returns elapsed time' do
expect(apply).to be(1.0)
end
end
describe '.now' do
def apply
described_class.now
end
it 'returns current monotonic time' do
expect(apply).to be(1.0)
expect(apply).to be(2.0)
end
it 'calls expected system API' do
expect { apply }
.to change(events, :to_a)
.from([])
.to(%i[clock_gettime])
end
end
end

View file

@ -57,7 +57,7 @@ RSpec.describe Mutant::Env do
.with(mutation_subject)
.and_return(tests)
allow(Time).to receive_messages(now: Time.at(0))
allow(Mutant::Timer).to receive(:now).and_return(2.0, 3.0)
end
context 'when isolation does not raise error' do
@ -91,7 +91,7 @@ RSpec.describe Mutant::Env do
Mutant::Result::Test.new(
output: 'test-error',
passed: false,
runtime: 0.0,
runtime: 1.0,
tests: tests
)
end

View file

@ -126,7 +126,7 @@ RSpec.describe Mutant::Integration::Rspec do
.and_return(rspec_runner)
expect(RSpec).to receive_messages(world: world)
allow(Time).to receive_messages(now: Time.now)
allow(Mutant::Timer).to receive_messages(now: Mutant::Timer.now)
end
describe '#all_tests' do

View file

@ -41,7 +41,7 @@ RSpec.describe Mutant::Reporter::CLI do
end
before do
allow(Time).to receive(:now).and_return(Time.now)
allow(Mutant::Timer).to receive_messages(now: Mutant::Timer.now)
end
describe '.build' do

View file

@ -19,7 +19,7 @@ describe Mutant::Runner::Sink do
let(:object) { described_class.new(env) }
before do
allow(Time).to receive(:now).and_return(Time.now)
allow(Mutant::Timer).to receive_messages(now: Mutant::Timer.now)
end
describe '#result' do