Skip to content

Commit 128aa4b

Browse files
committed
🐛 Use monotonic time to calculate elapsed time
- See: https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/
1 parent ce45fa6 commit 128aa4b

File tree

10 files changed

+49
-10
lines changed

10 files changed

+49
-10
lines changed

Gemfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ source "https://rubygems.org"
88
# Uncomment this to use development version of html formatter from github
99
# gem "simplecov-html", github: "simplecov-ruby/simplecov-html"
1010

11+
# std lib gems removed from std lib
12+
gem "logger"
13+
1114
gem "matrix"
1215

1316
group :development do

Gemfile.lock

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ GEM
8383
json (2.9.1)
8484
json (2.9.1-java)
8585
language_server-protocol (3.17.0.3)
86+
logger (1.6.6)
8687
matrix (0.4.2)
8788
method_source (1.1.0)
8889
mini_mime (1.1.5)
@@ -180,6 +181,7 @@ DEPENDENCIES
180181
benchmark-ips
181182
capybara
182183
cucumber
184+
logger
183185
matrix
184186
minitest
185187
pry
@@ -192,4 +194,4 @@ DEPENDENCIES
192194
webrick
193195

194196
BUNDLED WITH
195-
2.7.0.dev
197+
2.6.5

features/step_definitions/old_coverage_json_steps.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
in_current_directory do
1616
resultset_json = File.read(RESULTSET_JSON_PATH)
1717
resultset_hash = JSON.parse(resultset_json)
18-
resultset_hash[COMMAND_NAME]["timestamp"] = Time.now.to_i
18+
resultset_hash[COMMAND_NAME]["timestamp"] = SimpleCov::Timer.monotonic.truncate
1919
File.write(RESULTSET_JSON_PATH, JSON.pretty_generate(resultset_hash))
2020
end
2121
end

lib/simplecov.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def result_exit_status(result)
267267
#
268268
def final_result_process?
269269
# checking for ENV["TEST_ENV_NUMBER"] to determine if the tests are being run in parallel
270-
!defined?(ParallelTests) || !ENV["TEST_ENV_NUMBER"] || ParallelTests.last_process?
270+
!ENV["TEST_ENV_NUMBER"] || (defined?(ParallelTests) && ParallelTests.last_process?)
271271
end
272272

273273
#
@@ -448,6 +448,7 @@ def probably_running_parallel_tests?
448448
require "forwardable"
449449
require_relative "simplecov/configuration"
450450
SimpleCov.extend SimpleCov::Configuration
451+
require_relative "simplecov/timer"
451452
require_relative "simplecov/coverage_statistics"
452453
require_relative "simplecov/exit_codes"
453454
require_relative "simplecov/profiles"

lib/simplecov/result.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ def format!
5151
SimpleCov.formatter.new.format(self)
5252
end
5353

54-
# Defines when this result has been created. Defaults to Time.now
54+
# Defines when this result has been created. Defaults to current truncated system monotonic uptime
5555
def created_at
56-
@created_at ||= Time.now
56+
@created_at ||= SimpleCov::Timer.monotonic.truncate
5757
end
5858

5959
# The command name that launched this result.

lib/simplecov/result_merger.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ def within_merge_timeout?(data)
8787
end
8888

8989
def time_since_result_creation(data)
90-
Time.now - Time.at(data.fetch("timestamp"))
90+
timestamp = data.fetch("timestamp")
91+
timer = SimpleCov::Timer.new(timestamp)
92+
timer.elapsed_seconds
9193
end
9294

9395
def create_result(command_names, coverage)

lib/simplecov/timer.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
# Use system uptime to calculate accurate and reliable elapsed time.
4+
#
5+
# Question:
6+
# Why not just do:
7+
# elapsed_time = Time.now - other_time
8+
# Answer:
9+
# It is not accurate or reliable.
10+
# https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/
11+
module SimpleCov
12+
class Timer
13+
attr_accessor :start_time
14+
15+
class << self
16+
def monotonic
17+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
18+
end
19+
end
20+
21+
# Capture Time when instantiated
22+
def initialize(start_time)
23+
@start_time = start_time || self.class.monotonic
24+
end
25+
26+
# Get Elapsed Time in Seconds
27+
def elapsed_seconds
28+
(self.class.monotonic - @start_time).truncate
29+
end
30+
end
31+
end

spec/result_merger_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
data = {
176176
"some command name" => {
177177
"coverage" => content,
178-
"timestamp" => Time.now.to_i
178+
"timestamp" => SimpleCov::Timer.monotonic.truncate
179179
}
180180
}
181181
File.open(file_path, "w+") do |f|
@@ -286,7 +286,7 @@ def store_result(result, path:)
286286
end
287287

288288
def outdated(result)
289-
result.created_at = Time.now - 172_800
289+
result.created_at = SimpleCov::Timer.monotonic.truncate - 172_800
290290
result
291291
end
292292

spec/result_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@
212212
source_fixture("sample.rb") => {"lines" => [nil, 1, 1, 1, nil, nil, 0, 0, nil, nil]}
213213
}
214214
end
215-
let(:created_at) { Time.now.to_i }
215+
let(:created_at) { SimpleCov::Timer.monotonic.truncate }
216216

217217
it "can consume multiple commands" do
218218
input = {

spec/simplecov_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@
299299
def create_mergeable_report(name, resultset, outdated: false)
300300
result = SimpleCov::Result.new(resultset)
301301
result.command_name = name
302-
result.created_at = Time.now - 172_800 if outdated
302+
result.created_at = SimpleCov::Timer.monotonic.truncate - 172_800 if outdated
303303
SimpleCov::ResultMerger.store_result(result)
304304
FileUtils.mv resultset_path, "#{resultset_path}#{name}.final"
305305
end

0 commit comments

Comments
 (0)