Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[app] Forget exchange context when SubscribeResponse is received #11211

Merged
merged 1 commit into from
Nov 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ CHIP_ERROR ReadClient::OnMessageReceived(Messaging::ExchangeContext * apExchange
{
VerifyOrExit(apExchangeContext == mpExchangeCtx, err = CHIP_ERROR_INCORRECT_STATE);
err = ProcessSubscribeResponse(std::move(aPayload));
// Forget the context as SUBSCRIBE RESPONSE is the last message in SUBSCRIBE transaction and
// ExchangeContext::HandleMessage automatically closes a context if no other messages need to
// be sent or received.
mpExchangeCtx = nullptr;
Damian-Nordic marked this conversation as resolved.
Show resolved Hide resolved
SuccessOrExit(err);
}
else
Expand Down
52 changes: 52 additions & 0 deletions src/app/tests/TestReadInteraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ class TestReadInteraction
static void TestProcessSubscribeRequest(nlTestSuite * apSuite, void * apContext);
static void TestReadRoundtrip(nlTestSuite * apSuite, void * apContext);
static void TestSubscribeRoundtrip(nlTestSuite * apSuite, void * apContext);
static void TestSubscribeEarlyShutdown(nlTestSuite * apSuite, void * apContext);
static void TestSubscribeInvalidAttributePathRoundtrip(nlTestSuite * apSuite, void * apContext);
static void TestReadInvalidAttributePathRoundtrip(nlTestSuite * apSuite, void * apContext);

Expand Down Expand Up @@ -1037,6 +1038,56 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a
engine->Shutdown();
}

// Verify that subscription can be shut down just after receiving SUBSCRIBE RESPONSE,
// before receiving any subsequent REPORT DATA.
void TestReadInteraction::TestSubscribeEarlyShutdown(nlTestSuite * apSuite, void * apContext)
{
TestContext & ctx = *static_cast<TestContext *>(apContext);
Messaging::ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr();
InteractionModelEngine & engine = *InteractionModelEngine::GetInstance();
MockInteractionModelApp delegate;

// Initialize Interaction Model Engine
NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0);
NL_TEST_ASSERT(apSuite, engine.Init(&ctx.GetExchangeManager(), &delegate) == CHIP_NO_ERROR);

// Subscribe to the attribute
AttributePathParams attributePathParams;
attributePathParams.mNodeId = chip::kTestDeviceNodeId;
attributePathParams.mEndpointId = kTestEndpointId;
attributePathParams.mClusterId = kTestClusterId;
attributePathParams.mFieldId = 1;
attributePathParams.mListIndex = 0;
attributePathParams.mFlags.Set(AttributePathParams::Flags::kFieldIdValid);

ReadPrepareParams readPrepareParams(ctx.GetSessionBobToAlice());
readPrepareParams.mpAttributePathParamsList = &attributePathParams;
readPrepareParams.mAttributePathParamsListSize = 1;
readPrepareParams.mMinIntervalFloorSeconds = 2;
readPrepareParams.mMaxIntervalCeilingSeconds = 5;
readPrepareParams.mKeepSubscriptions = false;

printf("Send subscribe request message to Node: %" PRIu64 "\n", chip::kTestDeviceNodeId);
NL_TEST_ASSERT(apSuite, engine.SendSubscribeRequest(readPrepareParams, &delegate) == CHIP_NO_ERROR);

engine.GetReportingEngine().Run();
NL_TEST_ASSERT(apSuite, delegate.mGotReport);
NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 1);
NL_TEST_ASSERT(apSuite, delegate.mNumSubscriptions == 1);
NL_TEST_ASSERT(apSuite, delegate.mpReadHandler != nullptr);

// Shutdown the subscription
uint64_t subscriptionId = 0;
delegate.mpReadHandler->GetSubscriptionId(subscriptionId);

NL_TEST_ASSERT(apSuite, subscriptionId != 0);
NL_TEST_ASSERT(apSuite, engine.ShutdownSubscription(subscriptionId) == CHIP_NO_ERROR);

// Cleanup
NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0);
engine.Shutdown();
}

void TestReadInteraction::TestSubscribeInvalidAttributePathRoundtrip(nlTestSuite * apSuite, void * apContext)
{
TestContext & ctx = *static_cast<TestContext *>(apContext);
Expand Down Expand Up @@ -1106,6 +1157,7 @@ const nlTest sTests[] =
NL_TEST_DEF("TestProcessSubscribeResponse", chip::app::TestReadInteraction::TestProcessSubscribeResponse),
NL_TEST_DEF("TestProcessSubscribeRequest", chip::app::TestReadInteraction::TestProcessSubscribeRequest),
NL_TEST_DEF("TestSubscribeRoundtrip", chip::app::TestReadInteraction::TestSubscribeRoundtrip),
NL_TEST_DEF("TestSubscribeEarlyShutdown", chip::app::TestReadInteraction::TestSubscribeEarlyShutdown),
NL_TEST_DEF("TestSubscribeInvalidAttributePathRoundtrip", chip::app::TestReadInteraction::TestSubscribeInvalidAttributePathRoundtrip),
NL_TEST_DEF("TestReadInvalidAttributePathRoundtrip", chip::app::TestReadInteraction::TestReadInvalidAttributePathRoundtrip),
NL_TEST_SENTINEL()
Expand Down