Skip to content

Commit

Permalink
Make the mock attribute storage implementation configurable at runtime (
Browse files Browse the repository at this point in the history
#30676)

* Make the mock attribute storage implementation configurable at runtime

* Tweaks from review

* Exclude mocks from include rules

* Tweaks from revivew
  • Loading branch information
ksperling-apple authored and pull[bot] committed Dec 14, 2023
1 parent bceb772 commit 2103810
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 170 deletions.
1 change: 1 addition & 0 deletions scripts/tools/check_includes_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
'/examples/',
'/java/',
'/Jni',
'/mock/',
'/pybindings/',
'/python/',
'/Test',
Expand Down
5 changes: 4 additions & 1 deletion src/app/util/mock/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
9 changes: 9 additions & 0 deletions src/app/util/mock/Functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,24 @@
#include <app/AttributeAccessInterface.h>
#include <app/ConcreteAttributePath.h>
#include <app/MessageDef/AttributeReportIB.h>
#include <app/util/mock/MockNodeConfig.h>
#include <lib/core/CHIPError.h>
#include <lib/core/DataModelTypes.h>

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
125 changes: 125 additions & 0 deletions src/app/util/mock/MockNodeConfig.cpp
Original file line number Diff line number Diff line change
@@ -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 <app/util/mock/MockNodeConfig.h>

#include <app/att-storage.h>
#include <app/util/af.h>
#include <lib/support/CodeUtils.h>

#include <utility>

namespace chip {
namespace Test {

namespace {

template <class T>
const T * findById(const std::vector<T> & vector, decltype(std::declval<T>().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<MockAttributeConfig> aAttributes,
std::initializer_list<MockEventConfig> 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<uint16_t>(attributes.size());
mEmberCluster.mask = CLUSTER_MASK_SERVER;
mEmberCluster.eventCount = static_cast<uint16_t>(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<MockClusterConfig> 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<uint8_t>(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<MockEndpointConfig> 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
86 changes: 86 additions & 0 deletions src/app/util/mock/MockNodeConfig.h
Original file line number Diff line number Diff line change
@@ -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 <app/util/af-types.h>
#include <lib/core/DataModelTypes.h>

#include <cstddef>
#include <initializer_list>
#include <vector>

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<MockAttributeConfig> aAttributes = {},
std::initializer_list<MockEventConfig> aEvents = {});

const MockAttributeConfig * attributeById(AttributeId attributeId, ptrdiff_t * outIndex = nullptr) const;
const EmberAfCluster * emberCluster() const { return &mEmberCluster; }

const ClusterId id;
const std::vector<MockAttributeConfig> attributes;
const std::vector<MockEventConfig> events;

private:
EmberAfCluster mEmberCluster;
std::vector<EventId> mEmberEventList;
};

struct MockEndpointConfig
{
MockEndpointConfig(EndpointId aId, std::initializer_list<MockClusterConfig> aClusters = {});

const MockClusterConfig * clusterById(ClusterId clusterId, ptrdiff_t * outIndex = nullptr) const;
const EmberAfEndpointType * emberEndpoint() const { return &mEmberEndpoint; }

const EndpointId id;
const std::vector<MockClusterConfig> clusters;

private:
std::vector<EmberAfCluster> mEmberClusters;
EmberAfEndpointType mEmberEndpoint;
};

struct MockNodeConfig
{
MockNodeConfig(std::initializer_list<MockEndpointConfig> 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<MockEndpointConfig> endpoints;
};

} // namespace Test
} // namespace chip
Loading

0 comments on commit 2103810

Please sign in to comment.