diff --git a/src/app/tests/AppTestContext.cpp b/src/app/tests/AppTestContext.cpp index ff1154dafbb306..ecf4aff9bf7c40 100644 --- a/src/app/tests/AppTestContext.cpp +++ b/src/app/tests/AppTestContext.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include +#include "AppTestContext.h" #include #include @@ -40,11 +40,10 @@ namespace Test { void AppContext::SetUpTestSuite() { - CHIP_ERROR err = CHIP_NO_ERROR; LoopbackMessagingContext::SetUpTestSuite(); - // TODO: use ASSERT_EQ, once transition to pw_unit_test is complete - VerifyOrDieWithMsg((err = chip::DeviceLayer::PlatformMgr().InitChipStack()) == CHIP_NO_ERROR, AppServer, - "Init CHIP stack failed: %" CHIP_ERROR_FORMAT, err.Format()); + VerifyOrReturn(!HasFailure()); // Stop if parent had a failure. + + ASSERT_EQ(chip::DeviceLayer::PlatformMgr().InitChipStack(), CHIP_NO_ERROR); } void AppContext::TearDownTestSuite() @@ -67,17 +66,15 @@ void AppContext::TearDownTestSuite() void AppContext::SetUp() { - CHIP_ERROR err = CHIP_NO_ERROR; LoopbackMessagingContext::SetUp(); - // TODO: use ASSERT_EQ, once transition to pw_unit_test is complete - VerifyOrDieWithMsg((err = app::InteractionModelEngine::GetInstance()->Init(&GetExchangeManager(), &GetFabricTable(), - app::reporting::GetDefaultReportScheduler())) == - CHIP_NO_ERROR, - AppServer, "Init InteractionModelEngine failed: %" CHIP_ERROR_FORMAT, err.Format()); + VerifyOrReturn(!HasFailure()); // Stop if parent had a failure. + + ASSERT_EQ(app::InteractionModelEngine::GetInstance()->Init(&GetExchangeManager(), &GetFabricTable(), + app::reporting::GetDefaultReportScheduler()), + CHIP_NO_ERROR); Access::SetAccessControl(gPermissiveAccessControl); - VerifyOrDieWithMsg((err = Access::GetAccessControl().Init(chip::Access::Examples::GetPermissiveAccessControlDelegate(), - gDeviceTypeResolver)) == CHIP_NO_ERROR, - AppServer, "Init AccessControl failed: %" CHIP_ERROR_FORMAT, err.Format()); + ASSERT_EQ(Access::GetAccessControl().Init(chip::Access::Examples::GetPermissiveAccessControlDelegate(), gDeviceTypeResolver), + CHIP_NO_ERROR); } void AppContext::TearDown() @@ -85,6 +82,7 @@ void AppContext::TearDown() Access::GetAccessControl().Finish(); Access::ResetAccessControlToDefault(); chip::app::InteractionModelEngine::GetInstance()->Shutdown(); + LoopbackMessagingContext::TearDown(); } diff --git a/src/app/tests/AppTestContext.h b/src/app/tests/AppTestContext.h index a2fe3387d2d7aa..c05e490fb9e6aa 100644 --- a/src/app/tests/AppTestContext.h +++ b/src/app/tests/AppTestContext.h @@ -32,9 +32,9 @@ class AppContext : public LoopbackMessagingContext // Performs shared teardown for all tests in the test suite static void TearDownTestSuite(); // Performs setup for each individual test in the test suite - void SetUp(); + virtual void SetUp(); // Performs teardown for each individual test in the test suite - void TearDown(); + virtual void TearDown(); }; } // namespace Test diff --git a/src/controller/tests/TestEventCaching.cpp b/src/controller/tests/TestEventCaching.cpp index b4c262725f74d3..e31e3ed358b6f0 100644 --- a/src/controller/tests/TestEventCaching.cpp +++ b/src/controller/tests/TestEventCaching.cpp @@ -16,8 +16,6 @@ * limitations under the License. */ -#include - #include "app-common/zap-generated/ids/Attributes.h" #include "app-common/zap-generated/ids/Clusters.h" #include "app/ClusterStateCache.h" @@ -37,7 +35,6 @@ #include #include #include -#include using namespace chip; using namespace chip::app; @@ -50,8 +47,6 @@ static uint8_t gInfoEventBuffer[4096]; static uint8_t gCritEventBuffer[4096]; static chip::app::CircularEventBuffer gCircularEventBuffer[3]; -using TestContext = chip::Test::AppContext; - // // The generated endpoint_config for the controller app has Endpoint 1 // already used in the fixed endpoint set of size 1. Consequently, let's use the next @@ -59,33 +54,10 @@ using TestContext = chip::Test::AppContext; // constexpr EndpointId kTestEndpointId = 2; -class TestEventCaching : public ::testing::Test +class TestEventCaching : public Test::AppContext { -public: - // Performs shared setup for all tests in the test suite - static void SetUpTestSuite() - { - if (mpContext == nullptr) - { - mpContext = new TestContext(); - ASSERT_NE(mpContext, nullptr); - } - mpContext->SetUpTestSuite(); - } - - // Performs shared teardown for all tests in the test suite - static void TearDownTestSuite() - { - mpContext->TearDownTestSuite(); - if (mpContext != nullptr) - { - delete mpContext; - mpContext = nullptr; - } - } - protected: - // Performs setup for each test in the suite + // Performs setup for each test in the suite. Run once for each test function. void SetUp() { const chip::app::LogStorageResources logStorageResources[] = { @@ -94,29 +66,24 @@ class TestEventCaching : public ::testing::Test { &gCritEventBuffer[0], sizeof(gCritEventBuffer), chip::app::PriorityLevel::Critical }, }; - mpContext->SetUp(); + AppContext::SetUp(); // Call parent. + VerifyOrReturn(!HasFailure()); // Stop if parent had a failure. - CHIP_ERROR err = CHIP_NO_ERROR; - // TODO: use ASSERT_EQ, once transition to pw_unit_test is complete - VerifyOrDieWithMsg((err = mEventCounter.Init(0)) == CHIP_NO_ERROR, AppServer, - "Init EventCounter failed: %" CHIP_ERROR_FORMAT, err.Format()); - chip::app::EventManagement::CreateEventManagement(&mpContext->GetExchangeManager(), ArraySize(logStorageResources), + ASSERT_EQ(mEventCounter.Init(0), CHIP_NO_ERROR); + chip::app::EventManagement::CreateEventManagement(&GetExchangeManager(), ArraySize(logStorageResources), gCircularEventBuffer, logStorageResources, &mEventCounter); } - // Performs teardown for each test in the suite + // Performs teardown for each test in the suite. Run once for each test function. void TearDown() { chip::app::EventManagement::DestroyEventManagement(); - mpContext->TearDown(); + AppContext::TearDown(); // Call parent. } - static TestContext * mpContext; - private: MonotonicallyIncreasingCounter mEventCounter; }; -TestContext * TestEventCaching::mpContext = nullptr; //clang-format off DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(testClusterAttrs) @@ -179,7 +146,7 @@ void GenerateEvents(chip::EventNumber & firstEventNumber, chip::EventNumber & la */ TEST_F(TestEventCaching, TestBasicCaching) { - auto sessionHandle = mpContext->GetSessionBobToAlice(); + auto sessionHandle = GetSessionBobToAlice(); app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic @@ -207,12 +174,12 @@ TEST_F(TestEventCaching, TestBasicCaching) TestReadCallback readCallback; { - app::ReadClient readClient(engine, &mpContext->GetExchangeManager(), - readCallback.mClusterCacheAdapter.GetBufferedCallback(), app::ReadClient::InteractionType::Read); + app::ReadClient readClient(engine, &GetExchangeManager(), readCallback.mClusterCacheAdapter.GetBufferedCallback(), + app::ReadClient::InteractionType::Read); EXPECT_EQ(readClient.SendRequest(readParams), CHIP_NO_ERROR); - mpContext->DrainAndServiceIO(); + DrainAndServiceIO(); uint8_t generationCount = 0; readCallback.mClusterCacheAdapter.ForEachEventData( @@ -340,12 +307,12 @@ TEST_F(TestEventCaching, TestBasicCaching) GenerateEvents(firstEventNumber, lastEventNumber); { - app::ReadClient readClient(engine, &mpContext->GetExchangeManager(), - readCallback.mClusterCacheAdapter.GetBufferedCallback(), app::ReadClient::InteractionType::Read); + app::ReadClient readClient(engine, &GetExchangeManager(), readCallback.mClusterCacheAdapter.GetBufferedCallback(), + app::ReadClient::InteractionType::Read); EXPECT_EQ(readClient.SendRequest(readParams), CHIP_NO_ERROR); - mpContext->DrainAndServiceIO(); + DrainAndServiceIO(); // // Validate that we still have all 5 of the old events we received, as well as the new ones that just got generated. @@ -392,8 +359,8 @@ TEST_F(TestEventCaching, TestBasicCaching) // we don't receive events lower than that value. // { - app::ReadClient readClient(engine, &mpContext->GetExchangeManager(), - readCallback.mClusterCacheAdapter.GetBufferedCallback(), app::ReadClient::InteractionType::Read); + app::ReadClient readClient(engine, &GetExchangeManager(), readCallback.mClusterCacheAdapter.GetBufferedCallback(), + app::ReadClient::InteractionType::Read); readCallback.mClusterCacheAdapter.ClearEventCache(); constexpr EventNumber kLastSeenEventNumber = 3; @@ -405,7 +372,7 @@ TEST_F(TestEventCaching, TestBasicCaching) EXPECT_EQ(readClient.SendRequest(readParams), CHIP_NO_ERROR); - mpContext->DrainAndServiceIO(); + DrainAndServiceIO(); // We should only get events with event numbers larger than kHighestEventNumberSeen. EXPECT_EQ(readCallback.mEventsSeen, lastEventNumber - kLastSeenEventNumber); @@ -441,12 +408,12 @@ TEST_F(TestEventCaching, TestBasicCaching) { readParams.mEventNumber.SetValue(5); - app::ReadClient readClient(engine, &mpContext->GetExchangeManager(), - readCallback.mClusterCacheAdapter.GetBufferedCallback(), app::ReadClient::InteractionType::Read); + app::ReadClient readClient(engine, &GetExchangeManager(), readCallback.mClusterCacheAdapter.GetBufferedCallback(), + app::ReadClient::InteractionType::Read); readCallback.mClusterCacheAdapter.ClearEventCache(true); EXPECT_EQ(readClient.SendRequest(readParams), CHIP_NO_ERROR); - mpContext->DrainAndServiceIO(); + DrainAndServiceIO(); // // Validate that we would receive 5 events @@ -474,7 +441,7 @@ TEST_F(TestEventCaching, TestBasicCaching) EXPECT_TRUE(highestEventNumber.HasValue() && highestEventNumber.Value() == 9); } - EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); emberAfClearDynamicEndpoint(0); } diff --git a/src/controller/tests/TestWriteChunking.cpp b/src/controller/tests/TestWriteChunking.cpp index 60be2212aa00e8..5059b8eb40f2ac 100644 --- a/src/controller/tests/TestWriteChunking.cpp +++ b/src/controller/tests/TestWriteChunking.cpp @@ -19,8 +19,6 @@ #include #include -#include - #include "app-common/zap-generated/ids/Attributes.h" #include "app-common/zap-generated/ids/Clusters.h" #include "app/ConcreteAttributePath.h" @@ -40,7 +38,6 @@ #include #include -using TestContext = chip::Test::AppContext; using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; @@ -62,41 +59,39 @@ constexpr uint32_t kTestListLength = 5; // We don't really care about the content, we just need a buffer. uint8_t sByteSpanData[app::kMaxSecureSduLengthBytes]; -class TestWriteChunking : public ::testing::Test +class TestWriteChunking : public Test::AppContext { -public: - // Performs shared setup for all tests in the test suite - static void SetUpTestSuite() - { - if (mpContext == nullptr) - { - mpContext = new TestContext(); - ASSERT_NE(mpContext, nullptr); - } - mpContext->SetUpTestSuite(); - } +private: + using PathStatus = std::pair; - // Performs shared teardown for all tests in the test suite - static void TearDownTestSuite() +protected: + enum class Operations : uint8_t { - mpContext->TearDownTestSuite(); - if (mpContext != nullptr) - { - delete mpContext; - mpContext = nullptr; - } - } + kNoop, + kShutdownWriteClient, + }; -protected: - // Performs setup for each test in the suite - void SetUp() { mpContext->SetUp(); } + enum class ListData : uint8_t + { + kNull, + kList, + kBadValue, + }; - // Performs teardown for each test in the suite - void TearDown() { mpContext->TearDown(); } + struct Instructions + { + // The paths used in write request + std::vector paths; + // The type of content of the list, it should be an empty vector or its size should equals to the list of paths. + std::vector data; + // operations on OnListWriteBegin and OnListWriteEnd on the server side. + std::function onListWriteBeginActions; + // The expected status when OnListWriteEnd is called. In the same order as paths + std::vector expectedStatus; + }; - static TestContext * mpContext; + void RunTest(Instructions instructions); }; -TestContext * TestWriteChunking::mpContext = nullptr; //clang-format off DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(testClusterAttrsOnEndpoint) @@ -211,7 +206,7 @@ CHIP_ERROR TestAttrAccess::Write(const app::ConcreteDataAttributePath & aPath, a */ TEST_F(TestWriteChunking, TestListChunking) { - auto sessionHandle = mpContext->GetSessionBobToAlice(); + auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic InitDataModelHandler(); @@ -238,7 +233,7 @@ TEST_F(TestWriteChunking, TestListChunking) gIterationCount = i; - app::WriteClient writeClient(&mpContext->GetExchangeManager(), &writeCallback, Optional::Missing(), + app::WriteClient writeClient(&GetExchangeManager(), &writeCallback, Optional::Missing(), static_cast(minReservationSize + i) /* reserved buffer size */); ByteSpan list[kTestListLength]; @@ -256,14 +251,14 @@ TEST_F(TestWriteChunking, TestListChunking) // for (int j = 0; j < 10 && writeCallback.mOnDoneCount == 0; j++) { - mpContext->DrainAndServiceIO(); + DrainAndServiceIO(); } EXPECT_EQ(writeCallback.mSuccessCount, kTestListLength + 1 /* an extra item for the empty list at the beginning */); EXPECT_EQ(writeCallback.mErrorCount, 0u); EXPECT_EQ(writeCallback.mOnDoneCount, 1u); - EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); // // Stop the test if we detected an error. Otherwise, it'll be difficult to read the logs. @@ -281,7 +276,7 @@ TEST_F(TestWriteChunking, TestListChunking) // As the actual overhead may change, we will test over a few possible payload lengths, from 850 to MTU used in write clients. TEST_F(TestWriteChunking, TestBadChunking) { - auto sessionHandle = mpContext->GetSessionBobToAlice(); + auto sessionHandle = GetSessionBobToAlice(); bool atLeastOneRequestSent = false; bool atLeastOneRequestFailed = false; @@ -306,7 +301,7 @@ TEST_F(TestWriteChunking, TestBadChunking) gIterationCount = (uint32_t) i; - app::WriteClient writeClient(&mpContext->GetExchangeManager(), &writeCallback, Optional::Missing()); + app::WriteClient writeClient(&GetExchangeManager(), &writeCallback, Optional::Missing()); ByteSpan list[kTestListLength]; for (auto & item : list) @@ -335,14 +330,14 @@ TEST_F(TestWriteChunking, TestBadChunking) // for (int j = 0; j < 10 && writeCallback.mOnDoneCount == 0; j++) { - mpContext->DrainAndServiceIO(); + DrainAndServiceIO(); } EXPECT_EQ(writeCallback.mSuccessCount, kTestListLength + 1 /* an extra item for the empty list at the beginning */); EXPECT_EQ(writeCallback.mErrorCount, 0u); EXPECT_EQ(writeCallback.mOnDoneCount, 1u); - EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); // // Stop the test if we detected an error. Otherwise, it'll be difficult to read the logs. @@ -352,7 +347,7 @@ TEST_F(TestWriteChunking, TestBadChunking) break; } } - EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); EXPECT_TRUE(atLeastOneRequestSent && atLeastOneRequestFailed); emberAfClearDynamicEndpoint(0); } @@ -363,7 +358,7 @@ TEST_F(TestWriteChunking, TestBadChunking) */ TEST_F(TestWriteChunking, TestConflictWrite) { - auto sessionHandle = mpContext->GetSessionBobToAlice(); + auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic InitDataModelHandler(); @@ -380,11 +375,11 @@ TEST_F(TestWriteChunking, TestConflictWrite) constexpr size_t kReserveSize = kMaxSecureSduLengthBytes - 128; TestWriteCallback writeCallback1; - app::WriteClient writeClient1(&mpContext->GetExchangeManager(), &writeCallback1, Optional::Missing(), + app::WriteClient writeClient1(&GetExchangeManager(), &writeCallback1, Optional::Missing(), static_cast(kReserveSize)); TestWriteCallback writeCallback2; - app::WriteClient writeClient2(&mpContext->GetExchangeManager(), &writeCallback2, Optional::Missing(), + app::WriteClient writeClient2(&GetExchangeManager(), &writeCallback2, Optional::Missing(), static_cast(kReserveSize)); ByteSpan list[kTestListLength]; @@ -402,7 +397,7 @@ TEST_F(TestWriteChunking, TestConflictWrite) err = writeClient2.SendWriteRequest(sessionHandle); EXPECT_EQ(err, CHIP_NO_ERROR); - mpContext->DrainAndServiceIO(); + DrainAndServiceIO(); { const TestWriteCallback * writeCallbackRef1 = &writeCallback1; @@ -426,7 +421,7 @@ TEST_F(TestWriteChunking, TestConflictWrite) EXPECT_EQ(writeCallbackRef2->mOnDoneCount, 1u); } - EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); emberAfClearDynamicEndpoint(0); } @@ -437,7 +432,7 @@ TEST_F(TestWriteChunking, TestConflictWrite) */ TEST_F(TestWriteChunking, TestNonConflictWrite) { - auto sessionHandle = mpContext->GetSessionBobToAlice(); + auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic InitDataModelHandler(); @@ -455,11 +450,11 @@ TEST_F(TestWriteChunking, TestNonConflictWrite) constexpr size_t kReserveSize = kMaxSecureSduLengthBytes - 128; TestWriteCallback writeCallback1; - app::WriteClient writeClient1(&mpContext->GetExchangeManager(), &writeCallback1, Optional::Missing(), + app::WriteClient writeClient1(&GetExchangeManager(), &writeCallback1, Optional::Missing(), static_cast(kReserveSize)); TestWriteCallback writeCallback2; - app::WriteClient writeClient2(&mpContext->GetExchangeManager(), &writeCallback2, Optional::Missing(), + app::WriteClient writeClient2(&GetExchangeManager(), &writeCallback2, Optional::Missing(), static_cast(kReserveSize)); ByteSpan list[kTestListLength]; @@ -477,7 +472,7 @@ TEST_F(TestWriteChunking, TestNonConflictWrite) err = writeClient2.SendWriteRequest(sessionHandle); EXPECT_EQ(err, CHIP_NO_ERROR); - mpContext->DrainAndServiceIO(); + DrainAndServiceIO(); { EXPECT_EQ(writeCallback1.mErrorCount, 0u); @@ -489,48 +484,19 @@ TEST_F(TestWriteChunking, TestNonConflictWrite) EXPECT_EQ(writeCallback2.mOnDoneCount, 1u); } - EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); emberAfClearDynamicEndpoint(0); } -namespace TestTransactionalListInstructions { - -using PathStatus = std::pair; - -enum class Operations : uint8_t -{ - kNoop, - kShutdownWriteClient, -}; - -enum class ListData : uint8_t -{ - kNull, - kList, - kBadValue, -}; - -struct Instructions -{ - // The paths used in write request - std::vector paths; - // The type of content of the list, it should be an empty vector or its size should equals to the list of paths. - std::vector data; - // operations on OnListWriteBegin and OnListWriteEnd on the server side. - std::function onListWriteBeginActions; - // The expected status when OnListWriteEnd is called. In the same order as paths - std::vector expectedStatus; -}; - -void RunTest(TestContext * pContext, Instructions instructions) +void TestWriteChunking::RunTest(Instructions instructions) { CHIP_ERROR err = CHIP_NO_ERROR; - auto sessionHandle = pContext->GetSessionBobToAlice(); + auto sessionHandle = GetSessionBobToAlice(); TestWriteCallback writeCallback; std::unique_ptr writeClient = std::make_unique( - &pContext->GetExchangeManager(), &writeCallback, Optional::Missing(), + &GetExchangeManager(), &writeCallback, Optional::Missing(), static_cast(kMaxSecureSduLengthBytes - 128) /* use a smaller chunk so we only need a few attributes in the write request. */); @@ -598,9 +564,9 @@ void RunTest(TestContext * pContext, Instructions instructions) err = writeClient->SendWriteRequest(sessionHandle); EXPECT_EQ(err, CHIP_NO_ERROR); - pContext->GetIOContext().DriveIOUntil(sessionHandle->ComputeRoundTripTimeout(app::kExpectedIMProcessingTime) + - System::Clock::Seconds16(1), - [&]() { return pContext->GetExchangeManager().GetNumActiveExchanges() == 0; }); + GetIOContext().DriveIOUntil(sessionHandle->ComputeRoundTripTimeout(app::kExpectedIMProcessingTime) + + System::Clock::Seconds16(1), + [&]() { return GetExchangeManager().GetNumActiveExchanges() == 0; }); EXPECT_EQ(onGoingPath, app::ConcreteAttributePath()); EXPECT_EQ(status.size(), instructions.expectedStatus.size()); @@ -614,12 +580,8 @@ void RunTest(TestContext * pContext, Instructions instructions) testServer.mOnListWriteEnd = nullptr; } -} // namespace TestTransactionalListInstructions - TEST_F(TestWriteChunking, TestTransactionalList) { - using namespace TestTransactionalListInstructions; - // Initialize the ember side server logic InitDataModelHandler(); @@ -631,98 +593,88 @@ TEST_F(TestWriteChunking, TestTransactionalList) // Test 1: we should receive transaction notifications ChipLogProgress(Zcl, "Test 1: we should receive transaction notifications"); - RunTest(mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, - .expectedStatus = { true }, - }); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, + .expectedStatus = { true }, + }); ChipLogProgress(Zcl, "Test 2: we should receive transaction notifications for incomplete list operations"); - RunTest( - mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, - .onListWriteBeginActions = [&](const app::ConcreteAttributePath & aPath) { return Operations::kShutdownWriteClient; }, - .expectedStatus = { false }, - }); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, + .onListWriteBeginActions = [&](const app::ConcreteAttributePath & aPath) { return Operations::kShutdownWriteClient; }, + .expectedStatus = { false }, + }); ChipLogProgress(Zcl, "Test 3: we should receive transaction notifications for every list in the transaction"); - RunTest(mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), - ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute2) }, - .expectedStatus = { true, true }, - }); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), + ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute2) }, + .expectedStatus = { true, true }, + }); ChipLogProgress(Zcl, "Test 4: we should receive transaction notifications with the status of each list"); - RunTest(mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), - ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute2) }, - .onListWriteBeginActions = - [&](const app::ConcreteAttributePath & aPath) { - if (aPath.mAttributeId == kTestListAttribute2) - { - return Operations::kShutdownWriteClient; - } - return Operations::kNoop; - }, - .expectedStatus = { true, false }, - }); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), + ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute2) }, + .onListWriteBeginActions = + [&](const app::ConcreteAttributePath & aPath) { + if (aPath.mAttributeId == kTestListAttribute2) + { + return Operations::kShutdownWriteClient; + } + return Operations::kNoop; + }, + .expectedStatus = { true, false }, + }); ChipLogProgress(Zcl, "Test 5: transactional list callbacks will be called for nullable lists, test if it is handled correctly for " "null value before non null values"); - RunTest(mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), - ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, - .data = { ListData::kNull, ListData::kList }, - .expectedStatus = { true }, - }); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), + ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, + .data = { ListData::kNull, ListData::kList }, + .expectedStatus = { true }, + }); ChipLogProgress(Zcl, "Test 6: transactional list callbacks will be called for nullable lists, test if it is handled correctly for " "null value after non null values"); - RunTest(mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), - ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, - .data = { ListData::kList, ListData::kNull }, - .expectedStatus = { true }, - }); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), + ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, + .data = { ListData::kList, ListData::kNull }, + .expectedStatus = { true }, + }); ChipLogProgress(Zcl, "Test 7: transactional list callbacks will be called for nullable lists, test if it is handled correctly for " "null value between non null values"); - RunTest(mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), - ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), - ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, - .data = { ListData::kList, ListData::kNull, ListData::kList }, - .expectedStatus = { true }, - }); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), + ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute), + ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, + .data = { ListData::kList, ListData::kNull, ListData::kList }, + .expectedStatus = { true }, + }); ChipLogProgress(Zcl, "Test 8: transactional list callbacks will be called for nullable lists"); - RunTest(mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, - .data = { ListData::kNull }, - .expectedStatus = { true }, - }); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, + .data = { ListData::kNull }, + .expectedStatus = { true }, + }); ChipLogProgress(Zcl, "Test 9: for nullable lists, we should receive notifications for unsuccessful writes when non-fatal occurred " "during processing the requests"); - RunTest(mpContext, - Instructions{ - .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, - .data = { ListData::kBadValue }, - .expectedStatus = { false }, - }); - - EXPECT_EQ(mpContext->GetExchangeManager().GetNumActiveExchanges(), 0u); + RunTest(Instructions{ + .paths = { ConcreteAttributePath(kTestEndpointId, Clusters::UnitTesting::Id, kTestListAttribute) }, + .data = { ListData::kBadValue }, + .expectedStatus = { false }, + }); + + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); emberAfClearDynamicEndpoint(0); } diff --git a/src/messaging/tests/MessagingContext.cpp b/src/messaging/tests/MessagingContext.cpp index 909bc90f443575..14ef27f147b624 100644 --- a/src/messaging/tests/MessagingContext.cpp +++ b/src/messaging/tests/MessagingContext.cpp @@ -302,9 +302,9 @@ Messaging::ExchangeContext * MessagingContext::NewExchangeToBob(Messaging::Excha return mExchangeManager.NewContext(GetSessionAliceToBob(), delegate, isInitiator); } -LoopbackTransportManager LoopbackMessagingContext::sLoopbackTransportManager; +LoopbackTransportManager * LoopbackMessagingContext::spLoopbackTransportManager = nullptr; -UDPTransportManager UDPMessagingContext::sUDPTransportManager; +UDPTransportManager * UDPMessagingContext::spUDPTransportManager = nullptr; void MessageCapturer::OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, const SessionHandle & session, DuplicateMessage isDuplicate, diff --git a/src/messaging/tests/MessagingContext.h b/src/messaging/tests/MessagingContext.h index 51525f967d1475..aafd93c5fcb4d6 100644 --- a/src/messaging/tests/MessagingContext.h +++ b/src/messaging/tests/MessagingContext.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -207,94 +208,105 @@ class MessagingContext : public PlatformMemoryUser }; // LoopbackMessagingContext enriches MessagingContext with an async loopback transport -class LoopbackMessagingContext : public MessagingContext +class LoopbackMessagingContext : public ::testing::Test, public MessagingContext { public: virtual ~LoopbackMessagingContext() {} - // These functions wrap sLoopbackTransportManager methods - static auto & GetSystemLayer() { return sLoopbackTransportManager.GetSystemLayer(); } - static auto & GetLoopback() { return sLoopbackTransportManager.GetLoopback(); } - static auto & GetTransportMgr() { return sLoopbackTransportManager.GetTransportMgr(); } - static auto & GetIOContext() { return sLoopbackTransportManager.GetIOContext(); } + // These functions wrap spLoopbackTransportManager methods + static auto & GetSystemLayer() { return spLoopbackTransportManager->GetSystemLayer(); } + static auto & GetLoopback() { return spLoopbackTransportManager->GetLoopback(); } + static auto & GetTransportMgr() { return spLoopbackTransportManager->GetTransportMgr(); } + static auto & GetIOContext() { return spLoopbackTransportManager->GetIOContext(); } template static void DrainAndServiceIO(Ts... args) { - return sLoopbackTransportManager.DrainAndServiceIO(args...); + return spLoopbackTransportManager->DrainAndServiceIO(args...); } // Performs shared setup for all tests in the test suite static void SetUpTestSuite() { - CHIP_ERROR err = CHIP_NO_ERROR; - // TODO: use ASSERT_EQ, once transition to pw_unit_test is complete - VerifyOrDieWithMsg((err = chip::Platform::MemoryInit()) == CHIP_NO_ERROR, AppServer, - "Init CHIP memory failed: %" CHIP_ERROR_FORMAT, err.Format()); - VerifyOrDieWithMsg((err = sLoopbackTransportManager.Init()) == CHIP_NO_ERROR, AppServer, - "Init LoopbackTransportManager failed: %" CHIP_ERROR_FORMAT, err.Format()); + // Initialize memory. + ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); + // Instantiate the LoopbackTransportManager. + ASSERT_EQ(spLoopbackTransportManager, nullptr); + spLoopbackTransportManager = new LoopbackTransportManager(); + ASSERT_NE(spLoopbackTransportManager, nullptr); + // Initialize the LoopbackTransportManager. + ASSERT_EQ(spLoopbackTransportManager->Init(), CHIP_NO_ERROR); } // Performs shared teardown for all tests in the test suite static void TearDownTestSuite() { - sLoopbackTransportManager.Shutdown(); + // Shutdown the LoopbackTransportManager. + spLoopbackTransportManager->Shutdown(); + // Destroy the LoopbackTransportManager. + if (spLoopbackTransportManager != nullptr) + { + delete spLoopbackTransportManager; + spLoopbackTransportManager = nullptr; + } + // Shutdown memory. chip::Platform::MemoryShutdown(); } // Performs setup for each individual test in the test suite - virtual void SetUp() - { - CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrDieWithMsg((err = MessagingContext::Init(&GetTransportMgr(), &GetIOContext())) == CHIP_NO_ERROR, AppServer, - "Init MessagingContext failed: %" CHIP_ERROR_FORMAT, err.Format()); - } + virtual void SetUp() { ASSERT_EQ(MessagingContext::Init(&GetTransportMgr(), &GetIOContext()), CHIP_NO_ERROR); } // Performs teardown for each individual test in the test suite virtual void TearDown() { MessagingContext::Shutdown(); } - static LoopbackTransportManager sLoopbackTransportManager; + static LoopbackTransportManager * spLoopbackTransportManager; }; // UDPMessagingContext enriches MessagingContext with an UDP transport -class UDPMessagingContext : public MessagingContext +class UDPMessagingContext : public ::testing::Test, public MessagingContext { public: virtual ~UDPMessagingContext() {} - static auto & GetSystemLayer() { return sUDPTransportManager.GetSystemLayer(); } - static auto & GetTransportMgr() { return sUDPTransportManager.GetTransportMgr(); } - static auto & GetIOContext() { return sUDPTransportManager.GetIOContext(); } + static auto & GetSystemLayer() { return spUDPTransportManager->GetSystemLayer(); } + static auto & GetTransportMgr() { return spUDPTransportManager->GetTransportMgr(); } + static auto & GetIOContext() { return spUDPTransportManager->GetIOContext(); } // Performs shared setup for all tests in the test suite static void SetUpTestSuite() { - CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrDieWithMsg((err = chip::Platform::MemoryInit()) == CHIP_NO_ERROR, AppServer, - "Init CHIP memory failed: %" CHIP_ERROR_FORMAT, err.Format()); - VerifyOrDieWithMsg((err = sUDPTransportManager.Init()) == CHIP_NO_ERROR, AppServer, - "Init UDPTransportManager failed: %" CHIP_ERROR_FORMAT, err.Format()); + // Initialize memory. + ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); + // Instantiate the UDPTransportManager. + ASSERT_EQ(spUDPTransportManager, nullptr); + spUDPTransportManager = new UDPTransportManager(); + ASSERT_NE(spUDPTransportManager, nullptr); + // Initialize the UDPTransportManager. + ASSERT_EQ(spUDPTransportManager->Init(), CHIP_NO_ERROR); } // Performs shared teardown for all tests in the test suite static void TearDownTestSuite() { - sUDPTransportManager.Shutdown(); + // Shutdown the UDPTransportManager. + spUDPTransportManager->Shutdown(); + // Destroy the UDPTransportManager. + if (spUDPTransportManager != nullptr) + { + delete spUDPTransportManager; + spUDPTransportManager = nullptr; + } + // Shutdown memory. chip::Platform::MemoryShutdown(); } // Performs setup for each individual test in the test suite - virtual void SetUp() - { - CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrDieWithMsg((err = MessagingContext::Init(&GetTransportMgr(), &GetIOContext())) == CHIP_NO_ERROR, AppServer, - "Init MessagingContext failed: %" CHIP_ERROR_FORMAT, err.Format()); - } + virtual void SetUp() { ASSERT_EQ(MessagingContext::Init(&GetTransportMgr(), &GetIOContext()), CHIP_NO_ERROR); } // Performs teardown for each individual test in the test suite virtual void TearDown() { MessagingContext::Shutdown(); } - static UDPTransportManager sUDPTransportManager; + static UDPTransportManager * spUDPTransportManager; }; // Class that can be used to capture decrypted message traffic in tests using