TEST_F(ReporterTest, TriggerBeforeKeepAliveTimeoutShouldCancelExistingTimeoutAndSendUpdateImmediately) { processNetworkResponse(BSON("ok" << 1)); auto keepAliveTimeoutWhen = getExecutor().now() + reporter->getKeepAliveInterval(); ASSERT_EQUALS(keepAliveTimeoutWhen, reporter->getKeepAliveTimeoutWhen_forTest()); ASSERT_TRUE(reporter->isActive()); auto until = keepAliveTimeoutWhen - reporter->getKeepAliveInterval() / 2; runUntil(until); ASSERT_OK(reporter->trigger()); // '_keepAliveTimeoutWhen' is reset by trigger() not by the canceled callback. ASSERT_EQUALS(Date_t(), reporter->getKeepAliveTimeoutWhen_forTest()); ASSERT_TRUE(reporter->isActive()); processNetworkResponse(BSON("ok" << 1)); keepAliveTimeoutWhen = getExecutor().now() + reporter->getKeepAliveInterval(); // A new keep alive timeout should be scheduled. ASSERT_EQUALS(keepAliveTimeoutWhen, reporter->getKeepAliveTimeoutWhen_forTest()); ASSERT_TRUE(reporter->isActive()); reporter->shutdown(); ASSERT_EQUALS(ErrorCodes::CallbackCanceled, reporter->join()); assertReporterDone(); }
TEST_F(ReporterTest, ShutdownImmediatelyAfterTriggerWhileKeepAliveTimeoutIsScheduledShouldSucceed) { processNetworkResponse(BSON("ok" << 1)); auto keepAliveTimeoutWhen = getExecutor().now() + reporter->getKeepAliveInterval(); ASSERT_EQUALS(keepAliveTimeoutWhen, reporter->getKeepAliveTimeoutWhen_forTest()); ASSERT_TRUE(reporter->isActive()); auto until = keepAliveTimeoutWhen - reporter->getKeepAliveInterval() / 2; runUntil(until); ASSERT_OK(reporter->trigger()); // '_keepAliveTimeoutWhen' is reset by trigger() not by the canceled callback. ASSERT_EQUALS(Date_t(), reporter->getKeepAliveTimeoutWhen_forTest()); ASSERT_TRUE(reporter->isActive()); auto net = getNet(); net->enterNetwork(); ASSERT_TRUE(net->hasReadyRequests()); net->exitNetwork(); reporter->shutdown(); net->enterNetwork(); ASSERT_FALSE(net->hasReadyRequests()); // Executor should invoke reporter callback with a ErrorCodes::CallbackCanceled status. net->runReadyNetworkOperations(); net->exitNetwork(); ASSERT_EQUALS(ErrorCodes::CallbackCanceled, reporter->join()); assertReporterDone(); }
TEST_F(ReporterTest, KeepAliveTimeoutFailingToScheduleRemoteCommandShouldMakeReporterInactive) { processNetworkResponse(BSON("ok" << 1)); auto until = getExecutor().now() + reporter->getKeepAliveInterval(); ASSERT_EQUALS(until, reporter->getKeepAliveTimeoutWhen_forTest()); ASSERT_TRUE(reporter->isActive()); Status expectedStatus(ErrorCodes::UnknownError, "failed to prepare update command"); prepareReplSetUpdatePositionCommandFn = [expectedStatus]() -> StatusWith<BSONObj> { return expectedStatus; }; runUntil(until); ASSERT_EQUALS(expectedStatus, reporter->join()); assertReporterDone(); }
TEST_F(ReporterTest, FailingToScheduleTimeoutShouldMakeReporterInactive) { class TaskExecutorWithFailureInScheduleWorkAt : public unittest::TaskExecutorProxy { public: TaskExecutorWithFailureInScheduleWorkAt(executor::TaskExecutor* executor) : unittest::TaskExecutorProxy(executor) {} virtual StatusWith<executor::TaskExecutor::CallbackHandle> scheduleWorkAt( Date_t when, CallbackFn&&) override { return Status(ErrorCodes::OperationFailed, "failed to schedule work"); } }; TaskExecutorWithFailureInScheduleWorkAt badExecutor(&getExecutor()); _executorProxy->setExecutor(&badExecutor); processNetworkResponse(BSON("ok" << 1)); _executorProxy->setExecutor(&getExecutor()); ASSERT_EQUALS(ErrorCodes::OperationFailed, reporter->join()); assertReporterDone(); }
executor::RemoteCommandRequest AbstractOplogFetcherTest::processNetworkResponse( BSONObj obj, bool expectReadyRequestsAfterProcessing) { return processNetworkResponse({obj, Milliseconds(0)}, expectReadyRequestsAfterProcessing); }