commit
						0303f647d5
					
				
					 13 changed files with 93 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
									
								
							
							
						
						
									
										21
									
								
								lib/mutant/timer.rb
									
										
									
									
									
										Normal 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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										52
									
								
								spec/unit/mutant/clock_monotonic_spec.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								spec/unit/mutant/clock_monotonic_spec.rb
									
										
									
									
									
										Normal 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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue