From 88b0677db183a54f7e41555d73f93085a7e3d8d3 Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs Date: Mon, 20 Mar 2023 18:19:31 -0400 Subject: [PATCH] Addressed comments, fixed TLV structures, removed redundant checks --- src/app/clusters/scenes/ExtensionFieldSets.h | 12 +-- .../scenes/ExtensionFieldSetsImpl.cpp | 39 +++++---- .../clusters/scenes/ExtensionFieldSetsImpl.h | 26 +++--- src/app/clusters/scenes/SceneTable.h | 8 +- src/app/clusters/scenes/SceneTableImpl.cpp | 70 ++++++++++------ src/app/clusters/scenes/SceneTableImpl.h | 42 ++++------ src/app/tests/TestExtensionFieldSets.cpp | 81 ++++++++++++++----- src/app/tests/TestSceneTable.cpp | 1 + src/lib/core/CHIPConfig.h | 3 +- 9 files changed, 171 insertions(+), 111 deletions(-) diff --git a/src/app/clusters/scenes/ExtensionFieldSets.h b/src/app/clusters/scenes/ExtensionFieldSets.h index 4753995d9421e3..e05525e0586f02 100644 --- a/src/app/clusters/scenes/ExtensionFieldSets.h +++ b/src/app/clusters/scenes/ExtensionFieldSets.h @@ -34,12 +34,14 @@ class ExtensionFieldSets ExtensionFieldSets(){}; virtual ~ExtensionFieldSets() = default; - virtual CHIP_ERROR Serialize(TLV::TLVWriter & writer) const = 0; - virtual CHIP_ERROR Deserialize(TLV::TLVReader & reader) = 0; - virtual void Clear() = 0; - virtual bool IsEmpty() const = 0; + virtual CHIP_ERROR Serialize(TLV::TLVWriter & writer, TLV::Tag structTa) const = 0; + virtual CHIP_ERROR Deserialize(TLV::TLVReader & reader, TLV::Tag structTa) = 0; + virtual void Clear() = 0; + virtual bool IsEmpty() const = 0; /// @brief Gets a count of how many initialized fields sets are in the object - /// @return The number of initialized field sets in the object + /// @return The number of initialized field sets the object + /// @note Field set refers to extension field sets, from the scene cluster (see 1.4.6.2 ExtensionFieldSet in Matter Application + /// Clusters) virtual uint8_t GetFieldSetCount() const = 0; }; } // namespace scenes diff --git a/src/app/clusters/scenes/ExtensionFieldSetsImpl.cpp b/src/app/clusters/scenes/ExtensionFieldSetsImpl.cpp index 95900c167dc424..8c9c2870a7ed3c 100644 --- a/src/app/clusters/scenes/ExtensionFieldSetsImpl.cpp +++ b/src/app/clusters/scenes/ExtensionFieldSetsImpl.cpp @@ -22,43 +22,40 @@ namespace scenes { // ExtensionFieldSetsImpl::ExtensionFieldSetsImpl() : ExtensionFieldSets() {} -CHIP_ERROR ExtensionFieldSetsImpl::Serialize(TLV::TLVWriter & writer) const +CHIP_ERROR ExtensionFieldSetsImpl::Serialize(TLV::TLVWriter & writer, TLV::Tag structTag) const { TLV::TLVType container; - ReturnErrorOnFailure( - writer.StartContainer(TLV::ContextTag(TagEFS::kFieldSetArrayContainer), TLV::kTLVType_Structure, container)); - ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagEFS::kFieldSetsCount), static_cast(mFieldSetsCount))); - if (!IsEmpty()) + ReturnErrorOnFailure(writer.StartContainer(structTag, TLV::kTLVType_Structure, container)); + // ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagEFS::kFieldSetsCount), static_cast(mFieldSetsCount))); + ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(TagEFS::kFieldSetArrayContainer), TLV::kTLVType_Array, container)); + for (uint8_t i = 0; i < mFieldSetsCount; i++) { - for (uint8_t i = 0; i < mFieldSetsCount; i++) - { - if (!mFieldSets[i].IsEmpty()) - { - ReturnErrorOnFailure(mFieldSets[i].Serialize(writer)); - } - } + ReturnErrorOnFailure(mFieldSets[i].Serialize(writer)); } return writer.EndContainer(container); + return writer.EndContainer(container); } -CHIP_ERROR ExtensionFieldSetsImpl::Deserialize(TLV::TLVReader & reader) +CHIP_ERROR ExtensionFieldSetsImpl::Deserialize(TLV::TLVReader & reader, TLV::Tag structTag) { TLV::TLVType container; - ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::ContextTag(TagEFS::kFieldSetArrayContainer))); + ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, structTag)); ReturnErrorOnFailure(reader.EnterContainer(container)); - ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagEFS::kFieldSetsCount))); - ReturnErrorOnFailure(reader.Get(mFieldSetsCount)); + ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::ContextTag(TagEFS::kFieldSetArrayContainer))); + ReturnErrorOnFailure(reader.EnterContainer(container)); - if (!this->IsEmpty()) + uint8_t i = 0; + CHIP_ERROR err; + while ((err = reader.Next(TLV::AnonymousTag())) == CHIP_NO_ERROR && i < kMaxClustersPerScene) { - for (uint8_t i = 0; i < mFieldSetsCount; i++) - { - ReturnErrorOnFailure(mFieldSets[i].Deserialize(reader)); - } + ReturnErrorOnFailure(mFieldSets[i].Deserialize(reader)); + i++; } + mFieldSetsCount = i; + VerifyOrReturnError(err == CHIP_END_OF_TLV, err); return reader.ExitContainer(container); } diff --git a/src/app/clusters/scenes/ExtensionFieldSetsImpl.h b/src/app/clusters/scenes/ExtensionFieldSetsImpl.h index 9c544b4893fbe5..2525546e0cdb7a 100644 --- a/src/app/clusters/scenes/ExtensionFieldSetsImpl.h +++ b/src/app/clusters/scenes/ExtensionFieldSetsImpl.h @@ -24,16 +24,12 @@ namespace chip { namespace scenes { /// @brief Tags Used to serialize Extension Field Sets struct as well as individual field sets. -/// kArrayContainer: Tag for the container of the Struct with the EFS array -/// kFieldSetsCount: Tag representing the number of individual field sets -/// kIndividualContainer: Tag for the container of single EFS struct +/// kFieldSetArrayContainer: Tag for the container of the EFS array /// kClusterID: Tag for the ClusterID of a field set -/// kBufferBytes: Tag for the serialized field set data +/// kClusterFieldSetData: Tag for the serialized field set data enum class TagEFS : uint8_t { kFieldSetArrayContainer = 1, - kFieldSetsCount, - kIndividualContainer, kClusterID, kClusterFieldSetData, }; @@ -78,8 +74,7 @@ struct ExtensionFieldSet CHIP_ERROR Serialize(TLV::TLVWriter & writer) const { TLV::TLVType container; - ReturnErrorOnFailure( - writer.StartContainer(TLV::ContextTag(TagEFS::kIndividualContainer), TLV::kTLVType_Structure, container)); + ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container)); ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagEFS::kClusterID), mID)); ReturnErrorOnFailure(writer.PutBytes(TLV::ContextTag(TagEFS::kClusterFieldSetData), mBytesBuffer, mUsedBytes)); @@ -91,7 +86,6 @@ struct ExtensionFieldSet { ByteSpan buffer; TLV::TLVType container; - ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::ContextTag(TagEFS::kIndividualContainer))); ReturnErrorOnFailure(reader.EnterContainer(container)); ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagEFS::kClusterID))); @@ -128,8 +122,8 @@ class ExtensionFieldSetsImpl : public ExtensionFieldSets ~ExtensionFieldSetsImpl() override{}; // overrides - CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override; - CHIP_ERROR Deserialize(TLV::TLVReader & reader) override; + CHIP_ERROR Serialize(TLV::TLVWriter & writer, TLV::Tag structTag) const override; + CHIP_ERROR Deserialize(TLV::TLVReader & reader, TLV::Tag structTag) override; void Clear() override; bool IsEmpty() const override { return (mFieldSetsCount == 0); } uint8_t GetFieldSetCount() const override { return mFieldSetsCount; }; @@ -141,6 +135,11 @@ class ExtensionFieldSetsImpl : public ExtensionFieldSets // implementation bool operator==(const ExtensionFieldSetsImpl & other) const { + if (this->mFieldSetsCount != other.mFieldSetsCount) + { + return false; + } + for (uint8_t i = 0; i < mFieldSetsCount; i++) { if (!(this->mFieldSets[i] == other.mFieldSets[i])) @@ -159,6 +158,11 @@ class ExtensionFieldSetsImpl : public ExtensionFieldSets } mFieldSetsCount = other.mFieldSetsCount; + for (uint8_t i = mFieldSetsCount; i < kMaxClustersPerScene; i++) + { + this->mFieldSets[i].Clear(); + } + return *this; } diff --git a/src/app/clusters/scenes/SceneTable.h b/src/app/clusters/scenes/SceneTable.h index e0c25bcf0ee60c..5288deb537de80 100644 --- a/src/app/clusters/scenes/SceneTable.h +++ b/src/app/clusters/scenes/SceneTable.h @@ -84,6 +84,8 @@ class SceneHandler : public IntrusiveListNodeBase<> /// @param cluster[out] Cluster in the Extension field set, filled by the function /// @param serialisedBytes[out] Buffer to fill from the ExtensionFieldSet in command /// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise + /// @note Only gets called after the scene-cluster has previously verified that the endpoint,cluster valuer pair is supported by + /// the handler. It is therefore the implementation's reponsibility to also implement the SupportsCluster method. virtual CHIP_ERROR SerializeAdd(EndpointId endpoint, const app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType & extensionFieldSet, ClusterId & cluster, MutableByteSpan & serialisedBytes) = 0; @@ -103,11 +105,13 @@ class SceneHandler : public IntrusiveListNodeBase<> /// @brief Deserialize an ExtensionFieldSet into a cluster object (e.g. when handling ViewScene). /// /// @param endpoint[in] Endpoint ID - /// @param cluster[in] Cluster ID to save + /// @param cluster[in] Cluster ID /// @param serializedBytes[in] ExtensionFieldSet stored in NVM /// /// @param extensionFieldSet[out] ExtensionFieldSet in command format /// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise + /// @note Only gets called after the scene-cluster has previously verified that the endpoint,cluster valuer pair is supported by + /// the handler. It is therefore the implementation's reponsibility to also implement the SupportsCluster method. virtual CHIP_ERROR Deserialize(EndpointId endpoint, ClusterId cluster, const ByteSpan & serializedBytes, app::Clusters::Scenes::Structs::ExtensionFieldSet::Type & extensionFieldSet) = 0; @@ -149,6 +153,8 @@ class SceneTable mSceneId = kUndefinedSceneId; } + bool IsValid() { return (mEndpointId != kInvalidEndpointId) && (mSceneId != kUndefinedSceneId); } + bool operator==(const SceneStorageId & other) { return (mEndpointId == other.mEndpointId && mGroupId == other.mGroupId && mSceneId == other.mSceneId); diff --git a/src/app/clusters/scenes/SceneTableImpl.cpp b/src/app/clusters/scenes/SceneTableImpl.cpp index 835c3a9fcc06f3..fc6a7dc1233ee5 100644 --- a/src/app/clusters/scenes/SceneTableImpl.cpp +++ b/src/app/clusters/scenes/SceneTableImpl.cpp @@ -23,12 +23,24 @@ namespace chip { namespace scenes { -/// @brief Tags Used to serialize Scene specific Fabric data -/// kSceneCount: Tag for the number of scenes in Fabric -/// kGroupID: Tag for the next Fabric -enum class TagSceneImpl : uint8_t +/// @brief Tags Used to serialize Scenes so they can be stored in flash memory. +/// kSceneCount: Number of scene in a Fabric +/// kStorageIDArray: Array of StorageID struct +/// kEndpointID: Tag for the Endpoint ID to which this scene applies to +/// kGroupID: Tag for GroupID if the Scene is a Group Scene +/// kSceneID: Tag for the scene ID together with the two previous tag, forms the SceneStorageID +/// kName: Tag for the name of the scene +/// kTransitionTime: Tag for the transition time of the scene in miliseconds +enum class TagScene : uint8_t { kSceneCount = 1, + kStorageIDArray, + kEndpointID, + kGroupID, + kSceneID, + kName, + kTransitionTimeMs, + kExtensionFieldSetsContainer, }; using SceneTableEntry = DefaultSceneTableImpl::SceneTableEntry; @@ -68,12 +80,12 @@ struct SceneTableData : public SceneTableEntry, PersistentData { TLV::TLVType container; ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container)); + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kSceneCount), scene_count)); + ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(TagScene::kStorageIDArray), TLV::kTLVType_Array, container)); - ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagSceneImpl::kSceneCount), scene_count)); // Storing the scene map for (uint8_t i = 0; i < kMaxScenesPerFabric; i++) { + ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container)); ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kEndpointID), (scene_map[i].mEndpointId))); ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kGroupID), (scene_map[i].mGroupId))); - ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kID), (scene_map[i].mSceneId))); + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(TagScene::kSceneID), (scene_map[i].mSceneId))); + ReturnErrorOnFailure(writer.EndContainer(container)); } - + ReturnErrorOnFailure(writer.EndContainer(container)); return writer.EndContainer(container); } @@ -186,21 +201,29 @@ struct FabricSceneData : public PersistentData TLV::TLVType container; ReturnErrorOnFailure(reader.EnterContainer(container)); - ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagSceneImpl::kSceneCount))); + ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kSceneCount))); ReturnErrorOnFailure(reader.Get(scene_count)); + ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::ContextTag(TagScene::kStorageIDArray))); + ReturnErrorOnFailure(reader.EnterContainer(container)); uint8_t i = 0; - while (reader.Next(TLV::ContextTag(TagScene::kEndpointID)) != CHIP_END_OF_TLV) + CHIP_ERROR err; + while ((err = reader.Next(TLV::AnonymousTag())) == CHIP_NO_ERROR && i < kMaxScenesPerFabric) { + ReturnErrorOnFailure(reader.EnterContainer(container)); + ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kEndpointID))); ReturnErrorOnFailure(reader.Get(scene_map[i].mEndpointId)); ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kGroupID))); ReturnErrorOnFailure(reader.Get(scene_map[i].mGroupId)); - ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kID))); + ReturnErrorOnFailure(reader.Next(TLV::ContextTag(TagScene::kSceneID))); ReturnErrorOnFailure(reader.Get(scene_map[i].mSceneId)); + ReturnErrorOnFailure(reader.ExitContainer(container)); i++; } + VerifyOrReturnError(err == CHIP_END_OF_TLV, err); + ReturnErrorOnFailure(reader.ExitContainer(container)); return reader.ExitContainer(container); } @@ -222,7 +245,7 @@ struct FabricSceneData : public PersistentData idx = index; return CHIP_NO_ERROR; // return scene at current index if scene found } - if (scene_map[index].mEndpointId == kInvalidEndpointId && firstFreeIdx == kUndefinedSceneIndex) + if (!scene_map[index].IsValid() && firstFreeIdx == kUndefinedSceneIndex) { firstFreeIdx = index; } @@ -454,7 +477,6 @@ CHIP_ERROR DefaultSceneTableImpl::SceneApplyEFS(const SceneTableEntry & scene) if (!EFS.IsEmpty()) { - IntrusiveList::Iterator iter = mHandlerList.begin(); for (auto & handler : mHandlerList) { if (handler.SupportsCluster(scene.mStorageId.mEndpointId, cluster)) @@ -525,7 +547,7 @@ bool DefaultSceneTableImpl::SceneEntryIteratorImpl::Next(SceneTableEntry & outpu // looks for next available scene while (mSceneIndex < kMaxScenesPerFabric) { - if (fabric.scene_map[mSceneIndex].mEndpointId != kInvalidEndpointId) + if (fabric.scene_map[mSceneIndex].IsValid()) { scene.index = mSceneIndex; VerifyOrReturnError(scene.Load(mProvider.mStorage) == CHIP_NO_ERROR, false); diff --git a/src/app/clusters/scenes/SceneTableImpl.h b/src/app/clusters/scenes/SceneTableImpl.h index 87edee4bb425a1..f10b89953e4375 100644 --- a/src/app/clusters/scenes/SceneTableImpl.h +++ b/src/app/clusters/scenes/SceneTableImpl.h @@ -26,21 +26,6 @@ namespace chip { namespace scenes { -/// @brief Tags Used to serialize Scenes so they can be stored in flash memory. -/// kEndpointID: Tag for the Endpoint ID to which this scene applies to -/// kGroupID: Tag for GroupID if the Scene is a Group Scene -/// kID: Tag for the scene ID together with the two previous tag, forms the SceneStorageID -/// kName: Tag for the name of the scene -/// kTransitionTime: Tag for the transition time of the scene in miliseconds -enum class TagScene : uint8_t -{ - kEndpointID = 1, - kGroupID, - kID, - kName, - kTransitionTimeMs, -}; - using clusterId = chip::ClusterId; /// @brief Default implementation of handler, handle EFS from add scene and view scene commands for any cluster @@ -62,12 +47,11 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler /// @param extensionFieldSet[in] ExtensionFieldSets provided by the AddScene Command, pre initialized /// @param cluster[out] Cluster in the Extension field set, filled by the function /// @param serialisedBytes[out] Buffer to fill from the ExtensionFieldSet in command - /// @return CHIP_NO_ERROR if successful, CHIP_ERROR value otherwise + /// @return CHIP_NO_ERROR if successful, CHIP_ERROR_INVALID_ARGUMENT if the cluster is not supported, CHIP_ERROR value otherwise virtual CHIP_ERROR SerializeAdd(EndpointId endpoint, const app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType & extensionFieldSet, ClusterId & cluster, MutableByteSpan & serialisedBytes) override { - app::DataModel::List attributeValueList; app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType aVPair; TLV::TLVWriter writer; TLV::TLVType outer; @@ -93,15 +77,16 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler valueBytes++; } // Check we could go through all bytes of the value - VerifyOrReturnError(value_iterator.Next() == false, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorOnFailure(value_iterator.GetStatus()); + mAVPairs[pairCount].attributeValue = mValueBuffer[pairCount]; mAVPairs[pairCount].attributeValue.reduce_size(valueBytes); pairCount++; } - // Check we could go through all pairs in incomming command - VerifyOrReturnError(pair_iterator.Next() == false, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorOnFailure(pair_iterator.GetStatus()); + app::DataModel::List attributeValueList; attributeValueList = mAVPairs; attributeValueList.reduce_size(pairCount); @@ -119,7 +104,8 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler /// @param endpoint target endpoint /// @param cluster target cluster /// @param serialisedBytes data to deserialize into EFS - /// @return CHIP_NO_ERROR if Extension Field Set was successfully populated, specific CHIP_ERROR otherwise + /// @return CHIP_NO_ERROR if Extension Field Set was successfully populated, CHIP_ERROR_INVALID_ARGUMENT if the cluster is not + /// supported, specific CHIP_ERROR otherwise virtual CHIP_ERROR Deserialize(EndpointId endpoint, ClusterId cluster, const ByteSpan & serialisedBytes, app::Clusters::Scenes::Structs::ExtensionFieldSet::Type & extensionFieldSet) override { @@ -135,9 +121,11 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler extensionFieldSet.clusterID = cluster; reader.Init(serialisedBytes); - ReturnErrorOnFailure(reader.Next()); + ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())); ReturnErrorOnFailure(reader.EnterContainer(outer)); - ReturnErrorOnFailure(reader.Next()); + ReturnErrorOnFailure(reader.Next( + TLV::kTLVType_Array, + TLV::ContextTag(to_underlying(app::Clusters::Scenes::Structs::ExtensionFieldSet::Fields::kAttributeValueList)))); attributeValueList.Decode(reader); auto pair_iterator = attributeValueList.begin(); @@ -154,16 +142,16 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler valueBytes++; } // Check we could go through all bytes of the value - VerifyOrReturnError(value_iterator.Next() == false, CHIP_ERROR_BUFFER_TOO_SMALL); + ReturnErrorOnFailure(value_iterator.GetStatus()); + mAVPairs[pairCount].attributeValue = mValueBuffer[pairCount]; mAVPairs[pairCount].attributeValue.reduce_size(valueBytes); pairCount++; }; - // Check we could go through all pairs stored in memory - VerifyOrReturnError(pair_iterator.Next() == false, CHIP_ERROR_BUFFER_TOO_SMALL); - ReturnErrorOnFailure(reader.ExitContainer(outer)); + ReturnErrorOnFailure(pair_iterator.GetStatus()); + ReturnErrorOnFailure(reader.ExitContainer(outer)); extensionFieldSet.attributeValueList = mAVPairs; extensionFieldSet.attributeValueList.reduce_size(pairCount); diff --git a/src/app/tests/TestExtensionFieldSets.cpp b/src/app/tests/TestExtensionFieldSets.cpp index 718e151acb6d21..8d7ea232c9bca1 100644 --- a/src/app/tests/TestExtensionFieldSets.cpp +++ b/src/app/tests/TestExtensionFieldSets.cpp @@ -26,6 +26,12 @@ using namespace chip; namespace { +enum class TagTestEFS : uint8_t +{ + kEFS = 1, + kTestArray, +}; + static constexpr size_t kPersistentSceneBufferMax = 256; // Test Cluster ID @@ -50,6 +56,10 @@ static scenes::ExtensionFieldSetsImpl sEFSets; void TestInsertExtensionFieldSet(nlTestSuite * aSuite, void * aContext) { scenes::ExtensionFieldSetsImpl * EFS = &sEFSets; + scenes::ExtensionFieldSetsImpl testEFS1; + scenes::ExtensionFieldSetsImpl testEFS2; + scenes::ExtensionFieldSetsImpl testEFS3; + scenes::ExtensionFieldSetsImpl tempTestEFS; scenes::ExtensionFieldSet tempEFS; uint8_t empty_buffer[scenes::kMaxFieldBytesPerCluster] = { 0 }; @@ -73,6 +83,21 @@ void TestInsertExtensionFieldSet(nlTestSuite * aSuite, void * aContext) NL_TEST_ASSERT(aSuite, EFS3.mUsedBytes == kColorControlSize); NL_TEST_ASSERT(aSuite, !memcmp(colorControlBuffer, EFS3.mBytesBuffer, EFS3.mUsedBytes)); + // operator tests single EFS + tempEFS = EFS1; + NL_TEST_ASSERT(aSuite, tempEFS == EFS1); + tempEFS = EFS2; + NL_TEST_ASSERT(aSuite, tempEFS == EFS2); + tempEFS = EFS3; + NL_TEST_ASSERT(aSuite, tempEFS == EFS3); + + // Test clear EFS + tempEFS.Clear(); + NL_TEST_ASSERT(aSuite, tempEFS.IsEmpty()); + NL_TEST_ASSERT(aSuite, tempEFS.mID == kInvalidClusterId); + NL_TEST_ASSERT(aSuite, tempEFS.mUsedBytes == 0); + NL_TEST_ASSERT(aSuite, !memcmp(empty_buffer, tempEFS.mBytesBuffer, sizeof(tempEFS.mBytesBuffer))); + // Test creation of EFS from Array and ByteSpan that are to big tempEFS = scenes::ExtensionFieldSet(kOnOffClusterId, double_size_buffer, sizeof(double_size_buffer)); NL_TEST_ASSERT(aSuite, tempEFS.mID == kOnOffClusterId); @@ -93,11 +118,8 @@ void TestInsertExtensionFieldSet(nlTestSuite * aSuite, void * aContext) NL_TEST_ASSERT(aSuite, tempEFS.mUsedBytes == static_cast(sizeof(tempEFS.mBytesBuffer))); NL_TEST_ASSERT(aSuite, !memcmp(double_size_buffer, tempEFS.mBytesBuffer, sizeof(tempEFS.mBytesBuffer))); - // Test clear EFS tempEFS.Clear(); - NL_TEST_ASSERT(aSuite, tempEFS.mID == kInvalidClusterId); - NL_TEST_ASSERT(aSuite, tempEFS.mUsedBytes == 0); - NL_TEST_ASSERT(aSuite, !memcmp(empty_buffer, tempEFS.mBytesBuffer, sizeof(tempEFS.mBytesBuffer))); + NL_TEST_ASSERT(aSuite, tempEFS.IsEmpty()); // Test insertion of uninitialized EFS NL_TEST_ASSERT(aSuite, CHIP_ERROR_INVALID_ARGUMENT == EFS->InsertFieldSet(tempEFS)); @@ -108,6 +130,34 @@ void TestInsertExtensionFieldSet(nlTestSuite * aSuite, void * aContext) NL_TEST_ASSERT(aSuite, CHIP_ERROR_INVALID_ARGUMENT == EFS->InsertFieldSet(tempEFS)); NL_TEST_ASSERT(aSuite, 0 == EFS->GetFieldSetCount()); + // test operators on multiple EFS struct + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == testEFS1.InsertFieldSet(EFS1)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == testEFS1.InsertFieldSet(EFS2)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == testEFS1.InsertFieldSet(EFS3)); + + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == testEFS2.InsertFieldSet(EFS3)); + + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == testEFS3.InsertFieldSet(EFS1)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == testEFS3.InsertFieldSet(EFS2)); + + tempTestEFS = testEFS1; + NL_TEST_ASSERT(aSuite, tempTestEFS == testEFS1); + NL_TEST_ASSERT(aSuite, !(tempTestEFS == testEFS2)); + NL_TEST_ASSERT(aSuite, !(tempTestEFS == testEFS3)); + tempTestEFS = testEFS2; + NL_TEST_ASSERT(aSuite, tempTestEFS == testEFS2); + NL_TEST_ASSERT(aSuite, !(tempTestEFS == testEFS1)); + NL_TEST_ASSERT(aSuite, !(tempTestEFS == testEFS3)); + tempTestEFS = testEFS3; + NL_TEST_ASSERT(aSuite, tempTestEFS == testEFS3); + NL_TEST_ASSERT(aSuite, !(tempTestEFS == testEFS1)); + NL_TEST_ASSERT(aSuite, !(tempTestEFS == testEFS2)); + + // test clear multipler efs struct + tempTestEFS.Clear(); + NL_TEST_ASSERT(aSuite, tempTestEFS.IsEmpty()); + NL_TEST_ASSERT(aSuite, 0 == tempTestEFS.GetFieldSetCount()); + // Test insert NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == EFS->InsertFieldSet(EFS1)); NL_TEST_ASSERT(aSuite, 1 == EFS->GetFieldSetCount()); @@ -153,51 +203,39 @@ void TestSerializeDerializeExtensionFieldSet(nlTestSuite * aSuite, void * aConte // Individual Field Sets serialize / deserialize writer.Init(EFS1Buffer); - writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer); NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == EFS1.Serialize(writer)); - writer.EndContainer(outer); EFS1_serialized_length = writer.GetLengthWritten(); NL_TEST_ASSERT(aSuite, EFS1_serialized_length <= scenes::kMaxFieldBytesPerCluster); writer.Init(EFS2Buffer); - writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer); NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == EFS2.Serialize(writer)); - writer.EndContainer(outer); EFS2_serialized_length = writer.GetLengthWritten(); NL_TEST_ASSERT(aSuite, EFS2_serialized_length <= scenes::kMaxFieldBytesPerCluster); writer.Init(EFS3Buffer); - writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer); NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == EFS3.Serialize(writer)); - writer.EndContainer(outer); EFS3_serialized_length = writer.GetLengthWritten(); NL_TEST_ASSERT(aSuite, EFS3_serialized_length <= scenes::kMaxFieldBytesPerCluster); reader.Init(EFS1Buffer); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.Next()); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.EnterContainer(outerRead)); + reader.Next(TLV::AnonymousTag()); NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == tempEFS.Deserialize(reader)); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.ExitContainer(outerRead)); NL_TEST_ASSERT(aSuite, EFS1 == tempEFS); reader.Init(EFS2Buffer); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.Next()); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.EnterContainer(outerRead)); + reader.Next(TLV::AnonymousTag()); NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == tempEFS.Deserialize(reader)); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.ExitContainer(outerRead)); NL_TEST_ASSERT(aSuite, EFS2 == tempEFS); reader.Init(EFS3Buffer); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.Next()); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.EnterContainer(outerRead)); + reader.Next(TLV::AnonymousTag()); NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == tempEFS.Deserialize(reader)); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.ExitContainer(outerRead)); NL_TEST_ASSERT(aSuite, EFS3 == tempEFS); // All ExtensionFieldSets serialize / deserialize writer.Init(sceneEFSBuffer); writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == EFS->Serialize(writer)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == EFS->Serialize(writer, TLV::ContextTag(TagTestEFS::kEFS))); writer.EndContainer(outer); sceneEFS_serialized_length = writer.GetLengthWritten(); NL_TEST_ASSERT(aSuite, sceneEFS_serialized_length <= kPersistentSceneBufferMax); @@ -205,7 +243,8 @@ void TestSerializeDerializeExtensionFieldSet(nlTestSuite * aSuite, void * aConte reader.Init(sceneEFSBuffer); NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.Next()); NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.EnterContainer(outerRead)); - NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == testSceneEFS.Deserialize(reader)); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == testSceneEFS.Deserialize(reader, TLV::ContextTag(TagTestEFS::kEFS))); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == reader.ExitContainer(outerRead)); NL_TEST_ASSERT(aSuite, *EFS == testSceneEFS); } diff --git a/src/app/tests/TestSceneTable.cpp b/src/app/tests/TestSceneTable.cpp index 6bcc8f496bf67f..a2846dd8043d7f 100644 --- a/src/app/tests/TestSceneTable.cpp +++ b/src/app/tests/TestSceneTable.cpp @@ -661,6 +661,7 @@ void TestStoreScenes(nlTestSuite * aSuite, void * aContext) SceneTableEntry scene; // Set test NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == sceneTable->SetSceneTableEntry(kFabric1, scene1)); + LogErrorOnFailure(sceneTable->SetSceneTableEntry(kFabric1, scene2)); 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)); diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index 96de94294d1df4..4052c17a446bfa 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1387,7 +1387,8 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #endif /** - * @brief The maximum number of clusters per scene + * @brief The maximum number of clusters per scene, defaults to 3 for a typical usecase (onOff + level control + color control + * cluster). Needs to be changed in case a greater number of clusters is chosen. */ #ifndef CHIP_CONFIG_SCENES_MAX_CLUSTERS_PER_SCENE #define CHIP_CONFIG_SCENES_MAX_CLUSTERS_PER_SCENE 3