From 21038100f0e9b041912b0d6d2c1a0576b2ba3c0b Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:55:04 +1300 Subject: [PATCH] Make the mock attribute storage implementation configurable at runtime (#30676) * Make the mock attribute storage implementation configurable at runtime * Tweaks from review * Exclude mocks from include rules * Tweaks from revivew --- scripts/tools/check_includes_config.py | 1 + src/app/util/mock/BUILD.gn | 5 +- src/app/util/mock/Functions.h | 9 + src/app/util/mock/MockNodeConfig.cpp | 125 +++++++++++ src/app/util/mock/MockNodeConfig.h | 86 ++++++++ src/app/util/mock/attribute-storage.cpp | 274 +++++++++--------------- 6 files changed, 330 insertions(+), 170 deletions(-) create mode 100644 src/app/util/mock/MockNodeConfig.cpp create mode 100644 src/app/util/mock/MockNodeConfig.h diff --git a/scripts/tools/check_includes_config.py b/scripts/tools/check_includes_config.py index bfd7f15c5ccf17..1e06f933dfb63c 100644 --- a/scripts/tools/check_includes_config.py +++ b/scripts/tools/check_includes_config.py @@ -28,6 +28,7 @@ '/examples/', '/java/', '/Jni', + '/mock/', '/pybindings/', '/python/', '/Test', diff --git a/src/app/util/mock/BUILD.gn b/src/app/util/mock/BUILD.gn index 640e1a97e4661b..94e1a30aa6433b 100644 --- a/src/app/util/mock/BUILD.gn +++ b/src/app/util/mock/BUILD.gn @@ -19,7 +19,10 @@ config("mock_include") { } source_set("mock_ember") { - sources = [ "attribute-storage.cpp" ] + sources = [ + "MockNodeConfig.cpp", + "attribute-storage.cpp", + ] public_deps = [ "${chip_root}/src/app", diff --git a/src/app/util/mock/Functions.h b/src/app/util/mock/Functions.h index 1dc692669b4cab..32ba08d316f484 100644 --- a/src/app/util/mock/Functions.h +++ b/src/app/util/mock/Functions.h @@ -26,15 +26,24 @@ #include #include #include +#include #include #include namespace chip { namespace Test { + CHIP_ERROR ReadSingleMockClusterData(FabricIndex aAccessingFabricIndex, const app::ConcreteAttributePath & aPath, app::AttributeReportIBs::Builder & aAttributeReports, app::AttributeValueEncoder::AttributeEncodeState * apEncoderState); void BumpVersion(); DataVersion GetVersion(); + +/// Configures the singular global mock attribute storage to use the specified configuration. +void SetMockNodeConfig(const MockNodeConfig & config); + +/// Resets the mock attribute storage to the default configuration. +void ResetMockNodeConfig(); + } // namespace Test } // namespace chip diff --git a/src/app/util/mock/MockNodeConfig.cpp b/src/app/util/mock/MockNodeConfig.cpp new file mode 100644 index 00000000000000..b640be42f751e0 --- /dev/null +++ b/src/app/util/mock/MockNodeConfig.cpp @@ -0,0 +1,125 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include + +namespace chip { +namespace Test { + +namespace { + +template +const T * findById(const std::vector & vector, decltype(std::declval().id) aId, ptrdiff_t * outIndex = nullptr) +{ + for (auto & element : vector) + { + if (element.id == aId) + { + if (outIndex != nullptr) + { + *outIndex = &element - vector.data(); + } + return &element; + } + } + + if (outIndex != nullptr) + { + *outIndex = -1; + } + return nullptr; +} + +} // namespace + +MockClusterConfig::MockClusterConfig(ClusterId aId, std::initializer_list aAttributes, + std::initializer_list aEvents) : + id(aId), + attributes(aAttributes), events(aEvents), mEmberCluster{} +{ + VerifyOrDie(aAttributes.size() < UINT16_MAX); + + // Note: This only populates the parts of the ember structs that are currently needed for our tests. + for (const auto & event : events) + { + mEmberEventList.push_back(event.id); + } + mEmberCluster.clusterId = id; + mEmberCluster.attributeCount = static_cast(attributes.size()); + mEmberCluster.mask = CLUSTER_MASK_SERVER; + mEmberCluster.eventCount = static_cast(mEmberEventList.size()); + mEmberCluster.eventList = mEmberEventList.data(); +} + +const MockAttributeConfig * MockClusterConfig::attributeById(AttributeId attributeId, ptrdiff_t * outIndex) const +{ + return findById(attributes, attributeId, outIndex); +} + +MockEndpointConfig::MockEndpointConfig(EndpointId aId, std::initializer_list aClusters) : + id(aId), clusters(aClusters), mEmberEndpoint{} +{ + VerifyOrDie(aClusters.size() < UINT8_MAX); + + // Note: We're copying all the EmberAfClusters because they need to be contiguous in memory + for (const auto & cluster : clusters) + { + mEmberClusters.push_back(*cluster.emberCluster()); + } + mEmberEndpoint.clusterCount = static_cast(mEmberClusters.size()); + mEmberEndpoint.cluster = mEmberClusters.data(); +} + +const MockClusterConfig * MockEndpointConfig::clusterById(ClusterId clusterId, ptrdiff_t * outIndex) const +{ + return findById(clusters, clusterId, outIndex); +} + +MockNodeConfig::MockNodeConfig(std::initializer_list aEndpoints) : endpoints(aEndpoints) +{ + VerifyOrDie(aEndpoints.size() < kEmberInvalidEndpointIndex); +} + +const MockEndpointConfig * MockNodeConfig::endpointById(EndpointId endpointId, ptrdiff_t * outIndex) const +{ + return findById(endpoints, endpointId, outIndex); +} + +const MockClusterConfig * MockNodeConfig::clusterByIds(EndpointId endpointId, ClusterId clusterId, + ptrdiff_t * outClusterIndex) const +{ + auto endpoint = endpointById(endpointId); + if (endpoint == nullptr) + { + if (outClusterIndex != nullptr) + { + *outClusterIndex = -1; + } + return nullptr; + } + return endpoint->clusterById(clusterId, outClusterIndex); +} + +} // namespace Test +} // namespace chip diff --git a/src/app/util/mock/MockNodeConfig.h b/src/app/util/mock/MockNodeConfig.h new file mode 100644 index 00000000000000..2e8f19895036a7 --- /dev/null +++ b/src/app/util/mock/MockNodeConfig.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include +#include +#include + +namespace chip { +namespace Test { + +struct MockAttributeConfig +{ + MockAttributeConfig(AttributeId aId) : id(aId) {} + const AttributeId id; +}; + +struct MockEventConfig +{ + MockEventConfig(EventId aId) : id(aId) {} + const EventId id; +}; + +struct MockClusterConfig +{ + MockClusterConfig(ClusterId aId, std::initializer_list aAttributes = {}, + std::initializer_list aEvents = {}); + + const MockAttributeConfig * attributeById(AttributeId attributeId, ptrdiff_t * outIndex = nullptr) const; + const EmberAfCluster * emberCluster() const { return &mEmberCluster; } + + const ClusterId id; + const std::vector attributes; + const std::vector events; + +private: + EmberAfCluster mEmberCluster; + std::vector mEmberEventList; +}; + +struct MockEndpointConfig +{ + MockEndpointConfig(EndpointId aId, std::initializer_list aClusters = {}); + + const MockClusterConfig * clusterById(ClusterId clusterId, ptrdiff_t * outIndex = nullptr) const; + const EmberAfEndpointType * emberEndpoint() const { return &mEmberEndpoint; } + + const EndpointId id; + const std::vector clusters; + +private: + std::vector mEmberClusters; + EmberAfEndpointType mEmberEndpoint; +}; + +struct MockNodeConfig +{ + MockNodeConfig(std::initializer_list aEndpoints); + + const MockEndpointConfig * endpointById(EndpointId endpointId, ptrdiff_t * outIndex = nullptr) const; + const MockClusterConfig * clusterByIds(EndpointId endpointId, ClusterId clusterId, ptrdiff_t * outClusterIndex = nullptr) const; + + const std::vector endpoints; +}; + +} // namespace Test +} // namespace chip diff --git a/src/app/util/mock/attribute-storage.cpp b/src/app/util/mock/attribute-storage.cpp index 19c774fa40b0a8..ec47dc061dbd8a 100644 --- a/src/app/util/mock/attribute-storage.cpp +++ b/src/app/util/mock/attribute-storage.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -56,35 +57,61 @@ typedef uint8_t EmberAfClusterMask; using namespace chip; using namespace chip::Test; using namespace chip::app; +using namespace Clusters::Globals::Attributes; namespace { -DataVersion dataVersion = 0; -EndpointId endpoints[] = { kMockEndpoint1, kMockEndpoint2, kMockEndpoint3 }; -uint16_t clusterIndex[] = { 0, 2, 5 }; -uint8_t clusterCount[] = { 2, 3, 4 }; -ClusterId clusters[] = { MockClusterId(1), MockClusterId(2), MockClusterId(1), MockClusterId(2), MockClusterId(3), - MockClusterId(1), MockClusterId(2), MockClusterId(3), MockClusterId(4) }; -uint16_t attributeIndex[] = { 0, 2, 5, 7, 11, 16, 19, 25, 27 }; -uint16_t attributeCount[] = { 2, 3, 2, 4, 5, 3, 6, 2, 2 }; -uint16_t eventIndex[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2 }; -uint16_t eventCount[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0 }; -AttributeId attributes[] = { + +DataVersion dataVersion = 0; +const MockNodeConfig * mockConfig = nullptr; + +const MockNodeConfig & DefaultMockNodeConfig() +{ // clang-format off - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id, - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id, MockAttributeId(1), - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id, - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), MockAttributeId(3), - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id, MockAttributeId(1), - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), MockAttributeId(3), MockAttributeId(4), - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id, - Clusters::Globals::Attributes::ClusterRevision::Id, Clusters::Globals::Attributes::FeatureMap::Id + static const MockNodeConfig config({ + MockEndpointConfig(kMockEndpoint1, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, + }, { + MockEventId(1), MockEventId(2), + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), + }), + }), + MockEndpointConfig(kMockEndpoint2, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), + }), + MockClusterConfig(MockClusterId(3), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), MockAttributeId(3), + }), + }), + MockEndpointConfig(kMockEndpoint3, { + MockClusterConfig(MockClusterId(1), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), + }), + MockClusterConfig(MockClusterId(2), { + ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), MockAttributeId(2), MockAttributeId(3), MockAttributeId(4), + }), + MockClusterConfig(MockClusterId(3), { + ClusterRevision::Id, FeatureMap::Id, + }), + MockClusterConfig(MockClusterId(4), { + ClusterRevision::Id, FeatureMap::Id, + }), + }), + }); // clang-format on -}; -EventId events[] = { - MockEventId(1), - MockEventId(2), -}; + return config; +} + +const MockNodeConfig & GetMockNodeConfig() +{ + return (mockConfig != nullptr) ? *mockConfig : DefaultMockNodeConfig(); +} uint16_t mockClusterRevision = 1; uint32_t mockFeatureMap = 0x1234; @@ -102,125 +129,69 @@ uint8_t mockAttribute4[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, }; -#define MOCK_CLUSTER_DECL(idx) \ - { \ - .clusterId = clusters[idx], .attributes = nullptr, /* Not used for now. */ \ - .attributeCount = attributeCount[idx], .clusterSize = 0, /* Not used for now. */ \ - .mask = CLUSTER_MASK_SERVER, .functions = nullptr, .acceptedCommandList = nullptr, /* Not used for now */ \ - .generatedCommandList = nullptr, /* Not used for now */ \ - .eventList = &events[eventIndex[idx]], .eventCount = eventCount[idx], \ - } - -EmberAfCluster clusterStructs[] = { - MOCK_CLUSTER_DECL(0), MOCK_CLUSTER_DECL(1), MOCK_CLUSTER_DECL(2), MOCK_CLUSTER_DECL(3), MOCK_CLUSTER_DECL(4), - MOCK_CLUSTER_DECL(5), MOCK_CLUSTER_DECL(6), MOCK_CLUSTER_DECL(7), MOCK_CLUSTER_DECL(8), -}; - -#define MOCK_ENDPOINT_DECL(idx) \ - { \ - .cluster = &clusterStructs[clusterIndex[idx]], .clusterCount = clusterCount[idx], \ - .endpointSize = 0, /* Not used for now */ \ - } - -EmberAfEndpointType endpointStructs[] = { - MOCK_ENDPOINT_DECL(0), - MOCK_ENDPOINT_DECL(1), - MOCK_ENDPOINT_DECL(2), -}; - } // namespace uint16_t emberAfEndpointCount() { - return ArraySize(endpoints); + return static_cast(GetMockNodeConfig().endpoints.size()); } -uint16_t emberAfIndexFromEndpoint(chip::EndpointId endpoint) +uint16_t emberAfIndexFromEndpoint(EndpointId endpointId) { - static_assert(ArraySize(endpoints) < UINT16_MAX, "Need to be able to return endpoint index as a 16-bit value."); - - for (size_t i = 0; i < ArraySize(endpoints); i++) - { - if (endpoints[i] == endpoint) - { - return static_cast(i); - } - } - return UINT16_MAX; + ptrdiff_t index; + auto endpoint = GetMockNodeConfig().endpointById(endpointId, &index); + VerifyOrReturnValue(endpoint != nullptr, kEmberInvalidEndpointIndex); + return static_cast(index); } -uint8_t emberAfGetClusterCountForEndpoint(chip::EndpointId endpoint) +uint8_t emberAfGetClusterCountForEndpoint(EndpointId endpointId) { - for (size_t i = 0; i < ArraySize(endpoints); i++) - { - if (endpoints[i] == endpoint) - { - return clusterCount[i]; - } - } - return 0; + auto endpoint = GetMockNodeConfig().endpointById(endpointId); + VerifyOrReturnValue(endpoint != nullptr, 0); + return static_cast(endpoint->clusters.size()); } uint8_t emberAfClusterCount(chip::EndpointId endpoint, bool server) { - return emberAfGetClusterCountForEndpoint(endpoint); + return (server) ? emberAfGetClusterCountForEndpoint(endpoint) : 0; } -uint16_t emberAfGetServerAttributeCount(chip::EndpointId endpoint, chip::ClusterId cluster) +uint16_t emberAfGetServerAttributeCount(chip::EndpointId endpointId, chip::ClusterId clusterId) { - uint16_t endpointIndex = emberAfIndexFromEndpoint(endpoint); - uint8_t clusterCountOnEndpoint = emberAfClusterCount(endpoint, true); - for (uint8_t i = 0; i < clusterCountOnEndpoint; i++) - { - if (clusters[i + clusterIndex[endpointIndex]] == cluster) - { - return attributeCount[i + clusterIndex[endpointIndex]]; - } - } - return 0; + auto cluster = GetMockNodeConfig().clusterByIds(endpointId, clusterId); + VerifyOrReturnValue(cluster != nullptr, 0); + return static_cast(cluster->attributes.size()); } -uint16_t emberAfGetServerAttributeIndexByAttributeId(chip::EndpointId endpoint, chip::ClusterId cluster, +uint16_t emberAfGetServerAttributeIndexByAttributeId(chip::EndpointId endpointId, chip::ClusterId clusterId, chip::AttributeId attributeId) { - uint16_t endpointIndex = emberAfIndexFromEndpoint(endpoint); - uint8_t clusterCountOnEndpoint = emberAfClusterCount(endpoint, true); - for (uint8_t i = 0; i < clusterCountOnEndpoint; i++) - { - if (clusters[i + clusterIndex[endpointIndex]] == cluster) - { - uint16_t clusterAttributeOffset = attributeIndex[i + clusterIndex[endpointIndex]]; - for (uint16_t j = 0; j < emberAfGetServerAttributeCount(endpoint, cluster); j++) - { - if (attributes[clusterAttributeOffset + j] == attributeId) - { - return j; - } - } - break; - } - } - return UINT16_MAX; + auto cluster = GetMockNodeConfig().clusterByIds(endpointId, clusterId); + VerifyOrReturnValue(cluster != nullptr, kEmberInvalidEndpointIndex); + ptrdiff_t index; + auto attribute = cluster->attributeById(attributeId, &index); + VerifyOrReturnValue(attribute != nullptr, kEmberInvalidEndpointIndex); + return static_cast(index); } bool emberAfContainsAttribute(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId) { - return !(emberAfGetServerAttributeIndexByAttributeId(endpoint, clusterId, attributeId) == UINT16_MAX); + return emberAfGetServerAttributeIndexByAttributeId(endpoint, clusterId, attributeId) != kEmberInvalidEndpointIndex; } chip::EndpointId emberAfEndpointFromIndex(uint16_t index) { - VerifyOrDie(index < ArraySize(endpoints)); - return endpoints[index]; + auto & config = GetMockNodeConfig(); + VerifyOrDie(index < config.endpoints.size()); + return config.endpoints[index].id; } -chip::Optional emberAfGetNthClusterId(chip::EndpointId endpoint, uint8_t n, bool server) +chip::Optional emberAfGetNthClusterId(chip::EndpointId endpointId, uint8_t n, bool server) { - if (n >= emberAfClusterCount(endpoint, server)) - { - return chip::Optional::Missing(); - } - return chip::Optional(clusters[clusterIndex[emberAfIndexFromEndpoint(endpoint)] + n]); + VerifyOrReturnValue(server, NullOptional); // only server clusters supported + auto endpoint = GetMockNodeConfig().endpointById(endpointId); + VerifyOrReturnValue(endpoint != nullptr && n < endpoint->clusters.size(), NullOptional); + return MakeOptional(endpoint->clusters[n].id); } // Returns number of clusters put into the passed cluster list @@ -241,43 +212,26 @@ uint8_t emberAfGetClustersFromEndpoint(EndpointId endpoint, ClusterId * clusterL return cluster_count; } -chip::Optional emberAfGetServerAttributeIdByIndex(chip::EndpointId endpoint, chip::ClusterId cluster, +chip::Optional emberAfGetServerAttributeIdByIndex(chip::EndpointId endpointId, chip::ClusterId clusterId, uint16_t index) { - uint16_t endpointIndex = emberAfIndexFromEndpoint(endpoint); - uint8_t clusterCountOnEndpoint = emberAfClusterCount(endpoint, true); - for (uint8_t i = 0; i < clusterCountOnEndpoint; i++) - { - if (clusters[i + clusterIndex[endpointIndex]] == cluster) - { - uint16_t clusterAttributeOffset = attributeIndex[i + clusterIndex[endpointIndex]]; - if (index < emberAfGetServerAttributeCount(endpoint, cluster)) - { - return Optional(attributes[clusterAttributeOffset + index]); - } - break; - } - } - return Optional::Missing(); + auto cluster = GetMockNodeConfig().clusterByIds(endpointId, clusterId); + VerifyOrReturnValue(cluster != nullptr && index < cluster->attributes.size(), NullOptional); + return MakeOptional(cluster->attributes[index].id); } -uint8_t emberAfClusterIndex(chip::EndpointId endpoint, chip::ClusterId cluster, EmberAfClusterMask mask) +uint8_t emberAfClusterIndex(chip::EndpointId endpointId, chip::ClusterId clusterId, EmberAfClusterMask mask) { - uint16_t endpointIndex = emberAfIndexFromEndpoint(endpoint); - uint8_t clusterCountOnEndpoint = emberAfClusterCount(endpoint, true); - for (uint8_t i = 0; i < clusterCountOnEndpoint; i++) - { - if (clusters[i + clusterIndex[endpointIndex]] == cluster) - { - return i; - } - } - return UINT8_MAX; + VerifyOrReturnValue(mask == 0 || (mask & CLUSTER_MASK_SERVER) != 0, UINT8_MAX); // only server clusters supported + ptrdiff_t index; + auto cluster = GetMockNodeConfig().clusterByIds(endpointId, clusterId, &index); + VerifyOrReturnValue(cluster != nullptr, UINT8_MAX); + return static_cast(index); } bool emberAfEndpointIndexIsEnabled(uint16_t index) { - return index < ArraySize(endpoints); + return index < GetMockNodeConfig().endpoints.size(); } // This duplication of basic utilities is really unfortunate, but we can't link @@ -312,42 +266,24 @@ uint16_t emberAfLongStringLength(const uint8_t * buffer) // This will find the first server that has the clusterId given from the index of endpoint. bool emberAfContainsServerFromIndex(uint16_t index, ClusterId clusterId) { - if (index == kEmberInvalidEndpointIndex) - { - return false; - } - - return clusterId; // Mock version return true as long as the endpoint is - // valid + auto config = GetMockNodeConfig(); + VerifyOrReturnValue(index < config.endpoints.size(), false); + return true; // TODO: TestSceneTable relies on returning true here: https://github.com/project-chip/connectedhomeip/issues/30696 + // return config.endpoints[index].clusterById(clusterId) != nullptr; } const EmberAfEndpointType * emberAfFindEndpointType(EndpointId endpointId) { - uint16_t ep = emberAfIndexFromEndpoint(endpointId); - if (ep == UINT16_MAX) - { - return nullptr; - } - return &endpointStructs[ep]; + auto endpoint = GetMockNodeConfig().endpointById(endpointId); + VerifyOrReturnValue(endpoint != nullptr, nullptr); + return endpoint->emberEndpoint(); } -const EmberAfCluster * emberAfFindServerCluster(EndpointId endpoint, ClusterId clusterId) +const EmberAfCluster * emberAfFindServerCluster(EndpointId endpointId, ClusterId clusterId) { - auto * endpointType = emberAfFindEndpointType(endpoint); - if (endpointType == nullptr) - { - return nullptr; - } - - for (decltype(endpointType->clusterCount) idx = 0; idx < endpointType->clusterCount; ++idx) - { - auto * cluster = &endpointType->cluster[idx]; - if (cluster->clusterId == clusterId && (cluster->mask & CLUSTER_MASK_SERVER)) - { - return cluster; - } - } - return nullptr; + auto cluster = GetMockNodeConfig().clusterByIds(endpointId, clusterId); + VerifyOrReturnValue(cluster != nullptr, nullptr); + return cluster->emberCluster(); } namespace chip {