@@ -151,13 +151,14 @@ class NetworkInterfaceTest : public NetworkInterfaceIntegrationFixture {
151151
152152 RemoteCommandRequest makeTestCommand (boost::optional<Milliseconds> timeout = boost::none,
153153 BSONObj cmd = BSON(" echo" << 1 << " foo"
154- << " bar" )) {
154+ << " bar" ),
155+ OperationContext* opCtx = nullptr) {
155156 auto cs = fixture ();
156157 return RemoteCommandRequest (cs.getServers ().front (),
157158 " admin" ,
158159 std::move (cmd),
159160 BSONObj (),
160- nullptr ,
161+ opCtx ,
161162 timeout ? *timeout : RemoteCommandRequest::kNoTimeout );
162163 }
163164
@@ -289,6 +290,81 @@ TEST_F(NetworkInterfaceTest, AsyncOpTimeout) {
289290 }
290291}
291292
293+ TEST_F (NetworkInterfaceTest, AsyncOpTimeoutWithOpCtxDeadlineSooner) {
294+ // Kick off operation
295+ auto cb = makeCallbackHandle ();
296+ auto cmdObj = BSON (" sleep" << 1 << " lock"
297+ << " none"
298+ << " secs" << 1000000000 );
299+
300+ constexpr auto opCtxDeadline = Milliseconds{600 };
301+ constexpr auto requestTimeout = Milliseconds{1000 };
302+
303+ auto serviceContext = ServiceContext::make ();
304+ auto client = serviceContext->makeClient (" NetworkClient" );
305+ auto opCtx = client->makeOperationContext ();
306+ opCtx->setDeadlineAfterNowBy (opCtxDeadline, ErrorCodes::ExceededTimeLimit);
307+
308+ auto request = makeTestCommand (requestTimeout, cmdObj, opCtx.get ());
309+
310+ auto deferred = runCommand (cb, request);
311+
312+ waitForIsMaster ();
313+
314+ auto result = deferred.get ();
315+
316+ // mongos doesn't implement the ping command, so ignore the response there, otherwise
317+ // check that we've timed out.
318+ if (pingCommandMissing (result)) {
319+ return ;
320+ }
321+
322+ ASSERT_EQ (ErrorCodes::NetworkInterfaceExceededTimeLimit, result.status );
323+ ASSERT (result.elapsedMillis );
324+ // check that the request timeout uses the smaller of the operation context deadline and
325+ // the timeout specified in the request constructor.
326+ ASSERT_GTE (result.elapsedMillis .value (), opCtxDeadline);
327+ ASSERT_LT (result.elapsedMillis .value (), requestTimeout);
328+ assertNumOps (0u , 1u , 0u , 0u );
329+ }
330+
331+ TEST_F (NetworkInterfaceTest, AsyncOpTimeoutWithOpCtxDeadlineLater) {
332+ // Kick off operation
333+ auto cb = makeCallbackHandle ();
334+ auto cmdObj = BSON (" sleep" << 1 << " lock"
335+ << " none"
336+ << " secs" << 1000000000 );
337+
338+ constexpr auto opCtxDeadline = Milliseconds{1000 };
339+ constexpr auto requestTimeout = Milliseconds{600 };
340+
341+ auto serviceContext = ServiceContext::make ();
342+ auto client = serviceContext->makeClient (" NetworkClient" );
343+ auto opCtx = client->makeOperationContext ();
344+ opCtx->setDeadlineAfterNowBy (opCtxDeadline, ErrorCodes::ExceededTimeLimit);
345+ auto request = makeTestCommand (requestTimeout, cmdObj, opCtx.get ());
346+
347+ auto deferred = runCommand (cb, request);
348+
349+ waitForIsMaster ();
350+
351+ auto result = deferred.get ();
352+
353+ // mongos doesn't implement the ping command, so ignore the response there, otherwise
354+ // check that we've timed out.
355+ if (pingCommandMissing (result)) {
356+ return ;
357+ }
358+
359+ ASSERT_EQ (ErrorCodes::NetworkInterfaceExceededTimeLimit, result.status );
360+ ASSERT (result.elapsedMillis );
361+ // check that the request timeout uses the smaller of the operation context deadline and
362+ // the timeout specified in the request constructor.
363+ ASSERT_GTE (result.elapsedMillis .value (), requestTimeout);
364+ ASSERT_LT (result.elapsedMillis .value (), opCtxDeadline);
365+ assertNumOps (0u , 1u , 0u , 0u );
366+ }
367+
292368TEST_F (NetworkInterfaceTest, StartCommand) {
293369 auto commandRequest = BSON (" echo" << 1 << " boop"
294370 << " bop" );
0 commit comments