blob: 61d33e0d55008a75ee05a1111cb3cf6f11d82321 [file] [log] [blame]
/*
*
* Copyright (c) 2021 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.
*/
/**
* @file
* This file implements unit tests for CHIP Interaction Model Command Interaction
*
*/
#include <app/common/cluster-objects.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/UnitTestRegistration.h>
#include <nlunit-test.h>
#include <system/SystemPacketBuffer.h>
#include <system/TLVPacketBufferBackingStore.h>
using namespace chip;
using namespace chip::app;
class TestDataModelSerialization
{
public:
static void TestDataModelSerialization_EncAndDecSimpleStruct(nlTestSuite * apSuite, void * apContext);
static void TestDataModelSerialization_EncAndDecNestedStruct(nlTestSuite * apSuite, void * apContext);
static void TestDataModelSerialization_EncAndDecNestedStructList(nlTestSuite * apSuite, void * apContext);
static void TestDataModelSerialization_EncAndDecDecodableNestedStructList(nlTestSuite * apSuite, void * apContext);
static void TestDataModelSerialization_EncAndDecDecodableDoubleNestedStructList(nlTestSuite * apSuite, void * apContext);
static void TestDataModelSerialization_OptionalFields(nlTestSuite * apSuite, void * apContext);
static void TestDataModelSerialization_ExtraField(nlTestSuite * apSuite, void * apContext);
static void TestDataModelSerialization_InvalidSimpleFieldTypes(nlTestSuite * apSuite, void * apContext);
static void TestDataModelSerialization_InvalidListType(nlTestSuite * apSuite, void * apContext);
void Shutdown();
private:
void SetupBuf();
void DumpBuf();
void SetupReader();
System::TLVPacketBufferBackingStore mStore;
TLV::TLVWriter mWriter;
TLV::TLVReader mReader;
nlTestSuite * mpSuite;
};
using namespace TLV;
TestDataModelSerialization gTestDataModelSerialization;
void TestDataModelSerialization::SetupBuf()
{
System::PacketBufferHandle buf;
buf = System::PacketBufferHandle::New(1024);
mStore.Init(std::move(buf));
mWriter.Init(mStore);
mReader.Init(mStore);
}
void TestDataModelSerialization::Shutdown()
{
System::PacketBufferHandle buf = mStore.Release();
}
void TestDataModelSerialization::DumpBuf()
{
TLV::TLVReader reader;
reader.Init(mStore);
//
// Enable this once the TLV pretty printer has been checked in.
//
#if ENABLE_TLV_PRINT_OUT
TLV::Debug::Print(reader);
#endif
}
void TestDataModelSerialization::SetupReader()
{
CHIP_ERROR err;
mReader.Init(mStore);
err = mReader.Next();
NL_TEST_ASSERT(mpSuite, err == CHIP_NO_ERROR);
}
template <typename T>
struct TagValuePair
{
uint64_t tag;
T & value;
};
template <typename T>
TagValuePair<T> MakeTagValuePair(uint64_t tag, T & value)
{
return TagValuePair<T>{ tag, value };
}
template <typename... ArgTypes>
CHIP_ERROR EncodeStruct(TLV::TLVWriter & writer, uint64_t tag, ArgTypes... Args)
{
using expand_type = int[];
TLV::TLVType type;
ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, type));
(void) (expand_type{ (DataModel::Encode(writer, Args.tag, Args.value), 0)... });
ReturnErrorOnFailure(writer.EndContainer(type));
return CHIP_NO_ERROR;
}
bool StringMatches(Span<const char> str1, const char * str2)
{
if (str1.data() == nullptr || str2 == nullptr)
{
return false;
}
if (str1.size() != strlen(str2))
{
return false;
}
return (strncmp(str1.data(), str2, str1.size()) == 0);
}
void TestDataModelSerialization::TestDataModelSerialization_EncAndDecSimpleStruct(nlTestSuite * apSuite, void * apContext)
{
CHIP_ERROR err;
auto * _this = static_cast<TestDataModelSerialization *>(apContext);
_this->mpSuite = apSuite;
_this->SetupBuf();
//
// Encode
//
{
clusters::TestCluster::SimpleStruct::Type t;
uint8_t buf[4] = { 0, 1, 2, 3 };
char strbuf[10] = "chip";
t.a = 20;
t.b = true;
t.c = clusters::TestCluster::SimpleEnum::VALUEA;
t.d = buf;
t.e = Span<char>{ strbuf, strlen(strbuf) };
err = DataModel::Encode(_this->mWriter, TLV::AnonymousTag, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::SimpleStruct::Type t;
_this->SetupReader();
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, t.a == 20);
NL_TEST_ASSERT(apSuite, t.b == true);
NL_TEST_ASSERT(apSuite, t.c == clusters::TestCluster::SimpleEnum::VALUEA);
NL_TEST_ASSERT(apSuite, t.d.size() == 4);
for (uint32_t i = 0; i < t.d.size(); i++)
{
NL_TEST_ASSERT(apSuite, t.d.data()[i] == i);
}
NL_TEST_ASSERT(apSuite, StringMatches(t.e, "chip"));
}
}
void TestDataModelSerialization::TestDataModelSerialization_EncAndDecNestedStruct(nlTestSuite * apSuite, void * apContext)
{
CHIP_ERROR err;
auto * _this = static_cast<TestDataModelSerialization *>(apContext);
_this->mpSuite = apSuite;
_this->SetupBuf();
//
// Encode
//
{
clusters::TestCluster::NestedStruct::Type t;
uint8_t buf[4] = { 0, 1, 2, 3 };
char strbuf[10] = "chip";
t.a = 20;
t.b = true;
t.c.a = 11;
t.c.b = true;
t.c.c = clusters::TestCluster::SimpleEnum::VALUEB;
t.c.d = buf;
t.c.e = Span<char>{ strbuf, strlen(strbuf) };
err = DataModel::Encode(_this->mWriter, TLV::AnonymousTag, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::NestedStruct::Type t;
_this->SetupReader();
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, t.a == 20);
NL_TEST_ASSERT(apSuite, t.b == true);
NL_TEST_ASSERT(apSuite, t.c.a == 11);
NL_TEST_ASSERT(apSuite, t.c.b == true);
NL_TEST_ASSERT(apSuite, t.c.c == clusters::TestCluster::SimpleEnum::VALUEB);
NL_TEST_ASSERT(apSuite, t.c.d.size() == 4);
for (uint32_t i = 0; i < t.c.d.size(); i++)
{
NL_TEST_ASSERT(apSuite, t.c.d.data()[i] == i);
}
NL_TEST_ASSERT(apSuite, StringMatches(t.c.e, "chip"));
}
}
void TestDataModelSerialization::TestDataModelSerialization_EncAndDecDecodableNestedStructList(nlTestSuite * apSuite,
void * apContext)
{
CHIP_ERROR err;
auto * _this = static_cast<TestDataModelSerialization *>(apContext);
_this->mpSuite = apSuite;
_this->SetupBuf();
//
// Encode
//
{
clusters::TestCluster::NestedStructList::Type t;
uint8_t buf[4] = { 0, 1, 2, 3 };
uint32_t intBuf[4] = { 10000, 10001, 10002, 10003 };
char strbuf[10] = "chip";
clusters::TestCluster::SimpleStruct::Type structList[4];
uint8_t i = 0;
ByteSpan spanList[4];
t.a = 20;
t.b = true;
t.c.a = 11;
t.c.b = true;
t.c.c = clusters::TestCluster::SimpleEnum::VALUEB;
t.c.d = buf;
t.e = intBuf;
for (auto & item : structList)
{
item.a = i;
item.b = true;
i++;
}
t.f = spanList;
spanList[0] = buf;
spanList[1] = buf;
spanList[2] = buf;
spanList[3] = buf;
t.g = buf;
t.c.e = Span<char>{ strbuf, strlen(strbuf) };
t.d = structList;
err = DataModel::Encode(_this->mWriter, TLV::AnonymousTag, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::NestedStructList::DecodableType t;
int i;
_this->SetupReader();
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, t.a == 20);
NL_TEST_ASSERT(apSuite, t.b == true);
NL_TEST_ASSERT(apSuite, t.c.a == 11);
NL_TEST_ASSERT(apSuite, t.c.b == true);
NL_TEST_ASSERT(apSuite, t.c.c == clusters::TestCluster::SimpleEnum::VALUEB);
NL_TEST_ASSERT(apSuite, StringMatches(t.c.e, "chip"));
{
i = 0;
auto iter = t.d.begin();
while (iter.Next())
{
auto & item = iter.GetValue();
NL_TEST_ASSERT(apSuite, item.a == static_cast<uint8_t>(i));
NL_TEST_ASSERT(apSuite, item.b == true);
i++;
}
NL_TEST_ASSERT(apSuite, iter.GetStatus() == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, i == 4);
}
{
i = 0;
auto iter = t.e.begin();
while (iter.Next())
{
auto & item = iter.GetValue();
NL_TEST_ASSERT(apSuite, item == static_cast<uint32_t>(i + 10000));
i++;
}
NL_TEST_ASSERT(apSuite, iter.GetStatus() == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, i == 4);
}
{
i = 0;
auto iter = t.f.begin();
while (iter.Next())
{
auto & item = iter.GetValue();
unsigned int j = 0;
for (; j < item.size(); j++)
{
NL_TEST_ASSERT(apSuite, item.data()[j] == j);
}
NL_TEST_ASSERT(apSuite, j == 4);
i++;
}
NL_TEST_ASSERT(apSuite, iter.GetStatus() == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, i == 4);
}
{
i = 0;
auto iter = t.g.begin();
while (iter.Next())
{
auto & item = iter.GetValue();
NL_TEST_ASSERT(apSuite, item == i);
i++;
}
NL_TEST_ASSERT(apSuite, iter.GetStatus() == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, i == 4);
}
}
}
void TestDataModelSerialization::TestDataModelSerialization_EncAndDecDecodableDoubleNestedStructList(nlTestSuite * apSuite,
void * apContext)
{
CHIP_ERROR err;
auto * _this = static_cast<TestDataModelSerialization *>(apContext);
_this->mpSuite = apSuite;
_this->SetupBuf();
//
// Encode
//
{
clusters::TestCluster::DoubleNestedStructList::Type t;
clusters::TestCluster::NestedStructList::Type n[4];
clusters::TestCluster::SimpleStruct::Type structList[4];
uint8_t i;
t.a = n;
i = 0;
for (auto & item : structList)
{
item.a = static_cast<uint8_t>(35 + i);
i++;
}
for (auto & item : n)
{
item.d = structList;
}
err = DataModel::Encode(_this->mWriter, TLV::AnonymousTag, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::DoubleNestedStructList::DecodableType t;
_this->SetupReader();
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
uint8_t i = 0;
auto iter = t.a.begin();
while (iter.Next())
{
auto & item = iter.GetValue();
auto nestedIter = item.d.begin();
unsigned int j = 0;
while (nestedIter.Next())
{
auto & nestedItem = nestedIter.GetValue();
NL_TEST_ASSERT(apSuite, nestedItem.a == (static_cast<uint8_t>(35) + j));
j++;
}
NL_TEST_ASSERT(apSuite, j == 4);
i++;
}
NL_TEST_ASSERT(apSuite, iter.GetStatus() == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, i == 4);
}
}
void TestDataModelSerialization::TestDataModelSerialization_OptionalFields(nlTestSuite * apSuite, void * apContext)
{
CHIP_ERROR err;
auto * _this = static_cast<TestDataModelSerialization *>(apContext);
_this->mpSuite = apSuite;
_this->SetupBuf();
//
// Encode
//
{
clusters::TestCluster::SimpleStruct::Type t;
uint8_t buf[4] = { 0, 1, 2, 3 };
char strbuf[10] = "chip";
t.a = 20;
t.b = true;
t.c = clusters::TestCluster::SimpleEnum::VALUEA;
t.d = buf;
t.e = Span<char>{ strbuf, strlen(strbuf) };
// Encode every field manually except a.
{
err = EncodeStruct(_this->mWriter, TLV::AnonymousTag,
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kBFieldId), t.b),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kCFieldId), t.c),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kDFieldId), t.d),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kEFieldId), t.e));
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
}
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::SimpleStruct::Type t;
_this->SetupReader();
// Set the value of a to a specific value, and ensure it is not over-written after decode.
t.a = 150;
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
// Ensure that the decoder did not over-write the value set in the generated object
NL_TEST_ASSERT(apSuite, t.a == 150);
NL_TEST_ASSERT(apSuite, t.b == true);
NL_TEST_ASSERT(apSuite, t.c == clusters::TestCluster::SimpleEnum::VALUEA);
NL_TEST_ASSERT(apSuite, t.d.size() == 4);
for (uint32_t i = 0; i < t.d.size(); i++)
{
NL_TEST_ASSERT(apSuite, t.d.data()[i] == i);
}
NL_TEST_ASSERT(apSuite, StringMatches(t.e, "chip"));
}
}
void TestDataModelSerialization::TestDataModelSerialization_ExtraField(nlTestSuite * apSuite, void * apContext)
{
CHIP_ERROR err;
auto * _this = static_cast<TestDataModelSerialization *>(apContext);
_this->mpSuite = apSuite;
_this->SetupBuf();
//
// Encode
//
{
clusters::TestCluster::SimpleStruct::Type t;
uint8_t buf[4] = { 0, 1, 2, 3 };
char strbuf[10] = "chip";
t.a = 20;
t.b = true;
t.c = clusters::TestCluster::SimpleEnum::VALUEA;
t.d = buf;
t.e = Span<char>{ strbuf, strlen(strbuf) };
// Encode every field + an extra field.
{
err = EncodeStruct(_this->mWriter, TLV::AnonymousTag,
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kAFieldId), t.a),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kBFieldId), t.b),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kCFieldId), t.c),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kDFieldId), t.d),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kEFieldId), t.e),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kEFieldId + 1), t.a));
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
}
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::SimpleStruct::Type t;
_this->SetupReader();
// Ensure successful decode despite the extra field.
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, t.a == 20);
NL_TEST_ASSERT(apSuite, t.b == true);
NL_TEST_ASSERT(apSuite, t.c == clusters::TestCluster::SimpleEnum::VALUEA);
NL_TEST_ASSERT(apSuite, t.d.size() == 4);
for (uint32_t i = 0; i < t.d.size(); i++)
{
NL_TEST_ASSERT(apSuite, t.d.data()[i] == i);
}
NL_TEST_ASSERT(apSuite, StringMatches(t.e, "chip"));
}
}
void TestDataModelSerialization::TestDataModelSerialization_InvalidSimpleFieldTypes(nlTestSuite * apSuite, void * apContext)
{
CHIP_ERROR err;
auto * _this = static_cast<TestDataModelSerialization *>(apContext);
_this->mpSuite = apSuite;
_this->SetupBuf();
//
// Case #1: Swap out field a (an integer) with a boolean.
//
{
//
// Encode
//
{
clusters::TestCluster::SimpleStruct::Type t;
uint8_t buf[4] = { 0, 1, 2, 3 };
char strbuf[10] = "chip";
t.a = 20;
t.b = true;
t.c = clusters::TestCluster::SimpleEnum::VALUEA;
t.d = buf;
t.e = Span<char>{ strbuf, strlen(strbuf) };
// Encode every field manually except a.
{
err = EncodeStruct(_this->mWriter, TLV::AnonymousTag,
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kAFieldId), t.b),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kBFieldId), t.b),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kCFieldId), t.c),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kDFieldId), t.d),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kEFieldId), t.e));
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
}
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::SimpleStruct::Type t;
_this->SetupReader();
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err != CHIP_NO_ERROR);
}
}
_this->SetupBuf();
//
// Case #2: Swap out an octet string with a UTF-8 string.
//
{
//
// Encode
//
{
clusters::TestCluster::SimpleStruct::Type t;
uint8_t buf[4] = { 0, 1, 2, 3 };
char strbuf[10] = "chip";
t.a = 20;
t.b = true;
t.c = clusters::TestCluster::SimpleEnum::VALUEA;
t.d = buf;
t.e = Span<char>{ strbuf, strlen(strbuf) };
// Encode every field manually except a.
{
err = EncodeStruct(_this->mWriter, TLV::AnonymousTag,
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kAFieldId), t.a),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kBFieldId), t.b),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kCFieldId), t.c),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kDFieldId), t.e),
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::SimpleStruct::kEFieldId), t.e));
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
}
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::SimpleStruct::Type t;
_this->SetupReader();
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err != CHIP_NO_ERROR);
}
}
}
void TestDataModelSerialization::TestDataModelSerialization_InvalidListType(nlTestSuite * apSuite, void * apContext)
{
CHIP_ERROR err;
auto * _this = static_cast<TestDataModelSerialization *>(apContext);
_this->mpSuite = apSuite;
_this->SetupBuf();
//
// Encode
//
{
clusters::TestCluster::NestedStructList::Type t;
uint32_t intBuf[4] = { 10000, 10001, 10002, 10003 };
t.e = intBuf;
// Encode a list of integers for field d instead of a list of structs.
{
err = EncodeStruct(_this->mWriter, TLV::AnonymousTag,
MakeTagValuePair(TLV::ContextTag(clusters::TestCluster::NestedStructList::kDFieldId), t.e));
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
}
err = _this->mWriter.Finalize();
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
_this->DumpBuf();
}
//
// Decode
//
{
clusters::TestCluster::NestedStructList::DecodableType t;
_this->SetupReader();
err = DataModel::Decode(_this->mReader, t);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
auto iter = t.d.begin();
bool hadItems = false;
while (iter.Next())
{
hadItems = true;
}
NL_TEST_ASSERT(apSuite, iter.GetStatus() != CHIP_NO_ERROR);
NL_TEST_ASSERT(apSuite, !hadItems);
}
}
int Initialize(void * apSuite)
{
VerifyOrReturnError(chip::Platform::MemoryInit() == CHIP_NO_ERROR, FAILURE);
return SUCCESS;
}
int Finalize(void * aContext)
{
gTestDataModelSerialization.Shutdown();
chip::Platform::MemoryShutdown();
return SUCCESS;
}
// clang-format off
const nlTest sTests[] =
{
NL_TEST_DEF("TestDataModelSerialization_EncAndDecSimple", TestDataModelSerialization::TestDataModelSerialization_EncAndDecSimpleStruct),
NL_TEST_DEF("TestDataModelSerialization_EncAndDecNestedStruct", TestDataModelSerialization::TestDataModelSerialization_EncAndDecNestedStruct),
NL_TEST_DEF("TestDataModelSerialization_EncAndDecDecodableNestedStructList", TestDataModelSerialization::TestDataModelSerialization_EncAndDecDecodableNestedStructList),
NL_TEST_DEF("TestDataModelSerialization_EncAndDecDecodableDoubleNestedStructList", TestDataModelSerialization::TestDataModelSerialization_EncAndDecDecodableDoubleNestedStructList),
NL_TEST_DEF("TestDataModelSerialization_OptionalFields", TestDataModelSerialization::TestDataModelSerialization_OptionalFields),
NL_TEST_DEF("TestDataModelSerialization_ExtraField", TestDataModelSerialization::TestDataModelSerialization_ExtraField),
NL_TEST_DEF("TestDataModelSerialization_InvalidSimpleFieldTypes", TestDataModelSerialization::TestDataModelSerialization_InvalidSimpleFieldTypes),
NL_TEST_DEF("TestDataModelSerialization_InvalidListType", TestDataModelSerialization::TestDataModelSerialization_InvalidListType),
NL_TEST_SENTINEL()
};
// clang-format on
nlTestSuite theSuite = { "TestDataModelSerialization", &sTests[0], Initialize, Finalize };
int DataModelSerializationTest()
{
nlTestRunner(&theSuite, &gTestDataModelSerialization);
return (nlTestRunnerStats(&theSuite));
}
CHIP_REGISTER_TEST_SUITE(DataModelSerializationTest)