Skip to content

Commit 333fdfc

Browse files
committed
fix(gapic-common): Hardened deadline determination against Time.now hacking
1 parent f0a5746 commit 333fdfc

File tree

4 files changed

+20
-11
lines changed

4 files changed

+20
-11
lines changed

gapic-common/lib/gapic/grpc/service_stub/rpc_call.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,21 @@ def calculate_deadline options
145145
return if options.timeout.nil?
146146
return if options.timeout.negative?
147147

148-
Time.now + options.timeout
148+
current_time + options.timeout
149149
end
150150

151151
def check_retry? deadline
152152
return true if deadline.nil?
153153

154-
deadline > Time.now
154+
deadline > current_time
155+
end
156+
157+
def current_time
158+
# An alternative way of saying Time.now without actually calling
159+
# Time.now. This allows clients that replace Time.now (e.g. via the
160+
# timecop gem) to do so without interfering with the deadline.
161+
nanos = Process.clock_gettime Process::CLOCK_REALTIME, :nanosecond
162+
Time.at(nanos / 1_000_000_000, nanos % 1_000_000_000, :nanosecond)
155163
end
156164
end
157165
end

gapic-common/lib/gapic/headers.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ module Headers
3838
def self.x_goog_api_client ruby_version: nil, lib_name: nil, lib_version: nil, gax_version: nil,
3939
gapic_version: nil, grpc_version: nil, rest_version: nil, protobuf_version: nil,
4040
transports_version_send: [:grpc]
41-
4241
ruby_version ||= ::RUBY_VERSION
4342
gax_version ||= ::Gapic::Common::VERSION
4443
grpc_version ||= ::GRPC::VERSION if defined? ::GRPC::VERSION

gapic-common/test/gapic/grpc/rpc_call/retry/raise_test.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ def test_times_out
7474

7575
rpc_call = Gapic::ServiceStub::RpcCall.new api_meth_stub
7676

77-
time_now = Time.now
78-
time_proc = lambda do
79-
time_now += 60
77+
nanos = Process.clock_gettime Process::CLOCK_REALTIME, :nanosecond
78+
time_proc = lambda do |*|
79+
nanos += 60_000_000_000
8080
end
8181

8282
sleep_mock = Minitest::Mock.new
@@ -92,12 +92,13 @@ def test_times_out
9292
)
9393

9494
Kernel.stub :sleep, sleep_proc do
95-
Time.stub :now, time_proc do
95+
Process.stub :clock_gettime, time_proc do
9696
assert_raises GRPC::BadStatus do
9797
rpc_call.call Object.new, options: options
9898
end
9999

100-
assert_equal time_now, deadline_arg
100+
expected_time = Time.at(nanos / 1_000_000_000, nanos % 1_000_000_000, :nanosecond)
101+
assert_equal expected_time, deadline_arg
101102
assert_equal to_attempt, call_count
102103
end
103104
end

gapic-common/test/gapic/grpc/rpc_call/retry/retry_test.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,13 @@ def test_retries_with_exponential_backoff
5858
end
5959
sleep_proc = ->(count) { sleep_mock.sleep count }
6060

61-
time_now = Time.now
62-
Time.stub :now, time_now do
61+
nanos = Process.clock_gettime Process::CLOCK_REALTIME, :nanosecond
62+
expected_time = Time.at(nanos / 1_000_000_000, nanos % 1_000_000_000, :nanosecond)
63+
Process.stub :clock_gettime, nanos do
6364
Kernel.stub :sleep, sleep_proc do
6465
assert_equal 1729, rpc_call.call(Object.new, options: options)
6566
assert_equal 5, inner_attempts
66-
assert_equal time_now + 300, deadline_arg
67+
assert_equal(expected_time + 300, deadline_arg)
6768
end
6869
end
6970

0 commit comments

Comments
 (0)