From 32626325315af54d3a42f8325c3067e9ed081e3d Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Mon, 19 Jul 2021 13:51:47 -0700 Subject: [PATCH] Add IM read event e2e test and fix the found bug (#8338) Summary of Changes: -- When generating report, we read event from debug priority to critical priority, we should read event from cirtical priority to debug priority. We add test to check the initial read events are from critical priority via providing critical and info event. Without this fix, the test would fail. -- During test, we see current report engine fail to handle event-only read request where it inserts empty attribute list, we rollback the empty eventlist if no attribute is there, without this fix, the test would fail -- Fix event number calculation and event number test. --- src/app/EventLoggingTypes.h | 1 + src/app/EventManagement.cpp | 5 +- src/app/EventManagement.h | 3 +- src/app/ReadHandler.cpp | 9 +- src/app/ReadHandler.h | 3 +- src/app/reporting/Engine.cpp | 39 ++-- src/app/tests/TestEventLogging.cpp | 9 +- src/app/tests/TestReadInteraction.cpp | 296 ++++++++++++++++++++------ 8 files changed, 273 insertions(+), 92 deletions(-) diff --git a/src/app/EventLoggingTypes.h b/src/app/EventLoggingTypes.h index 5bc0d45bb16c85..129a33550055c4 100644 --- a/src/app/EventLoggingTypes.h +++ b/src/app/EventLoggingTypes.h @@ -175,6 +175,7 @@ struct EventLoadOutContext Timestamp mPreviousSystemTime; Timestamp mCurrentSystemTime; EventNumber mCurrentEventNumber = 0; + size_t mEventCount = 0; Timestamp mCurrentUTCTime; ClusterInfo * mpInterestedEventPaths = nullptr; bool mFirst = true; diff --git a/src/app/EventManagement.cpp b/src/app/EventManagement.cpp index 3bf47ddee030c8..40b207bf692f2b 100644 --- a/src/app/EventManagement.cpp +++ b/src/app/EventManagement.cpp @@ -690,13 +690,14 @@ CHIP_ERROR EventManagement::CopyEventsSince(const TLVReader & aReader, size_t aD loadOutContext->mPreviousSystemTime.mValue = loadOutContext->mCurrentSystemTime.mValue; loadOutContext->mFirst = false; + loadOutContext->mEventCount++; } return err; } CHIP_ERROR EventManagement::FetchEventsSince(TLVWriter & aWriter, ClusterInfo * apClusterInfolist, PriorityLevel aPriority, - EventNumber & aEventNumber) + EventNumber & aEventNumber, size_t & aEventCount) { // TODO: Add particular set of event Paths in FetchEventsSince so that we can filter the interested paths CHIP_ERROR err = CHIP_NO_ERROR; @@ -729,7 +730,7 @@ CHIP_ERROR EventManagement::FetchEventsSince(TLVWriter & aWriter, ClusterInfo * exit: aEventNumber = context.mCurrentEventNumber; - + aEventCount += context.mEventCount; return err; } diff --git a/src/app/EventManagement.h b/src/app/EventManagement.h index 827bab7d5e828f..86c8e87eab3f9e 100644 --- a/src/app/EventManagement.h +++ b/src/app/EventManagement.h @@ -381,6 +381,7 @@ class EventManagement * completion, the event number of the last event * fetched. * + * @param[out] aEventCount The number of fetched event * @retval #CHIP_END_OF_TLV The function has reached the end of the * available log entries at the specified * priority level @@ -395,7 +396,7 @@ class EventManagement * */ CHIP_ERROR FetchEventsSince(chip::TLV::TLVWriter & aWriter, ClusterInfo * apClusterInfolist, PriorityLevel aPriority, - EventNumber & aEventNumber); + EventNumber & aEventNumber, size_t & aEventCount); /** * @brief diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 344fb01ad909cf..18081cd8240cdc 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -303,15 +303,16 @@ bool ReadHandler::CheckEventClean(EventManagement & aEventManager) { if (mCurrentPriority == PriorityLevel::Invalid) { - // Upload is not in middle, previous mLastScheduledEventNumber is not valid, Check for new events, and set a checkpoint - for (size_t index = 0; index < ArraySize(mSelfProcessedEvents); index++) + // Upload is not in middle, previous mLastScheduledEventNumber is not valid, Check for new events from Critical high + // priority to Debug low priority, and set a checkpoint when there is dirty events + for (int index = ArraySize(mSelfProcessedEvents) - 1; index >= 0; index--) { EventNumber lastEventNumber = aEventManager.GetLastEventNumber(static_cast(index)); if ((lastEventNumber != 0) && (lastEventNumber >= mSelfProcessedEvents[index])) { // We have more events. snapshot last event IDs aEventManager.SetScheduledEventEndpoint(&(mLastScheduledEventNumber[0])); - // initialize the next priority level to transfer + // initialize the next dirty priority level to transfer MoveToNextScheduledDirtyPriority(); return false; } @@ -329,7 +330,7 @@ bool ReadHandler::CheckEventClean(EventManagement & aEventManager) void ReadHandler::MoveToNextScheduledDirtyPriority() { - for (uint8_t i = 0; i < ArraySize(mSelfProcessedEvents); i++) + for (int i = ArraySize(mSelfProcessedEvents) - 1; i >= 0; i--) { if ((mLastScheduledEventNumber[i] != 0) && mSelfProcessedEvents[i] <= mLastScheduledEventNumber[i]) { diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h index 8218b228eb6c67..28e4ac77ca4432 100644 --- a/src/app/ReadHandler.h +++ b/src/app/ReadHandler.h @@ -111,7 +111,8 @@ class ReadHandler // sanpshotted last event, check with latest last event number, re-setup snapshoted checkpoint, and compare again. bool CheckEventClean(EventManagement & aEventManager); - // Move to the next dirty priority where last schedule event number is larger than current self vended event number + // Move to the next dirty priority from critical high priority to debug low priority, where last schedule event number + // is larger than current self vended event number void MoveToNextScheduledDirtyPriority(); private: diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index b931eb03c6df47..f367ca79062bb1 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -83,12 +83,15 @@ Engine::RetrieveClusterData(AttributeDataElement::Builder & aAttributeDataElemen return err; } -CHIP_ERROR Engine::BuildSingleReportDataAttributeDataList(ReportData::Builder & reportDataBuilder, ReadHandler * apReadHandler) +CHIP_ERROR Engine::BuildSingleReportDataAttributeDataList(ReportData::Builder & aReportDataBuilder, ReadHandler * apReadHandler) { - CHIP_ERROR err = CHIP_NO_ERROR; - ClusterInfo * clusterInfo = apReadHandler->GetAttributeClusterInfolist(); - AttributeDataList::Builder attributeDataList = reportDataBuilder.CreateAttributeDataListBuilder(); - SuccessOrExit(err = reportDataBuilder.GetError()); + CHIP_ERROR err = CHIP_NO_ERROR; + ClusterInfo * clusterInfo = apReadHandler->GetAttributeClusterInfolist(); + bool attributeClean = true; + TLV::TLVWriter backup; + aReportDataBuilder.Checkpoint(backup); + AttributeDataList::Builder attributeDataList = aReportDataBuilder.CreateAttributeDataListBuilder(); + SuccessOrExit(err = aReportDataBuilder.GetError()); // TODO: Need to handle multiple chunk of message while (clusterInfo != nullptr) { @@ -101,6 +104,7 @@ CHIP_ERROR Engine::BuildSingleReportDataAttributeDataList(ReportData::Builder & err = RetrieveClusterData(attributeDataElementBuilder, *clusterInfo); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(DataManagement, " Error retrieving data from cluster, aborting")); + attributeClean = false; } clusterInfo = clusterInfo->mpNext; @@ -109,14 +113,18 @@ CHIP_ERROR Engine::BuildSingleReportDataAttributeDataList(ReportData::Builder & err = attributeDataList.GetError(); exit: + if (attributeClean || err != CHIP_NO_ERROR) + { + aReportDataBuilder.Rollback(backup); + } ChipLogFunctError(err); return err; } CHIP_ERROR Engine::BuildSingleReportDataEventList(ReportData::Builder & aReportDataBuilder, ReadHandler * apReadHandler) { - CHIP_ERROR err = CHIP_NO_ERROR; - EventNumber eventCount = 0; + CHIP_ERROR err = CHIP_NO_ERROR; + size_t eventCount = 0; TLV::TLVWriter backup; bool eventClean = true; EventNumber initialEvents[kNumPriorityLevel]; @@ -125,10 +133,9 @@ CHIP_ERROR Engine::BuildSingleReportDataEventList(ReportData::Builder & aReportD EventManagement & eventManager = EventManagement::GetInstance(); EventList::Builder eventList; - VerifyOrExit(clusterInfoList != nullptr, ); - aReportDataBuilder.Checkpoint(backup); + VerifyOrExit(clusterInfoList != nullptr, ); VerifyOrExit(apReadHandler != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); eventList = aReportDataBuilder.CreateEventDataListBuilder(); @@ -153,7 +160,6 @@ CHIP_ERROR Engine::BuildSingleReportDataEventList(ReportData::Builder & aReportD // proceed only if there are new events. if (eventClean) { - aReportDataBuilder.Rollback(backup); ExitNow(); // Read clean, move along } @@ -161,7 +167,7 @@ CHIP_ERROR Engine::BuildSingleReportDataEventList(ReportData::Builder & aReportD { uint8_t priorityIndex = static_cast(apReadHandler->GetCurrentPriority()); err = eventManager.FetchEventsSince(*(eventList.GetWriter()), clusterInfoList, apReadHandler->GetCurrentPriority(), - eventNumberList[priorityIndex]); + eventNumberList[priorityIndex], eventCount); if ((err == CHIP_END_OF_TLV) || (err == CHIP_ERROR_TLV_UNDERRUN) || (err == CHIP_NO_ERROR)) { @@ -174,8 +180,6 @@ CHIP_ERROR Engine::BuildSingleReportDataEventList(ReportData::Builder & aReportD } else if ((err == CHIP_ERROR_BUFFER_TOO_SMALL) || (err == CHIP_ERROR_NO_MEMORY)) { - eventCount = CountEvents(apReadHandler, initialEvents); - // when first cluster event is too big to fit in the packet, ignore that cluster event. if (eventCount == 0) { @@ -210,15 +214,14 @@ CHIP_ERROR Engine::BuildSingleReportDataEventList(ReportData::Builder & aReportD eventList.EndOfEventList(); SuccessOrExit(err = eventList.GetError()); - eventCount = CountEvents(apReadHandler, initialEvents); - ChipLogDetail(DataManagement, "Fetched 0x" ChipLogFormatX64 " events", ChipLogValueX64(eventCount)); + ChipLogDetail(DataManagement, "Fetched %zu events", eventCount); exit: - if (err != CHIP_NO_ERROR) + if (err != CHIP_NO_ERROR || eventCount == 0 || eventClean) { - ChipLogError(DataManagement, "Error retrieving events, err = %" CHIP_ERROR_FORMAT, ChipError::FormatError(err)); + aReportDataBuilder.Rollback(backup); } - + ChipLogFunctError(err); return err; } diff --git a/src/app/tests/TestEventLogging.cpp b/src/app/tests/TestEventLogging.cpp index 003fae912bfd21..d3f668fa3337e2 100644 --- a/src/app/tests/TestEventLogging.cpp +++ b/src/app/tests/TestEventLogging.cpp @@ -149,17 +149,18 @@ static void CheckLogReadOut(nlTestSuite * apSuite, chip::app::EventManagement & CHIP_ERROR err; chip::TLV::TLVReader reader; chip::TLV::TLVWriter writer; + size_t eventCount = 0; uint8_t backingStore[1024]; - size_t elementCount; + size_t totalNumElements; writer.Init(backingStore, 1024); - err = alogMgmt.FetchEventsSince(writer, clusterInfo, priority, startingEventNumber); + err = alogMgmt.FetchEventsSince(writer, clusterInfo, priority, startingEventNumber, eventCount); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR || err == CHIP_END_OF_TLV); reader.Init(backingStore, writer.GetLengthWritten()); - err = chip::TLV::Utilities::Count(reader, elementCount, false); + err = chip::TLV::Utilities::Count(reader, totalNumElements, false); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(apSuite, elementCount == expectedNumEvents); + NL_TEST_ASSERT(apSuite, totalNumElements == expectedNumEvents && totalNumElements == eventCount); reader.Init(backingStore, writer.GetLengthWritten()); chip::TLV::Debug::Dump(reader, SimpleDumpWriter); } diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index d8f8a7359211fb..c1e2c18b159beb 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -23,6 +23,8 @@ */ #include +#include +#include #include #include #include @@ -30,26 +32,130 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include +#include +#include -#include +namespace { +chip::TransportMgrBase gTransportManager; +chip::Test::LoopbackTransport gLoopback; +chip::secure_channel::MessageCounterManager gMessageCounterManager; +uint8_t gDebugEventBuffer[128]; +uint8_t gInfoEventBuffer[128]; +uint8_t gCritEventBuffer[128]; +chip::app::CircularEventBuffer gCircularEventBuffer[3]; +chip::NodeId kTestNodeId = 1; +chip::ClusterId kTestClusterId = 6; +chip::EndpointId kTestEndpointId = 1; +chip::EventId kTestEventIdDebug = 1; +chip::EventId kTestEventIdCritical = 2; +uint64_t kTestEventTag = 1; +using TestContext = chip::Test::MessagingContext; +TestContext sContext; + +void InitializeEventLogging(chip::Messaging::ExchangeManager & aExchangeManager) +{ + chip::app::LogStorageResources logStorageResources[] = { + { &gDebugEventBuffer[0], sizeof(gDebugEventBuffer), nullptr, 0, nullptr, chip::app::PriorityLevel::Debug }, + { &gInfoEventBuffer[0], sizeof(gInfoEventBuffer), nullptr, 0, nullptr, chip::app::PriorityLevel::Info }, + { &gCritEventBuffer[0], sizeof(gCritEventBuffer), nullptr, 0, nullptr, chip::app::PriorityLevel::Critical }, + }; -namespace chip { -System::Layer gSystemLayer; -SecureSessionMgr gSessionManager; -Messaging::ExchangeManager gExchangeManager; -TransportMgr gTransportManager; -const Transport::AdminId gAdminId = 0; -secure_channel::MessageCounterManager gMessageCounterManager; + chip::app::EventManagement::CreateEventManagement(&aExchangeManager, ArraySize(logStorageResources), gCircularEventBuffer, + logStorageResources); +} + +class TestEventGenerator : public chip::app::EventLoggingDelegate +{ +public: + CHIP_ERROR WriteEvent(chip::TLV::TLVWriter & aWriter) + { + CHIP_ERROR err = CHIP_NO_ERROR; + err = aWriter.Put(kTestEventTag, mStatus); + return err; + } + + void SetStatus(int32_t aStatus) { mStatus = aStatus; } + +private: + int32_t mStatus; +}; + +void GenerateEvents(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + chip::EventNumber eid1, eid2; + chip::app::EventSchema schema1 = { kTestNodeId, kTestEndpointId, kTestClusterId, kTestEventIdDebug, + chip::app::PriorityLevel::Info }; + chip::app::EventSchema schema2 = { kTestNodeId, kTestEndpointId, kTestClusterId, kTestEventIdCritical, + chip::app::PriorityLevel::Critical }; + chip::app::EventOptions options1; + chip::app::EventOptions options2; + TestEventGenerator testEventGenerator; + + options1.mpEventSchema = &schema1; + options2.mpEventSchema = &schema2; + chip::app::EventManagement & logMgmt = chip::app::EventManagement::GetInstance(); + testEventGenerator.SetStatus(0); + err = logMgmt.LogEvent(&testEventGenerator, options1, eid1); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + testEventGenerator.SetStatus(1); + err = logMgmt.LogEvent(&testEventGenerator, options2, eid2); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); +} + +class MockInteractionModelApp : public chip::app::InteractionModelDelegate +{ +public: + CHIP_ERROR EventStreamReceived(const chip::Messaging::ExchangeContext * apExchangeContext, + chip::TLV::TLVReader * apEventListReader) override + { + CHIP_ERROR err = CHIP_NO_ERROR; + chip::TLV::TLVReader reader; + int numDataElementIndex = 0; + reader.Init(*apEventListReader); + while (CHIP_NO_ERROR == (err = reader.Next())) + { + uint8_t priorityLevel = 0; + chip::app::EventDataElement::Parser event; + ReturnErrorOnFailure(event.Init(reader)); + ReturnErrorOnFailure(event.GetPriorityLevel(&priorityLevel)); + if (numDataElementIndex == 0) + { + VerifyOrReturnError(priorityLevel == static_cast(chip::app::PriorityLevel::Critical), + CHIP_ERROR_INCORRECT_STATE); + } + else if (numDataElementIndex == 1) + { + VerifyOrReturnError(priorityLevel == static_cast(chip::app::PriorityLevel::Info), + CHIP_ERROR_INCORRECT_STATE); + } + ++numDataElementIndex; + } + if (CHIP_END_OF_TLV == err) + { + mGotEventResponse = true; + err = CHIP_NO_ERROR; + } + return err; + } + bool mGotEventResponse = false; +}; +} // namespace + +namespace chip { namespace app { class TestReadInteraction { @@ -62,6 +168,7 @@ class TestReadInteraction static void TestReadClientGenerateTwoEventPathList(nlTestSuite * apSuite, void * apContext); static void TestReadClientInvalidReport(nlTestSuite * apSuite, void * apContext); static void TestReadHandlerInvalidAttributePath(nlTestSuite * apSuite, void * apContext); + static void TestReadEventRoundtrip(nlTestSuite * apSuite, void * apContext); private: static void GenerateReportData(nlTestSuite * apSuite, void * apContext, System::PacketBufferHandle & aPayload, @@ -145,20 +252,20 @@ void TestReadInteraction::GenerateReportData(nlTestSuite * apSuite, void * apCon void TestReadInteraction::TestReadClient(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; - + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); app::ReadClient readClient; EventNumber eventNumber = 0; chip::app::InteractionModelDelegate delegate; System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); - err = readClient.Init(&gExchangeManager, &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - - err = readClient.SendReadRequest(kTestDeviceNodeId, gAdminId, nullptr /* apSecureSession */, nullptr /*apEventPathParamsList*/, + SecureSessionHandle session = ctx.GetSessionLocalToPeer(); + err = readClient.SendReadRequest(ctx.GetDestinationNodeId(), ctx.GetAdminId(), &session, nullptr /*apEventPathParamsList*/, 0 /*aEventPathParamsListSize*/, nullptr /*apAttributePathParamsList*/, 0 /*aAttributePathParamsListSize*/, eventNumber /*aEventNumber*/); - NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_NOT_CONNECTED); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); GenerateReportData(apSuite, apContext, buf); @@ -170,15 +277,18 @@ void TestReadInteraction::TestReadClient(nlTestSuite * apSuite, void * apContext void TestReadInteraction::TestReadHandler(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); app::ReadHandler readHandler; System::PacketBufferTLVWriter writer; System::PacketBufferHandle reportDatabuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); System::PacketBufferHandle readRequestbuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); ReadRequest::Builder readRequestBuilder; chip::app::InteractionModelDelegate delegate; - err = InteractionModelEngine::GetInstance()->Init(&gExchangeManager, &delegate); + auto * engine = chip::app::InteractionModelEngine::GetInstance(); + err = engine->Init(&ctx.GetExchangeManager(), &delegate); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + readHandler.Init(nullptr); GenerateReportData(apSuite, apContext, reportDatabuf); @@ -211,11 +321,14 @@ void TestReadInteraction::TestReadHandler(nlTestSuite * apSuite, void * apContex err = readHandler.OnReadRequest(nullptr, std::move(readRequestbuf)); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + engine->Shutdown(); } void TestReadInteraction::TestReadClientGenerateAttributePathList(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); app::ReadClient readClient; chip::app::InteractionModelDelegate delegate; System::PacketBufferHandle msgBuf; @@ -227,7 +340,7 @@ void TestReadInteraction::TestReadClientGenerateAttributePathList(nlTestSuite * err = request.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - err = readClient.Init(&gExchangeManager, &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); AttributePathParams attributePathParams[2]; @@ -240,7 +353,8 @@ void TestReadInteraction::TestReadClientGenerateAttributePathList(nlTestSuite * void TestReadInteraction::TestReadClientGenerateInvalidAttributePathList(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); app::ReadClient readClient; chip::app::InteractionModelDelegate delegate; System::PacketBufferHandle msgBuf; @@ -249,7 +363,7 @@ void TestReadInteraction::TestReadClientGenerateInvalidAttributePathList(nlTestS msgBuf = System::PacketBufferHandle::New(kMaxSecureSduLengthBytes); NL_TEST_ASSERT(apSuite, !msgBuf.IsNull()); writer.Init(std::move(msgBuf)); - err = readClient.Init(&gExchangeManager, &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); err = request.Init(&writer); @@ -264,20 +378,21 @@ void TestReadInteraction::TestReadClientGenerateInvalidAttributePathList(nlTestS void TestReadInteraction::TestReadClientInvalidReport(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; - + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); app::ReadClient readClient; chip::app::InteractionModelDelegate delegate; EventNumber eventNumber = 0; System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); - err = readClient.Init(&gExchangeManager, &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - err = readClient.SendReadRequest(kTestDeviceNodeId, gAdminId, nullptr /* apSecureSession */, nullptr /*apEventPathParamsList*/, + SecureSessionHandle session = ctx.GetSessionLocalToPeer(); + err = readClient.SendReadRequest(ctx.GetDestinationNodeId(), ctx.GetAdminId(), &session, nullptr /*apEventPathParamsList*/, 0 /*aEventPathParamsListSize*/, nullptr /*apAttributePathParamsList*/, 0 /*aAttributePathParamsListSize*/, eventNumber /*aEventNumber*/); - NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_NOT_CONNECTED); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); GenerateReportData(apSuite, apContext, buf, true /*aNeedInvalidReport*/); @@ -289,7 +404,8 @@ void TestReadInteraction::TestReadClientInvalidReport(nlTestSuite * apSuite, voi void TestReadInteraction::TestReadHandlerInvalidAttributePath(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); app::ReadHandler readHandler; System::PacketBufferTLVWriter writer; System::PacketBufferHandle reportDatabuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); @@ -297,7 +413,8 @@ void TestReadInteraction::TestReadHandlerInvalidAttributePath(nlTestSuite * apSu ReadRequest::Builder readRequestBuilder; chip::app::InteractionModelDelegate delegate; - err = InteractionModelEngine::GetInstance()->Init(&gExchangeManager, &delegate); + auto * engine = chip::app::InteractionModelEngine::GetInstance(); + err = engine->Init(&ctx.GetExchangeManager(), &delegate); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); readHandler.Init(nullptr); @@ -327,11 +444,13 @@ void TestReadInteraction::TestReadHandlerInvalidAttributePath(nlTestSuite * apSu err = readHandler.OnReadRequest(nullptr, std::move(readRequestbuf)); NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + engine->Shutdown(); } void TestReadInteraction::TestReadClientGenerateOneEventPathList(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); app::ReadClient readClient; chip::app::InteractionModelDelegate delegate; System::PacketBufferHandle msgBuf; @@ -344,7 +463,7 @@ void TestReadInteraction::TestReadClientGenerateOneEventPathList(nlTestSuite * a err = request.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - err = readClient.Init(&gExchangeManager, &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); chip::app::EventPathParams eventPathParams[2]; @@ -379,7 +498,8 @@ void TestReadInteraction::TestReadClientGenerateOneEventPathList(nlTestSuite * a void TestReadInteraction::TestReadClientGenerateTwoEventPathList(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + TestContext & ctx = *static_cast(apContext); app::ReadClient readClient; chip::app::InteractionModelDelegate delegate; System::PacketBufferHandle msgBuf; @@ -392,7 +512,7 @@ void TestReadInteraction::TestReadClientGenerateTwoEventPathList(nlTestSuite * a err = request.Init(&writer); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - err = readClient.Init(&gExchangeManager, &delegate, 0 /* application identifier */); + err = readClient.Init(&ctx.GetExchangeManager(), &delegate, 0 /* application identifier */); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); chip::app::EventPathParams eventPathParams[2]; @@ -429,36 +549,54 @@ void TestReadInteraction::TestReadClientGenerateTwoEventPathList(nlTestSuite * a #endif } -} // namespace app -} // namespace chip - -namespace { - -void InitializeChip(nlTestSuite * apSuite) +void TestReadInteraction::TestReadEventRoundtrip(nlTestSuite * apSuite, void * apContext) { - CHIP_ERROR err = CHIP_NO_ERROR; - chip::Optional peer(chip::Transport::Type::kUndefined); - chip::Transport::AdminPairingTable admins; - chip::Transport::AdminPairingInfo * adminInfo = admins.AssignAdminId(chip::gAdminId, chip::kTestDeviceNodeId); + TestContext & ctx = *static_cast(apContext); + CHIP_ERROR err = CHIP_NO_ERROR; - NL_TEST_ASSERT(apSuite, adminInfo != nullptr); + Messaging::ReliableMessageMgr * rm = ctx.GetExchangeManager().GetReliableMessageMgr(); + // Shouldn't have anything in the retransmit table when starting the test. + NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0); - err = chip::Platform::MemoryInit(); + GenerateEvents(apSuite, apContext); + + MockInteractionModelApp delegate; + auto * engine = chip::app::InteractionModelEngine::GetInstance(); + err = engine->Init(&ctx.GetExchangeManager(), &delegate); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(apSuite, !delegate.mGotEventResponse); - chip::gSystemLayer.Init(); + chip::app::EventPathParams eventPathParams[2]; + eventPathParams[0].mNodeId = kTestNodeId; + eventPathParams[0].mEndpointId = kTestEndpointId; + eventPathParams[0].mClusterId = kTestClusterId; + eventPathParams[0].mEventId = kTestEventIdDebug; - err = chip::gSessionManager.Init(chip::kTestDeviceNodeId, &chip::gSystemLayer, &chip::gTransportManager, &admins, - &chip::gMessageCounterManager); - NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + eventPathParams[1].mNodeId = kTestNodeId; + eventPathParams[1].mEndpointId = kTestEndpointId; + eventPathParams[1].mClusterId = kTestClusterId; + eventPathParams[1].mEventId = kTestEventIdCritical; - err = chip::gExchangeManager.Init(&chip::gSessionManager); + SecureSessionHandle session = ctx.GetSessionLocalToPeer(); + err = chip::app::InteractionModelEngine::GetInstance()->SendReadRequest(ctx.GetDestinationNodeId(), ctx.GetAdminId(), &session, + eventPathParams, 2, nullptr, 1, 0); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - err = chip::gMessageCounterManager.Init(&chip::gExchangeManager); - NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + InteractionModelEngine::GetInstance()->GetReportingEngine().Run(); + NL_TEST_ASSERT(apSuite, delegate.mGotEventResponse); + + // By now we should have closed all exchanges and sent all pending acks, so + // there should be no queued-up things in the retransmit table. + NL_TEST_ASSERT(apSuite, rm->TestGetCountRetransTable() == 0); + + engine->Shutdown(); } +} // namespace app +} // namespace chip + +namespace { + /** * Test Suite. It lists all the test functions. */ @@ -466,6 +604,7 @@ void InitializeChip(nlTestSuite * apSuite) // clang-format off const nlTest sTests[] = { + NL_TEST_DEF("TestReadEventRoundtrip", chip::app::TestReadInteraction::TestReadEventRoundtrip), NL_TEST_DEF("CheckReadClient", chip::app::TestReadInteraction::TestReadClient), NL_TEST_DEF("CheckReadHandler", chip::app::TestReadInteraction::TestReadHandler), NL_TEST_DEF("TestReadClientGenerateAttributePathList", chip::app::TestReadInteraction::TestReadClientGenerateAttributePathList), @@ -478,25 +617,58 @@ const nlTest sTests[] = }; // clang-format on -} // namespace +int Initialize(void * aContext); +int Finalize(void * aContext); -int TestReadInteraction() +// clang-format off +nlTestSuite sSuite = { - // clang-format off - nlTestSuite theSuite = - { "TestReadInteraction", &sTests[0], - nullptr, - nullptr - }; - // clang-format on + Initialize, + Finalize +}; +// clang-format on - InitializeChip(&theSuite); +int Initialize(void * aContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + // Initialize System memory and resources + err = chip::Platform::MemoryInit(); + if (err != CHIP_NO_ERROR) + { + return FAILURE; + } + + gTransportManager.Init(&gLoopback); - nlTestRunner(&theSuite, nullptr); + auto * ctx = static_cast(aContext); + err = ctx->Init(&sSuite, &gTransportManager); + if (err != CHIP_NO_ERROR) + { + return FAILURE; + } + + InitializeEventLogging(ctx->GetExchangeManager()); + gTransportManager.SetSecureSessionMgr(&ctx->GetSecureSessionManager()); + return SUCCESS; +} + +int Finalize(void * aContext) +{ + CHIP_ERROR err = reinterpret_cast(aContext)->Shutdown(); + chip::Platform::MemoryShutdown(); + chip::app::EventManagement::DestroyEventManagement(); + return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE; +} + +} // namespace + +int TestReadInteraction() +{ + nlTestRunner(&sSuite, &sContext); - return (nlTestRunnerStats(&theSuite)); + return (nlTestRunnerStats(&sSuite)); } CHIP_REGISTER_TEST_SUITE(TestReadInteraction)