Skip to content

Commit dd79e92

Browse files
Add a test for a subscription trying to send reports on a defunct session.
This is testing the situation described in #24093
1 parent 1c87f62 commit dd79e92

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

src/app/tests/TestReadInteraction.cpp

+89
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ class TestReadInteraction
338338
static void TestReadHandlerInvalidSubscribeRequest(nlTestSuite * apSuite, void * apContext);
339339
static void TestSubscribeInvalidateFabric(nlTestSuite * apSuite, void * apContext);
340340
static void TestShutdownSubscription(nlTestSuite * apSuite, void * apContext);
341+
static void TestSubscriptionReportWithDefunctSession(nlTestSuite * apSuite, void * apContext);
341342
static void TestReadHandlerMalformedSubscribeRequest(nlTestSuite * apSuite, void * apContext);
342343

343344
private:
@@ -4096,6 +4097,93 @@ void TestReadInteraction::TestShutdownSubscription(nlTestSuite * apSuite, void *
40964097
NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
40974098
}
40984099

4100+
/**
4101+
* Tests what happens when a subscription tries to deliver reports but the
4102+
* session it has is defunct. Makes sure we correctly tear down the ReadHandler
4103+
* and don't increment the "reports in flight" count.
4104+
*/
4105+
void TestReadInteraction::TestSubscriptionReportWithDefunctSession(nlTestSuite * apSuite, void * apContext)
4106+
{
4107+
TestContext & ctx = *static_cast<TestContext *>(apContext);
4108+
CHIP_ERROR err = CHIP_NO_ERROR;
4109+
4110+
Messaging::ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
4111+
// Shouldn't have anything in the retransmit table when starting the test.
4112+
NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0);
4113+
4114+
MockInteractionModelApp delegate;
4115+
auto * engine = chip::app::InteractionModelEngine::GetInstance();
4116+
err = engine->Init(&ctx.GetExchangeManager(), &ctx.GetFabricTable());
4117+
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
4118+
4119+
ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
4120+
readPrepareParams.mpAttributePathParamsList = new chip::app::AttributePathParams[1];
4121+
readPrepareParams.mAttributePathParamsListSize = 1;
4122+
4123+
AttributePathParams subscribePath(Test::kMockEndpoint3, Test::MockClusterId(2), Test::MockAttributeId(4));
4124+
readPrepareParams.mpAttributePathParamsList[0] = subscribePath;
4125+
4126+
readPrepareParams.mMinIntervalFloorSeconds = 0;
4127+
readPrepareParams.mMaxIntervalCeilingSeconds = 0;
4128+
4129+
{
4130+
app::ReadClient readClient(chip::app::InteractionModelEngine::GetInstance(), &ctx.GetExchangeManager(), delegate,
4131+
chip::app::ReadClient::InteractionType::Subscribe);
4132+
4133+
delegate.mGotReport = false;
4134+
4135+
err = readClient.SendSubscribeRequest(std::move(readPrepareParams));
4136+
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
4137+
4138+
ctx.DrainAndServiceIO();
4139+
4140+
NL_TEST_ASSERT(apSuite, delegate.mGotReport);
4141+
NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadHandlers(ReadHandler::InteractionType::Subscribe) == 1);
4142+
NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadHandlers(ReadHandler::InteractionType::Read) == 0);
4143+
NL_TEST_ASSERT(apSuite, engine->GetReportingEngine().GetNumReportsInFlight() == 0);
4144+
4145+
NL_TEST_ASSERT(apSuite, engine->ActiveHandlerAt(0) != nullptr);
4146+
auto * readHandler = engine->ActiveHandlerAt(0);
4147+
4148+
// Verify that the session we will reset later is the one we will mess
4149+
// with now.
4150+
NL_TEST_ASSERT(apSuite, SessionHandle(*readHandler->GetSession()) == ctx.GetSessionAliceToBob());
4151+
4152+
// Test that we send reports as needed.
4153+
readHandler->mFlags.Set(ReadHandler::ReadHandlerFlags::HoldReport, false);
4154+
delegate.mGotReport = false;
4155+
engine->GetReportingEngine().SetDirty(subscribePath);
4156+
4157+
ctx.DrainAndServiceIO();
4158+
4159+
NL_TEST_ASSERT(apSuite, delegate.mGotReport);
4160+
NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadHandlers(ReadHandler::InteractionType::Subscribe) == 1);
4161+
NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadHandlers(ReadHandler::InteractionType::Read) == 0);
4162+
NL_TEST_ASSERT(apSuite, engine->GetReportingEngine().GetNumReportsInFlight() == 0);
4163+
4164+
// Test that if the session is defunct we don't send reports and clean
4165+
// up properly.
4166+
readHandler->GetSession()->MarkAsDefunct();
4167+
readHandler->mFlags.Set(ReadHandler::ReadHandlerFlags::HoldReport, false);
4168+
delegate.mGotReport = false;
4169+
engine->GetReportingEngine().SetDirty(subscribePath);
4170+
4171+
ctx.DrainAndServiceIO();
4172+
4173+
NL_TEST_ASSERT(apSuite, !delegate.mGotReport);
4174+
NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadHandlers(ReadHandler::InteractionType::Subscribe) == 0);
4175+
NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadHandlers(ReadHandler::InteractionType::Read) == 0);
4176+
NL_TEST_ASSERT(apSuite, engine->GetReportingEngine().GetNumReportsInFlight() == 0);
4177+
}
4178+
engine->Shutdown();
4179+
NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadClients() == 0);
4180+
NL_TEST_ASSERT(apSuite, ctx.GetExchangeManager().GetNumActiveExchanges() == 0);
4181+
4182+
// Get rid of our defunct session.
4183+
ctx.ExpireSessionAliceToBob();
4184+
ctx.CreateSessionAliceToBob();
4185+
}
4186+
40994187
} // namespace app
41004188
} // namespace chip
41014189

@@ -4159,6 +4247,7 @@ const nlTest sTests[] =
41594247
NL_TEST_DEF("TestPostSubscribeRoundtripChunkStatusReportTimeout", chip::app::TestReadInteraction::TestPostSubscribeRoundtripChunkStatusReportTimeout),
41604248
NL_TEST_DEF("TestPostSubscribeRoundtripChunkReportTimeout", chip::app::TestReadInteraction::TestPostSubscribeRoundtripChunkReportTimeout),
41614249
NL_TEST_DEF("TestReadShutdown", chip::app::TestReadInteraction::TestReadShutdown),
4250+
NL_TEST_DEF("TestSubscriptionReportWithDefunctSession", chip::app::TestReadInteraction::TestSubscriptionReportWithDefunctSession),
41624251
NL_TEST_SENTINEL()
41634252
};
41644253
// clang-format on

0 commit comments

Comments
 (0)