From 6246964eccb554354e3cd5dca931b40765697aff Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> Date: Tue, 14 Nov 2023 21:22:33 -0500 Subject: [PATCH] [Scenes] Endpoint Add and Remove support (#30391) * Moved the endpoint init code to the ember af init callback in scenes and updated config-data to signal scenes uses those init callbacks * Added temporary logs to see why test fails in CI --- .../app-templates/endpoint_config.h | 12 ++- src/app/clusters/scenes-server/SceneTable.h | 1 + .../clusters/scenes-server/SceneTableImpl.cpp | 29 +++++++ .../clusters/scenes-server/SceneTableImpl.h | 2 + .../clusters/scenes-server/scenes-server.cpp | 86 +++++++++++-------- src/app/common/templates/config-data.yaml | 2 + src/app/tests/TestSceneTable.cpp | 77 ++++++++++++++++- 7 files changed, 167 insertions(+), 42 deletions(-) diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h index c7bc4b0509434d..dd8fd1525e0d67 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h @@ -1558,6 +1558,10 @@ (EmberAfGenericClusterFunction) emberAfTimeFormatLocalizationClusterServerInitCallback, \ (EmberAfGenericClusterFunction) MatterTimeFormatLocalizationClusterServerPreAttributeChangedCallback, \ }; \ + const EmberAfGenericClusterFunction chipFuncArrayScenesServer[] = { \ + (EmberAfGenericClusterFunction) emberAfScenesClusterServerInitCallback, \ + (EmberAfGenericClusterFunction) MatterScenesClusterServerShutdownCallback, \ + }; \ const EmberAfGenericClusterFunction chipFuncArrayOnOffServer[] = { \ (EmberAfGenericClusterFunction) emberAfOnOffClusterServerInitCallback, \ (EmberAfGenericClusterFunction) MatterOnOffClusterServerShutdownCallback, \ @@ -2358,8 +2362,8 @@ .attributes = ZAP_ATTRIBUTE_INDEX(238), \ .attributeCount = 9, \ .clusterSize = 13, \ - .mask = ZAP_CLUSTER_MASK(SERVER), \ - .functions = NULL, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(SHUTDOWN_FUNCTION), \ + .functions = chipFuncArrayScenesServer, \ .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 94 ), \ .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 102 ), \ .eventList = nullptr, \ @@ -2930,8 +2934,8 @@ .attributes = ZAP_ATTRIBUTE_INDEX(687), \ .attributeCount = 9, \ .clusterSize = 13, \ - .mask = ZAP_CLUSTER_MASK(SERVER), \ - .functions = NULL, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(SHUTDOWN_FUNCTION), \ + .functions = chipFuncArrayScenesServer, \ .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 240 ), \ .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 248 ), \ .eventList = nullptr, \ diff --git a/src/app/clusters/scenes-server/SceneTable.h b/src/app/clusters/scenes-server/SceneTable.h index 5c28ef8db9a0f3..33a495f671bec8 100644 --- a/src/app/clusters/scenes-server/SceneTable.h +++ b/src/app/clusters/scenes-server/SceneTable.h @@ -285,6 +285,7 @@ class SceneTable // Fabrics virtual CHIP_ERROR RemoveFabric(FabricIndex fabric_index) = 0; + virtual CHIP_ERROR RemoveEndpoint() = 0; // Iterators using SceneEntryIterator = CommonIterator; diff --git a/src/app/clusters/scenes-server/SceneTableImpl.cpp b/src/app/clusters/scenes-server/SceneTableImpl.cpp index 7f5870f0ecf2b3..d003c42d74a50a 100644 --- a/src/app/clusters/scenes-server/SceneTableImpl.cpp +++ b/src/app/clusters/scenes-server/SceneTableImpl.cpp @@ -905,6 +905,35 @@ CHIP_ERROR DefaultSceneTableImpl::RemoveFabric(FabricIndex fabric_index) return CHIP_NO_ERROR; } +CHIP_ERROR DefaultSceneTableImpl::RemoveEndpoint() +{ + VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL); + + for (FabricIndex fabric_index = kMinValidFabricIndex; fabric_index < kMaxValidFabricIndex; fabric_index++) + { + FabricSceneData fabric(mEndpointId, fabric_index); + CHIP_ERROR err = fabric.Load(mStorage); + VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err); + if (CHIP_ERROR_NOT_FOUND == err) + { + continue; + } + + SceneIndex idx = 0; + while (idx < mMaxScenesPerFabric) + { + err = RemoveSceneTableEntryAtPosition(mEndpointId, fabric_index, idx); + VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err); + idx++; + }; + + // Remove fabric scenes on endpoint + ReturnErrorOnFailure(fabric.Delete(mStorage)); + } + + return CHIP_NO_ERROR; +} + /// @brief wrapper function around emberAfGetClustersFromEndpoint to allow testing, shimmed in test configuration because /// emberAfGetClusterFromEndpoint relies on , which relies on zap generated files uint8_t DefaultSceneTableImpl::GetClustersFromEndpoint(ClusterId * clusterList, uint8_t listLen) diff --git a/src/app/clusters/scenes-server/SceneTableImpl.h b/src/app/clusters/scenes-server/SceneTableImpl.h index 9f659fab068f50..8da1ba8fa465ef 100644 --- a/src/app/clusters/scenes-server/SceneTableImpl.h +++ b/src/app/clusters/scenes-server/SceneTableImpl.h @@ -39,6 +39,7 @@ static_assert(kMaxScenesPerEndpoint <= CHIP_CONFIG_MAX_SCENES_TABLE_SIZE, "CHIP_CONFIG_MAX_SCENES_TABLE_SIZE in CHIPConfig.h if you really need more scenes"); static_assert(kMaxScenesPerEndpoint >= 16, "Per spec, kMaxScenesPerEndpoint must be at least 16"); static constexpr uint16_t kMaxScenesPerFabric = (kMaxScenesPerEndpoint - 1) / 2; +static constexpr uint8_t kMaxFabrics = CHIP_CONFIG_MAX_FABRICS; using clusterId = chip::ClusterId; @@ -146,6 +147,7 @@ class DefaultSceneTableImpl : public SceneTable // Fabrics CHIP_ERROR RemoveFabric(FabricIndex fabric_index) override; + CHIP_ERROR RemoveEndpoint() override; // Iterators SceneEntryIterator * IterateSceneEntries(FabricIndex fabric_index) override; diff --git a/src/app/clusters/scenes-server/scenes-server.cpp b/src/app/clusters/scenes-server/scenes-server.cpp index 0bb0e012ba0f94..7a0807b5c7c816 100644 --- a/src/app/clusters/scenes-server/scenes-server.cpp +++ b/src/app/clusters/scenes-server/scenes-server.cpp @@ -116,42 +116,6 @@ CHIP_ERROR ScenesServer::Init() SceneTable * sceneTable = scenes::GetSceneTableImpl(); ReturnErrorOnFailure(sceneTable->Init(&chip::Server::GetInstance().GetPersistentStorage())); - for (auto endpoint : EnabledEndpointsWithServerCluster(Id)) - { - uint32_t featureMap = 0; - EmberAfStatus status = Attributes::FeatureMap::Get(endpoint, &featureMap); - if (EMBER_ZCL_STATUS_SUCCESS == status) - { - // According to spec, bit 7 MUST match feature bit 0 (SceneNames) - BitMask nameSupport = (featureMap & to_underlying(Feature::kSceneNames)) - ? BitMask(NameSupportBitmap::kSceneNames) - : BitMask(); - status = Attributes::NameSupport::Set(endpoint, nameSupport); - if (EMBER_ZCL_STATUS_SUCCESS != status) - { - ChipLogDetail(Zcl, "ERR: setting NameSupport on Endpoint %hu Status: %x", endpoint, status); - } - } - else - { - ChipLogDetail(Zcl, "ERR: getting the scenes FeatureMap on Endpoint %hu Status: %x", endpoint, status); - } - - // Explicit AttributeValuePairs and TableSize features are mandatory for matter so we force-set them here - featureMap |= (to_underlying(Feature::kExplicit) | to_underlying(Feature::kTableSize)); - status = Attributes::FeatureMap::Set(endpoint, featureMap); - if (EMBER_ZCL_STATUS_SUCCESS != status) - { - ChipLogDetail(Zcl, "ERR: setting the scenes FeatureMap on Endpoint %hu Status: %x", endpoint, status); - } - - status = Attributes::LastConfiguredBy::SetNull(endpoint); - if (EMBER_ZCL_STATUS_SUCCESS != status) - { - ChipLogDetail(Zcl, "ERR: setting LastConfiguredBy on Endpoint %hu Status: %x", endpoint, status); - } - } - mIsInitialized = true; return CHIP_NO_ERROR; } @@ -919,6 +883,56 @@ void ScenesServer::HandleCopyScene(HandlerContext & ctx, const Commands::CopySce } // namespace app } // namespace chip +using namespace chip; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Scenes; + +void emberAfScenesClusterServerInitCallback(EndpointId endpoint) +{ + uint32_t featureMap = 0; + EmberAfStatus status = Attributes::FeatureMap::Get(endpoint, &featureMap); + if (EMBER_ZCL_STATUS_SUCCESS == status) + { + // According to spec, bit 7 MUST match feature bit 0 (SceneNames) + BitMask nameSupport = (featureMap & to_underlying(Feature::kSceneNames)) + ? BitMask(NameSupportBitmap::kSceneNames) + : BitMask(); + status = Attributes::NameSupport::Set(endpoint, nameSupport); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogDetail(Zcl, "ERR: setting NameSupport on Endpoint %hu Status: %x", endpoint, status); + } + } + else + { + ChipLogDetail(Zcl, "ERR: getting the scenes FeatureMap on Endpoint %hu Status: %x", endpoint, status); + } + + // Explicit AttributeValuePairs and TableSize features are mandatory for matter so we force-set them here + featureMap |= (to_underlying(Feature::kExplicit) | to_underlying(Feature::kTableSize)); + status = Attributes::FeatureMap::Set(endpoint, featureMap); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogDetail(Zcl, "ERR: setting the scenes FeatureMap on Endpoint %hu Status: %x", endpoint, status); + } + + status = Attributes::LastConfiguredBy::SetNull(endpoint); + if (EMBER_ZCL_STATUS_SUCCESS != status) + { + ChipLogDetail(Zcl, "ERR: setting LastConfiguredBy on Endpoint %hu Status: %x", endpoint, status); + } +} + +void MatterScenesClusterServerShutdownCallback(EndpointId endpoint) +{ + uint16_t endpointTableSize = 0; + ReturnOnFailure(Attributes::SceneTableSize::Get(endpoint, &endpointTableSize)); + + // Get Scene Table Instance + SceneTable * sceneTable = scenes::GetSceneTableImpl(endpoint, endpointTableSize); + sceneTable->RemoveEndpoint(); +} + void MatterScenesPluginServerInitCallback() { CHIP_ERROR err = ScenesServer::Instance().Init(); diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index dfa4a3fa58ed15..aebf378b4cef21 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -64,6 +64,7 @@ ClustersWithInitFunctions: - Thermostat - Mode Select - Sample MEI + - Scenes ClustersWithAttributeChangedFunctions: - Bridged Device Basic @@ -80,6 +81,7 @@ ClustersWithShutdownFunctions: - Level Control - Color Control - Sample MEI + - Scenes ClustersWithPreAttributeChangeFunctions: - Door Lock diff --git a/src/app/tests/TestSceneTable.cpp b/src/app/tests/TestSceneTable.cpp index 743489450c7a8f..2ff9139b003bc5 100644 --- a/src/app/tests/TestSceneTable.cpp +++ b/src/app/tests/TestSceneTable.cpp @@ -1411,6 +1411,7 @@ void TestEndpointScenes(nlTestSuite * aSuite, void * aContext) NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric2, scene7)); // scene count to Endpoint + // Endpoint 3 still unafected sceneTable = scenes::GetSceneTableImpl(kTestEndpoint3, defaultTestTableSize); NL_TEST_ASSERT(aSuite, nullptr != sceneTable); VerifyOrReturn(nullptr != sceneTable); @@ -1419,6 +1420,69 @@ void TestEndpointScenes(nlTestSuite * aSuite, void * aContext) NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetRemainingCapacity(kFabric2, fabric_capacity)); NL_TEST_ASSERT(aSuite, defaultTestFabricCapacity == fabric_capacity); + // Fill fabric 1 endpoint 3 + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene1)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene2)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene3)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene4)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene5)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene6)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene7)); + + // Test removal of Endpoint clears scene on all fabrics for that endpoint + sceneTable = scenes::GetSceneTableImpl(kTestEndpoint2, defaultTestTableSize); + NL_TEST_ASSERT(aSuite, nullptr != sceneTable); + VerifyOrReturn(nullptr != sceneTable); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->RemoveEndpoint()); + + // Check Fabric1 on Endpoint 2 + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId1, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId2, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId3, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId4, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId5, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId6, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId7, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric2, sceneId1, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric2, sceneId2, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric2, sceneId3, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric2, sceneId4, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric2, sceneId5, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric2, sceneId6, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric2, sceneId7, scene)); + + // Check Fabric 1 and 2 on Endpoint 1 + sceneTable = scenes::GetSceneTableImpl(kTestEndpoint1, defaultTestTableSize); + NL_TEST_ASSERT(aSuite, nullptr != sceneTable); + VerifyOrReturn(nullptr != sceneTable); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId1, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId2, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId3, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId4, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId5, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId6, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId7, scene)); + + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric2, sceneId1, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric2, sceneId2, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric2, sceneId3, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric2, sceneId4, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric2, sceneId5, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric2, sceneId6, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric2, sceneId7, scene)); + + // Check Fabric 1 on Endpoint 3 + sceneTable = scenes::GetSceneTableImpl(kTestEndpoint3, defaultTestTableSize); + NL_TEST_ASSERT(aSuite, nullptr != sceneTable); + VerifyOrReturn(nullptr != sceneTable); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId1, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId2, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId3, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId4, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId5, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId6, scene)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->GetSceneTableEntry(kFabric1, sceneId7, scene)); + // Test removal of fabric clears scene fabric on all endpoints sceneTable = scenes::GetSceneTableImpl(kTestEndpoint1, defaultTestTableSize); NL_TEST_ASSERT(aSuite, nullptr != sceneTable); @@ -1431,7 +1495,6 @@ void TestEndpointScenes(nlTestSuite * aSuite, void * aContext) NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId5, scene)); NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId6, scene)); NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId7, scene)); - NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId8, scene)); sceneTable = scenes::GetSceneTableImpl(kTestEndpoint2, defaultTestTableSize); NL_TEST_ASSERT(aSuite, nullptr != sceneTable); @@ -1443,7 +1506,17 @@ void TestEndpointScenes(nlTestSuite * aSuite, void * aContext) NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId5, scene)); NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId6, scene)); NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId7, scene)); - NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId8, scene)); + + sceneTable = scenes::GetSceneTableImpl(kTestEndpoint3, defaultTestTableSize); + NL_TEST_ASSERT(aSuite, nullptr != sceneTable); + VerifyOrReturn(nullptr != sceneTable); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId1, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId2, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId3, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId4, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId5, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId6, scene)); + NL_TEST_ASSERT(aSuite, CHIP_ERROR_NOT_FOUND == sceneTable->GetSceneTableEntry(kFabric1, sceneId7, scene)); sceneTable->RemoveFabric(kFabric2);