@@ -244,7 +244,8 @@ public void testIsPlanRefreshError() {
244244 }
245245
246246 @ Test
247- public void planRefreshDelayIsFactoredIntoExecuteTimeout () throws InterruptedException {
247+ public void planRefreshDelayIsFactoredIntoExecuteTimeout ()
248+ throws InterruptedException , ExecutionException {
248249 MockServerStreamingCallable <ExecuteQueryRequest , ExecuteQueryResponse > innerCallable =
249250 new MockServerStreamingCallable <>();
250251 RequestContext requestContext = RequestContext .create ("project" , "instance" , "profile" );
@@ -258,30 +259,39 @@ public void planRefreshDelayIsFactoredIntoExecuteTimeout() throws InterruptedExc
258259 ExecuteQueryCallContext callContext =
259260 ExecuteQueryCallContext .create (preparedStatement .bind ().build (), metadataFuture );
260261
261- Duration originalAttemptTimeout = Duration .ofMillis (100 );
262+ // Simulate delay for prepare response
263+ int prepareDelayMs = 50 ;
264+ SettableApiFuture <Instant > prepareResolvedAt = SettableApiFuture .create ();
262265 scheduler .schedule (
263266 () -> {
267+ prepareResolvedAt .set (Instant .now ());
264268 prepareFuture .set (
265269 PrepareResponse .fromProto (
266270 prepareResponse (
267271 ByteString .copyFromUtf8 ("initialPlan" ),
268272 metadata (columnMetadata ("strCol" , stringType ())))));
269273 },
270- 50 ,
274+ prepareDelayMs ,
271275 TimeUnit .MILLISECONDS );
276+
277+ Duration originalAttemptTimeout = Duration .ofMillis (5000 );
272278 ApiCallContext context =
273279 GrpcCallContext .createDefault ().withTimeoutDuration (originalAttemptTimeout );
274- // prepare takes 50 ms to resolve. Despite that the execute timeout should be around 100ms from
275- // now (w padding)
276- Deadline paddedDeadlineAtStartOfCall =
277- Deadline .after (originalAttemptTimeout .toMillis () + 5 , TimeUnit .MILLISECONDS );
280+ Instant startOfCall = Instant .now ();
278281 callable .call (callContext , outerObserver , context );
279282 scheduler .shutdown ();
280283 scheduler .awaitTermination (30 , TimeUnit .SECONDS );
281284 GrpcCallContext grpcCallContext =
282285 (GrpcCallContext ) innerCallable .popLastCall ().getApiCallContext ();
286+
287+ // Deadline should be at most (original deadline - prepare delay). Add 1ms to avoid flakiness.
288+ Duration prepareLatency = Duration .between (startOfCall , prepareResolvedAt .get ());
289+ Deadline deadlineUpperBound =
290+ Deadline .after (
291+ originalAttemptTimeout .toMillis () - prepareLatency .toMillis () + 1 ,
292+ TimeUnit .MILLISECONDS );
283293 Deadline executeDeadline = grpcCallContext .getCallOptions ().getDeadline ();
284- assertThat (executeDeadline .isBefore (paddedDeadlineAtStartOfCall )).isTrue ();
294+ assertThat (executeDeadline .isBefore (deadlineUpperBound )).isTrue ();
285295 }
286296
287297 @ Test
0 commit comments