blob: 66b4e9e72ad891ba88b4c248ede0f458dd188eb5 [file] [log] [blame]
/*
*
* 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/clusters/scenes-server/ExtensionFieldSetsImpl.h>
#include <lib/core/TLV.h>
#include <lib/support/Span.h>
#include <lib/core/StringBuilderAdapters.h>
#include <pw_unit_test/framework.h>
using namespace chip;
namespace TestEFS {
enum class TagTestEFS : uint8_t
{
kEFS = 1,
kTestArray,
};
static constexpr size_t kPersistentSceneBufferMax = 256;
// Test Cluster ID
constexpr chip::ClusterId kOnOffClusterId = 0x0006;
constexpr chip::ClusterId kLevelControlClusterId = 0x0008;
constexpr chip::ClusterId kColorControlClusterId = 0x0300;
constexpr uint8_t kOnOffSize = 1;
constexpr uint8_t kLevelControlSize = 3;
constexpr uint8_t kColorControlSize = 14;
static uint8_t onOffBuffer[scenes::kMaxFieldBytesPerCluster] = "0";
static uint8_t levelControlBuffer[scenes::kMaxFieldBytesPerCluster] = "123";
static uint8_t colorControlBuffer[scenes::kMaxFieldBytesPerCluster] = "abcdefghijklmn";
static const scenes::ExtensionFieldSet EFS1(kOnOffClusterId, onOffBuffer, kOnOffSize);
static const scenes::ExtensionFieldSet EFS2(kLevelControlClusterId, levelControlBuffer, kLevelControlSize);
static const scenes::ExtensionFieldSet EFS3(kColorControlClusterId, colorControlBuffer, kColorControlSize);
static scenes::ExtensionFieldSetsImpl sEFSets;
class TestExtensionFieldSets : public ::testing::Test
{
public:
static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); }
static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); }
};
TEST_F(TestExtensionFieldSets, TestInsertExtensionFieldSet)
{
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 };
uint8_t double_size_buffer[scenes::kMaxFieldBytesPerCluster + 1];
ByteSpan bufferSpan(double_size_buffer);
memset(double_size_buffer, static_cast<uint8_t>(1), sizeof(double_size_buffer));
EXPECT_TRUE(EFS->IsEmpty());
// Test creators of single ExtensionFieldSet
EXPECT_EQ(EFS1.mID, kOnOffClusterId);
EXPECT_EQ(EFS1.mUsedBytes, kOnOffSize);
EXPECT_EQ(memcmp(onOffBuffer, EFS1.mBytesBuffer, EFS1.mUsedBytes), 0);
EXPECT_EQ(EFS2.mID, kLevelControlClusterId);
EXPECT_EQ(EFS2.mUsedBytes, kLevelControlSize);
EXPECT_EQ(memcmp(levelControlBuffer, EFS2.mBytesBuffer, EFS2.mUsedBytes), 0);
EXPECT_EQ(EFS3.mID, kColorControlClusterId);
EXPECT_EQ(EFS3.mUsedBytes, kColorControlSize);
EXPECT_EQ(memcmp(colorControlBuffer, EFS3.mBytesBuffer, EFS3.mUsedBytes), 0);
// operator tests single EFS
tempEFS = EFS1;
EXPECT_EQ(tempEFS, EFS1);
tempEFS = EFS2;
EXPECT_EQ(tempEFS, EFS2);
tempEFS = EFS3;
EXPECT_EQ(tempEFS, EFS3);
// Test clear EFS
tempEFS.Clear();
EXPECT_TRUE(tempEFS.IsEmpty());
EXPECT_EQ(tempEFS.mID, kInvalidClusterId);
EXPECT_EQ(tempEFS.mUsedBytes, 0);
EXPECT_EQ(memcmp(empty_buffer, tempEFS.mBytesBuffer, sizeof(tempEFS.mBytesBuffer)), 0);
// Test creation of EFS from Array and ByteSpan that are to big
tempEFS = scenes::ExtensionFieldSet(kOnOffClusterId, double_size_buffer, sizeof(double_size_buffer));
EXPECT_EQ(tempEFS.mID, kOnOffClusterId);
// Confirm EFS empty
EXPECT_EQ(tempEFS.mUsedBytes, 0);
EXPECT_EQ(memcmp(empty_buffer, tempEFS.mBytesBuffer, sizeof(empty_buffer)), 0);
tempEFS = scenes::ExtensionFieldSet(kLevelControlClusterId, bufferSpan);
EXPECT_EQ(tempEFS.mID, kLevelControlClusterId);
// Confirm EFS empty
EXPECT_EQ(tempEFS.mUsedBytes, 0);
EXPECT_EQ(memcmp(empty_buffer, tempEFS.mBytesBuffer, sizeof(empty_buffer)), 0);
// Test creation of EFS from truncating an Array
tempEFS = scenes::ExtensionFieldSet(kColorControlClusterId, double_size_buffer, sizeof(tempEFS.mBytesBuffer));
EXPECT_EQ(tempEFS.mID, kColorControlClusterId);
// Confirm EFS was written
EXPECT_EQ(tempEFS.mUsedBytes, static_cast<uint8_t>(sizeof(tempEFS.mBytesBuffer)));
EXPECT_EQ(memcmp(double_size_buffer, tempEFS.mBytesBuffer, sizeof(tempEFS.mBytesBuffer)), 0);
tempEFS.Clear();
EXPECT_TRUE(tempEFS.IsEmpty());
// Test insertion of uninitialized EFS
EXPECT_EQ(CHIP_ERROR_INVALID_ARGUMENT, EFS->InsertFieldSet(tempEFS));
EXPECT_EQ(0, EFS->GetFieldSetCount());
// Test insertion of empty EFS
tempEFS.mID = kOnOffClusterId;
EXPECT_EQ(CHIP_ERROR_INVALID_ARGUMENT, EFS->InsertFieldSet(tempEFS));
EXPECT_EQ(0, EFS->GetFieldSetCount());
// test operators on multiple EFS struct
EXPECT_EQ(CHIP_NO_ERROR, testEFS1.InsertFieldSet(EFS1));
EXPECT_EQ(CHIP_NO_ERROR, testEFS1.InsertFieldSet(EFS2));
EXPECT_EQ(CHIP_NO_ERROR, testEFS1.InsertFieldSet(EFS3));
EXPECT_EQ(CHIP_NO_ERROR, testEFS2.InsertFieldSet(EFS3));
EXPECT_EQ(CHIP_NO_ERROR, testEFS3.InsertFieldSet(EFS1));
EXPECT_EQ(CHIP_NO_ERROR, testEFS3.InsertFieldSet(EFS2));
tempTestEFS = testEFS1;
EXPECT_EQ(tempTestEFS, testEFS1);
EXPECT_FALSE(tempTestEFS == testEFS2);
EXPECT_FALSE(tempTestEFS == testEFS3);
tempTestEFS = testEFS2;
EXPECT_EQ(tempTestEFS, testEFS2);
EXPECT_FALSE(tempTestEFS == testEFS1);
EXPECT_FALSE(tempTestEFS == testEFS3);
tempTestEFS = testEFS3;
EXPECT_EQ(tempTestEFS, testEFS3);
EXPECT_FALSE(tempTestEFS == testEFS1);
EXPECT_FALSE(tempTestEFS == testEFS2);
// test clear multipler efs struct
tempTestEFS.Clear();
EXPECT_TRUE(tempTestEFS.IsEmpty());
EXPECT_EQ(0, tempTestEFS.GetFieldSetCount());
// Test insert
EXPECT_EQ(CHIP_NO_ERROR, EFS->InsertFieldSet(EFS1));
EXPECT_EQ(1, EFS->GetFieldSetCount());
EXPECT_EQ(CHIP_NO_ERROR, EFS->InsertFieldSet(EFS2));
EXPECT_EQ(2, EFS->GetFieldSetCount());
EXPECT_EQ(CHIP_NO_ERROR, EFS->InsertFieldSet(EFS3));
EXPECT_EQ(3, EFS->GetFieldSetCount());
// Test get
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 0));
EXPECT_EQ(tempEFS, EFS1);
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 1));
EXPECT_EQ(tempEFS, EFS2);
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 2));
EXPECT_EQ(tempEFS, EFS3);
}
TEST_F(TestExtensionFieldSets, TestSerializeDerializeExtensionFieldSet)
{
scenes::ExtensionFieldSetsImpl * EFS = &sEFSets;
scenes::ExtensionFieldSetsImpl testSceneEFS;
scenes::ExtensionFieldSet tempEFS;
uint8_t EFS1Buffer[scenes::kMaxFieldBytesPerCluster] = { 0 };
uint8_t EFS2Buffer[scenes::kMaxFieldBytesPerCluster] = { 0 };
uint8_t EFS3Buffer[scenes::kMaxFieldBytesPerCluster] = { 0 };
uint8_t sceneEFSBuffer[kPersistentSceneBufferMax] = { 0 };
uint32_t EFS1_serialized_length = 0;
uint32_t EFS2_serialized_length = 0;
uint32_t EFS3_serialized_length = 0;
uint32_t sceneEFS_serialized_length = 0;
TLV::TLVReader reader;
TLV::TLVWriter writer;
TLV::TLVType outer;
TLV::TLVType outerRead;
// Individual Field Sets serialize / deserialize
writer.Init(EFS1Buffer);
EXPECT_EQ(CHIP_NO_ERROR, EFS1.Serialize(writer));
EFS1_serialized_length = writer.GetLengthWritten();
EXPECT_LE(EFS1_serialized_length, scenes::kMaxFieldBytesPerCluster);
writer.Init(EFS2Buffer);
EXPECT_EQ(CHIP_NO_ERROR, EFS2.Serialize(writer));
EFS2_serialized_length = writer.GetLengthWritten();
EXPECT_LE(EFS2_serialized_length, scenes::kMaxFieldBytesPerCluster);
writer.Init(EFS3Buffer);
EXPECT_EQ(CHIP_NO_ERROR, EFS3.Serialize(writer));
EFS3_serialized_length = writer.GetLengthWritten();
EXPECT_LE(EFS3_serialized_length, scenes::kMaxFieldBytesPerCluster);
reader.Init(EFS1Buffer);
reader.Next(TLV::AnonymousTag());
EXPECT_EQ(CHIP_NO_ERROR, tempEFS.Deserialize(reader));
EXPECT_EQ(EFS1, tempEFS);
reader.Init(EFS2Buffer);
reader.Next(TLV::AnonymousTag());
EXPECT_EQ(CHIP_NO_ERROR, tempEFS.Deserialize(reader));
EXPECT_EQ(EFS2, tempEFS);
reader.Init(EFS3Buffer);
reader.Next(TLV::AnonymousTag());
EXPECT_EQ(CHIP_NO_ERROR, tempEFS.Deserialize(reader));
EXPECT_EQ(EFS3, tempEFS);
// All ExtensionFieldSets serialize / deserialize
writer.Init(sceneEFSBuffer);
writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer);
EXPECT_EQ(CHIP_NO_ERROR, EFS->Serialize(writer));
writer.EndContainer(outer);
sceneEFS_serialized_length = writer.GetLengthWritten();
EXPECT_LE(sceneEFS_serialized_length, kPersistentSceneBufferMax);
reader.Init(sceneEFSBuffer);
EXPECT_EQ(CHIP_NO_ERROR, reader.Next());
EXPECT_EQ(CHIP_NO_ERROR, reader.EnterContainer(outerRead));
EXPECT_EQ(CHIP_NO_ERROR, testSceneEFS.Deserialize(reader));
EXPECT_EQ(CHIP_NO_ERROR, reader.ExitContainer(outerRead));
EXPECT_EQ(*EFS, testSceneEFS);
}
TEST_F(TestExtensionFieldSets, TestRemoveExtensionFieldSet)
{
scenes::ExtensionFieldSetsImpl * EFS = &sEFSets;
scenes::ExtensionFieldSet tempEFS;
// Order in EFS at this point: [EFS1, EFS2, EFS3]
// Removal at beginning
EXPECT_EQ(CHIP_NO_ERROR, EFS->RemoveFieldAtPosition(0));
EXPECT_EQ(2, EFS->GetFieldSetCount());
EXPECT_EQ(CHIP_NO_ERROR, EFS->InsertFieldSet(EFS1));
EXPECT_EQ(3, EFS->GetFieldSetCount());
// Verify order
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 0));
EXPECT_EQ(tempEFS, EFS2);
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 1));
EXPECT_EQ(tempEFS, EFS3);
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 2));
EXPECT_EQ(tempEFS, EFS1);
// Order in EFS at this point: [EFS2, EFS3, EFS1]
// Removal at middle
EXPECT_EQ(CHIP_NO_ERROR, EFS->RemoveFieldAtPosition(1));
EXPECT_EQ(2, EFS->GetFieldSetCount());
EXPECT_EQ(CHIP_NO_ERROR, EFS->InsertFieldSet(EFS3));
EXPECT_EQ(3, EFS->GetFieldSetCount());
// Verify order
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 0));
EXPECT_EQ(tempEFS, EFS2);
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 1));
EXPECT_EQ(tempEFS, EFS1);
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 2));
EXPECT_EQ(tempEFS, EFS3);
// Order in EFS at this point: [EFS2, EFS1, EFS3]
// Removal at end
EXPECT_EQ(CHIP_NO_ERROR, EFS->RemoveFieldAtPosition(2));
EXPECT_EQ(2, EFS->GetFieldSetCount());
EXPECT_EQ(CHIP_NO_ERROR, EFS->InsertFieldSet(EFS3));
EXPECT_EQ(3, EFS->GetFieldSetCount());
// Verify order
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 0));
EXPECT_EQ(tempEFS, EFS2);
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 1));
EXPECT_EQ(tempEFS, EFS1);
EXPECT_EQ(CHIP_NO_ERROR, EFS->GetFieldSetAtPosition(tempEFS, 2));
EXPECT_EQ(tempEFS, EFS3);
// Emptying the table
EFS->Clear();
EXPECT_TRUE(EFS->IsEmpty());
}
} // namespace TestEFS