blob: 0a848e5de8f8352cd495825c0fd13622dd7bdc7c [file] [log] [blame]
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* 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 <lib/core/TLVWriter.h>
#include <lib/format/protocol_decoder.h>
#include <lib/support/StringBuilder.h>
#include <lib/support/UnitTestRegistration.h>
#include <tlv/meta/clusters_meta.h>
#include <tlv/meta/protocols_meta.h>
#include <nlunit-test.h>
#include "sample_data.h"
namespace {
using namespace chip::Decoders;
using namespace chip::FlatTree;
using namespace chip::TLV;
using namespace chip::TLVMeta;
using namespace chip::TestData;
// size 1 to avoid compilers complaining about empty arrays
// (not allowed by ISO 9899:2011 6.7.6.2:
// If the expression is a constant expression, it shall have a value greater
// than zero.
// ). We still claim its size is 0 in empty_meta though.
const Entry<ItemInfo> _empty_item[1] = {};
const std::array<const Node<ItemInfo>, 1> empty_meta = { { { 0, _empty_item } } };
const Entry<ItemInfo> _FakeProtocolData[] = {
{ { AttributeTag(5), "proto5", ItemType::kDefault }, kInvalidNodeIndex },
{ { AttributeTag(16), "proto16", ItemType::kDefault }, kInvalidNodeIndex },
};
const Entry<ItemInfo> _FakeProtocols[] = {
{ { ClusterTag(0xFFFF0000), "FakeSC", ItemType::kDefault }, 1 },
{ { ClusterTag(0xFFFF0001), "FakeIM", ItemType::kDefault }, 1 },
};
const std::array<const Node<ItemInfo>, 53 + 2> fake_protocols_meta = { {
{ 2, _FakeProtocols },
{ 2, _FakeProtocolData },
} };
void TestSampleData(nlTestSuite * inSuite, const PayloadDecoderInitParams & params, const SamplePayload & data,
const char * expectation)
{
chip::Decoders::PayloadDecoder<64, 128> decoder(
PayloadDecoderInitParams(params).SetProtocol(data.protocolId).SetMessageType(data.messageType));
decoder.StartDecoding(data.payload);
chip::StringBuilder<4096> output_builder;
PayloadEntry entry;
int nesting = 0;
while (decoder.Next(entry))
{
switch (entry.GetType())
{
case PayloadEntry::IMPayloadType::kNestingExit:
nesting--;
continue;
case PayloadEntry::IMPayloadType::kAttribute:
output_builder.AddFormat("%*sATTRIBUTE: %" PRIi32 "/%" PRIi32 "\n", nesting * 2, "", entry.GetClusterId(),
entry.GetAttributeId());
continue;
case PayloadEntry::IMPayloadType::kCommand:
output_builder.AddFormat("%*sCOMMAND: %" PRIi32 "/%" PRIi32 "\n", nesting * 2, "", entry.GetClusterId(),
entry.GetCommandId());
continue;
case PayloadEntry::IMPayloadType::kEvent:
output_builder.AddFormat("%*sEVENT: %" PRIi32 "/%" PRIi32 "\n", nesting * 2, "", entry.GetClusterId(),
entry.GetEventId());
continue;
default:
break;
}
output_builder.AddFormat("%*s%s", nesting * 2, "", entry.GetName());
if (entry.GetType() == PayloadEntry::IMPayloadType::kNestingEnter)
{
nesting++;
}
else if (entry.GetValueText()[0] != '\0')
{
output_builder.AddFormat(": %s", entry.GetValueText());
}
else
{
output_builder.Add(": EMPTY");
}
output_builder.AddFormat("\n");
}
output_builder.AddMarkerIfOverflow();
if (strcmp(output_builder.c_str(), expectation) != 0)
{
printf("!!!!!!!!!!!!!!!!!!! EXPECTED OUTPUT !!!!!!!!!!!!!!!!!\n");
printf("%s\n", expectation);
printf("!!!!!!!!!!!!!!!!!!! ACTUAL OUTPUT !!!!!!!!!!!!!!!!!\n");
printf("%s\n", output_builder.c_str());
unsigned idx = 0;
while (expectation[idx] == output_builder.c_str()[idx])
{
idx++;
}
printf("!!!!!!!!!!!!!!!!!!! DIFF LOCATION !!!!!!!!!!!!!!!!!\n");
printf("First diff at index %u\n", idx);
chip::StringBuilder<31> partial;
printf("EXPECT: '%s'\n", partial.Reset().Add(expectation + idx).AddMarkerIfOverflow().c_str());
printf("ACTUAL: '%s'\n", partial.Reset().Add(output_builder.c_str() + idx).AddMarkerIfOverflow().c_str());
}
NL_TEST_ASSERT(inSuite, strcmp(output_builder.c_str(), expectation) == 0);
}
void TestFullDataDecoding(nlTestSuite * inSuite, void * inContext)
{
PayloadDecoderInitParams params;
params.SetProtocolDecodeTree(chip::TLVMeta::protocols_meta).SetClusterDecodeTree(chip::TLVMeta::clusters_meta);
TestSampleData(inSuite, params, secure_channel_mrp_ack, "mrp_ack: EMPTY\n");
TestSampleData(inSuite, params, secure_channel_pkbdf_param_request,
"pbkdf_param_request\n"
" initiator_random: hex:7C8698755B8E9866BB4FFDC27B733F3B6EF7F83D43FBE0CA6AD2B8C52C8F4236\n"
" initiator_session_id: 37677\n"
" passcode_id: 0\n"
" has_pbkdf_parameters: false\n");
TestSampleData(inSuite, params, secure_channel_pkbdf_param_response,
"pbkdf_param_response\n"
" initiator_random: hex:7C8698755B8E9866BB4FFDC27B733F3B6EF7F83D43FBE0CA6AD2B8C52C8F4236\n"
" responder_random: hex:A44EB3E1A751A88A32BAB59EF16EB9764C20E1A9DDBEF6EFE3F588C943C58424\n"
" responder_session_id: 40168\n"
" pbkdf_parameters\n"
" iterations: 1000\n"
" salt: hex:E8FC1E6FD0023422B3CA7ECEDD344444551C814D3D0B0EB9C096F00E8A8051B2\n");
TestSampleData(inSuite, params, secure_channel_pase_pake1,
// clang-format off
"pase_pake1\n"
" pA: hex:0422ABC7A84352850456BD4A510905FE6BB782A0863A9382550E1228020801B22EEC4102C60F80082842B9739705FCD37F134651442A41E3723DFFE0...\n"
// clang-format on
);
TestSampleData(inSuite, params, secure_channel_pase_pake2,
// clang-format off
"pase_pake2\n"
" pB: hex:04B6A44A3347C6B77900A3674CA19F40F25F056F8CB344EC1B4FA7888B9E6B570B7010431C5D0BE4021FE74A96C40721765FDA6802BE8DFDF5624332...\n"
" cB: hex:40E7452275E38AEBAF0E0F6FAB33A1B0CB5AEB5E824230DD40D0071DC7E55C87\n"
// clang-format on
);
TestSampleData(inSuite, params, secure_channel_pase_pake3,
"pase_pake3\n"
" cA: hex:6008C72EDEC9D25D4A36522F0BF23058F9378EFE38CBBCCE8C6853900169BC38\n");
TestSampleData(inSuite, params, secure_channel_status_report, "status_report: BINARY DATA\n");
TestSampleData(inSuite, params, im_protocol_read_request,
"read_request\n"
" attribute_requests\n"
" Anonymous<>\n"
" cluster_id: 49 == 'NetworkCommissioning'\n"
" attribute_id: 65532 == 'featureMap'\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 48 == 'GeneralCommissioning'\n"
" attribute_id: 0 == 'breadcrumb'\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 48 == 'GeneralCommissioning'\n"
" attribute_id: 1 == 'basicCommissioningInfo'\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 48 == 'GeneralCommissioning'\n"
" attribute_id: 2 == 'regulatoryConfig'\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 48 == 'GeneralCommissioning'\n"
" attribute_id: 3 == 'locationCapability'\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 40 == 'BasicInformation'\n"
" attribute_id: 2 == 'vendorID'\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 40 == 'BasicInformation'\n"
" attribute_id: 4 == 'productID'\n"
" Anonymous<>\n"
" cluster_id: 49 == 'NetworkCommissioning'\n"
" attribute_id: 3 == 'connectMaxTimeSeconds'\n"
" fabric_filtered: false\n"
" interaction_model_revison: 1\n");
TestSampleData(inSuite, params, im_protocol_report_data,
"report_data\n"
" attribute_reports\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 28559721\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 49 == 'NetworkCommissioning'\n"
" attribute_id: 3 == 'connectMaxTimeSeconds'\n"
" NetworkCommissioning::connectMaxTimeSeconds: 0\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 664978787\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 40 == 'BasicInformation'\n"
" attribute_id: 4 == 'productID'\n"
" BasicInformation::productID: 32769\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 664978787\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 40 == 'BasicInformation'\n"
" attribute_id: 2 == 'vendorID'\n"
" BasicInformation::vendorID: 65521\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 1414030794\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 48 == 'GeneralCommissioning'\n"
" attribute_id: 3 == 'locationCapability'\n"
" GeneralCommissioning::locationCapability: 2 == kIndoorOutdoor\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 1414030794\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 48 == 'GeneralCommissioning'\n"
" attribute_id: 2 == 'regulatoryConfig'\n"
" GeneralCommissioning::regulatoryConfig: 0 == kIndoor\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 1414030794\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 48 == 'GeneralCommissioning'\n"
" attribute_id: 1 == 'basicCommissioningInfo'\n"
" GeneralCommissioning::basicCommissioningInfo\n"
" failSafeExpiryLengthSeconds: 60\n"
" maxCumulativeFailsafeSeconds: 900\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 1414030794\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 48 == 'GeneralCommissioning'\n"
" attribute_id: 0 == 'breadcrumb'\n"
" GeneralCommissioning::breadcrumb: 0\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 28559721\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 49 == 'NetworkCommissioning'\n"
" attribute_id: 65532 == 'featureMap'\n"
" NetworkCommissioning::featureMap: 4 == kEthernetNetworkInterface\n"
" suppress_response: true\n"
" interaction_model_revison: 1\n");
// Different content
TestSampleData(inSuite, params, im_protocol_report_data_acl,
"report_data\n"
" attribute_reports\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 3420147058\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 31 == 'AccessControl'\n"
" attribute_id: 0 == 'acl'\n"
" AccessControl::acl\n"
" Anonymous<>\n"
" privilege: 5 == kAdminister\n"
" authMode: 2 == kCASE\n"
" subjects\n"
" Anonymous<>: 112233\n"
" targets: NULL\n"
" fabricIndex: 1\n"
" suppress_response: true\n"
" interaction_model_revison: 1\n");
TestSampleData(
inSuite, params, im_protocol_report_data_window_covering,
"report_data\n"
" attribute_reports\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 2054986218\n"
" path\n"
" endpoint_id: 1\n"
" cluster_id: 258 == 'WindowCovering'\n"
" attribute_id: 7 == 'configStatus'\n"
" WindowCovering::configStatus: 27 == kOperational | kOnlineReserved | kLiftPositionAware | kTiltPositionAware\n"
" suppress_response: true\n"
" interaction_model_revison: 1\n");
TestSampleData(inSuite, params, im_protocol_invoke_request,
"invoke_request\n"
" suppress_response: false\n"
" timed_request: false\n"
" invoke_requests\n"
" Anonymous<>\n"
" path\n"
" endpoint_id: 1\n"
" cluster_id: 6 == 'OnOff'\n"
" command_id: 2 == 'Toggle'\n"
" OnOff::Toggle\n"
" interaction_model_revison: 1\n");
TestSampleData(inSuite, params, im_protocol_invoke_response,
"invoke_response\n"
" suppress_response: false\n"
" invoke_responses\n"
" Anonymous<>\n"
" status\n"
" path\n"
" endpoint_id: 1\n"
" cluster_id: 6 == 'OnOff'\n"
" command_id: 2 == 'Toggle'\n"
" status\n"
" status: 0 == kSuccess\n"
" interaction_model_revison: 1\n");
TestSampleData(inSuite, params, im_protocol_invoke_request_change_channel,
"invoke_request\n"
" suppress_response: false\n"
" timed_request: false\n"
" invoke_requests\n"
" Anonymous<>\n"
" path\n"
" endpoint_id: 1\n"
" cluster_id: 1284 == 'Channel'\n"
" command_id: 0 == 'ChangeChannel'\n"
" Channel::ChangeChannel\n"
" match: \"channel name\"\n"
" interaction_model_revison: 1\n");
TestSampleData(inSuite, params, im_protocol_event_software_fault,
"report_data\n"
" event_reports\n"
" Anonymous<>\n"
" event_data\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 52 == 'SoftwareDiagnostics'\n"
" event_id: 0 == 'SoftwareFault'\n"
" event_number: 196610\n"
" priority: 1\n"
" epoch_timestamp: 1690566548210\n"
" SoftwareDiagnostics::SoftwareFault\n"
" id: 2454952\n"
" name: \"2454952\"\n"
" faultRecording: hex:467269204A756C2032382031333A34393A30382032303233\n"
" suppress_response: true\n"
" interaction_model_revison: 1\n");
TestSampleData(inSuite, params, im_protocol_event_multipress,
"report_data\n"
" event_reports\n"
" Anonymous<>\n"
" event_data\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 59 == 'Switch'\n"
" event_id: 6 == 'MultiPressComplete'\n"
" event_number: 196611\n"
" priority: 1\n"
" epoch_timestamp: 1690566820898\n"
" Switch::MultiPressComplete\n"
" previousPosition: 1\n"
" totalNumberOfPressesCounted: 23\n"
" suppress_response: true\n"
" interaction_model_revison: 1\n");
}
void TestMetaDataOnlyDecoding(nlTestSuite * inSuite, void * inContext)
{
PayloadDecoderInitParams params;
// NO CLUSTER DECODE TREE
params.SetProtocolDecodeTree(chip::TLVMeta::protocols_meta);
TestSampleData(inSuite, params, secure_channel_mrp_ack, "mrp_ack: EMPTY\n");
TestSampleData(inSuite, params, secure_channel_pkbdf_param_request,
"pbkdf_param_request\n"
" initiator_random: hex:7C8698755B8E9866BB4FFDC27B733F3B6EF7F83D43FBE0CA6AD2B8C52C8F4236\n"
" initiator_session_id: 37677\n"
" passcode_id: 0\n"
" has_pbkdf_parameters: false\n");
TestSampleData(inSuite, params, im_protocol_read_request,
"read_request\n"
" attribute_requests\n"
" Anonymous<>\n"
" cluster_id: 49\n"
" attribute_id: 65532\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 48\n"
" attribute_id: 0\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 48\n"
" attribute_id: 1\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 48\n"
" attribute_id: 2\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 48\n"
" attribute_id: 3\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 40\n"
" attribute_id: 2\n"
" Anonymous<>\n"
" endpoint_id: 0\n"
" cluster_id: 40\n"
" attribute_id: 4\n"
" Anonymous<>\n"
" cluster_id: 49\n"
" attribute_id: 3\n"
" fabric_filtered: false\n"
" interaction_model_revison: 1\n");
TestSampleData(inSuite, params, im_protocol_report_data,
"report_data\n"
" attribute_reports\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 28559721\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 49\n"
" attribute_id: 3\n"
" ATTRIBUTE: 49/3\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 664978787\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 40\n"
" attribute_id: 4\n"
" ATTRIBUTE: 40/4\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 664978787\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 40\n"
" attribute_id: 2\n"
" ATTRIBUTE: 40/2\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 1414030794\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 48\n"
" attribute_id: 3\n"
" ATTRIBUTE: 48/3\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 1414030794\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 48\n"
" attribute_id: 2\n"
" ATTRIBUTE: 48/2\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 1414030794\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 48\n"
" attribute_id: 1\n"
" ATTRIBUTE: 48/1\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 1414030794\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 48\n"
" attribute_id: 0\n"
" ATTRIBUTE: 48/0\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 28559721\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 49\n"
" attribute_id: 65532\n"
" ATTRIBUTE: 49/65532\n"
" suppress_response: true\n"
" interaction_model_revison: 1\n");
// Different content
TestSampleData(inSuite, params, im_protocol_report_data_acl,
"report_data\n"
" attribute_reports\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 3420147058\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 31\n"
" attribute_id: 0\n"
" ATTRIBUTE: 31/0\n"
" suppress_response: true\n"
" interaction_model_revison: 1\n");
}
void TestEmptyClusterMetaDataDecode(nlTestSuite * inSuite, void * inContext)
{
PayloadDecoderInitParams params;
params.SetProtocolDecodeTree(chip::TLVMeta::protocols_meta).SetClusterDecodeTree(empty_meta);
TestSampleData(inSuite, params, secure_channel_mrp_ack, "mrp_ack: EMPTY\n");
TestSampleData(inSuite, params, im_protocol_report_data_acl,
"report_data\n"
" attribute_reports\n"
" Anonymous<>\n"
" attribute_data\n"
" data_version: 3420147058\n"
" path\n"
" endpoint_id: 0\n"
" cluster_id: 31\n"
" attribute_id: 0\n"
" 0x1f::ATTR(0x0)\n" // Cluster 31, attribute 0
" AnonymousTag()\n" // List entry (acl is a list)
" ContextTag(0x1): 5\n" // privilege
" ContextTag(0x2): 2\n" // authMode
" ContextTag(0x3)\n" // subjects
" AnonymousTag(): 112233\n" // List entry (subjects is a list)
" ContextTag(0x4): NULL\n" // targets
" ContextTag(0xFE): 1\n" // fabricIndex
" suppress_response: true\n"
" interaction_model_revison: 1\n");
}
void TestMissingDecodeData(nlTestSuite * inSuite, void * inContext)
{
PayloadDecoderInitParams params;
params.SetProtocolDecodeTree(empty_meta).SetClusterDecodeTree(empty_meta);
TestSampleData(inSuite, params, secure_channel_mrp_ack, "PROTO(0x0, 0x10): UNKNOWN\n");
TestSampleData(inSuite, params, im_protocol_report_data_acl, "PROTO(0x1, 0x5): UNKNOWN\n");
}
void TestWrongDecodeData(nlTestSuite * inSuite, void * inContext)
{
PayloadDecoderInitParams params;
params.SetProtocolDecodeTree(fake_protocols_meta).SetClusterDecodeTree(empty_meta);
TestSampleData(inSuite, params, secure_channel_mrp_ack, "proto16: EMPTY\n");
TestSampleData(inSuite, params, im_protocol_report_data_acl,
"proto5\n"
" ContextTag(0x1)\n"
" AnonymousTag()\n"
" ContextTag(0x1)\n"
" ContextTag(0x0): 3420147058\n"
" ContextTag(0x1)\n"
" ContextTag(0x2): 0\n"
" ContextTag(0x3): 31\n"
" ContextTag(0x4): 0\n"
" ContextTag(0x2)\n"
" AnonymousTag()\n"
" ContextTag(0x1): 5\n"
" ContextTag(0x2): 2\n"
" ContextTag(0x3)\n"
" AnonymousTag(): 112233\n"
" ContextTag(0x4): NULL\n"
" ContextTag(0xFE): 1\n"
" ContextTag(0x4): true\n"
" ContextTag(0xFF): 1\n");
}
void TestNestingOverflow(nlTestSuite * inSuite, void * inContext)
{
PayloadDecoderInitParams params;
params.SetProtocolDecodeTree(fake_protocols_meta).SetClusterDecodeTree(empty_meta);
uint8_t data_buffer[1024];
chip::TLV::TLVWriter writer;
writer.Init(data_buffer, sizeof(data_buffer));
chip::TLV::TLVType unusedType;
// Protocols start with an anonymous tagged structure, after which lists can be of any tags
NL_TEST_ASSERT(inSuite, writer.StartContainer(AnonymousTag(), kTLVType_Structure, unusedType) == CHIP_NO_ERROR);
// nesting overflow here
for (uint8_t i = 0; i < 32; i++)
{
NL_TEST_ASSERT(inSuite, writer.StartContainer(ContextTag(i), kTLVType_List, unusedType) == CHIP_NO_ERROR);
}
// Go back to 24 (still too much nesting)
for (uint8_t i = 0; i < 8; i++)
{
NL_TEST_ASSERT(inSuite, writer.EndContainer(kTLVType_List) == CHIP_NO_ERROR);
}
for (uint8_t i = 0; i < 4; i++)
{
NL_TEST_ASSERT(
inSuite, writer.StartContainer(ContextTag(static_cast<uint8_t>(i + 0x10)), kTLVType_List, unusedType) == CHIP_NO_ERROR);
}
for (uint8_t i = 0; i < 4; i++)
{
NL_TEST_ASSERT(inSuite, writer.EndContainer(kTLVType_List) == CHIP_NO_ERROR);
}
// Go back to 8
for (uint8_t i = 0; i < 16; i++)
{
NL_TEST_ASSERT(inSuite, writer.EndContainer(kTLVType_List) == CHIP_NO_ERROR);
}
for (uint8_t i = 0; i < 4; i++)
{
NL_TEST_ASSERT(
inSuite, writer.StartContainer(ContextTag(static_cast<uint8_t>(i + 0x20)), kTLVType_List, unusedType) == CHIP_NO_ERROR);
}
for (uint8_t i = 0; i < 4; i++)
{
NL_TEST_ASSERT(inSuite, writer.EndContainer(kTLVType_List) == CHIP_NO_ERROR);
}
// Go back to 4
for (uint8_t i = 0; i < 4; i++)
{
NL_TEST_ASSERT(inSuite, writer.EndContainer(kTLVType_List) == CHIP_NO_ERROR);
}
for (uint8_t i = 0; i < 4; i++)
{
NL_TEST_ASSERT(
inSuite, writer.StartContainer(ContextTag(static_cast<uint8_t>(i + 0x30)), kTLVType_List, unusedType) == CHIP_NO_ERROR);
}
for (uint8_t i = 0; i < 4; i++)
{
NL_TEST_ASSERT(inSuite, writer.EndContainer(kTLVType_List) == CHIP_NO_ERROR);
}
// close everything
for (uint8_t i = 0; i < 4; i++)
{
NL_TEST_ASSERT(inSuite, writer.EndContainer(kTLVType_List) == CHIP_NO_ERROR);
}
NL_TEST_ASSERT(inSuite, writer.EndContainer(kTLVType_Structure) == CHIP_NO_ERROR);
SamplePayload fake_payload{ chip::Protocols::InteractionModel::Id, 5, chip::ByteSpan(data_buffer, writer.GetLengthWritten()) };
TestSampleData(inSuite, params, fake_payload,
"proto5\n"
" ContextTag(0x0)\n"
" ContextTag(0x1)\n"
" ContextTag(0x2)\n"
" ContextTag(0x3)\n"
" ContextTag(0x4)\n"
" ContextTag(0x5)\n"
" ContextTag(0x6)\n"
" ContextTag(0x7)\n"
" ContextTag(0x8)\n"
" ContextTag(0x9)\n"
" ContextTag(0xA)\n"
" ContextTag(0xB)\n"
" ContextTag(0xC)\n"
" ContextTag(0xD)\n"
" ContextTag(0xE)\n"
" ContextTag(0xF): NESTING DEPTH REACHED\n"
" ContextTag(0x20)\n"
" ContextTag(0x21)\n"
" ContextTag(0x22)\n"
" ContextTag(0x23)\n"
" ContextTag(0x30)\n"
" ContextTag(0x31)\n"
" ContextTag(0x32)\n"
" ContextTag(0x33)\n");
}
const nlTest sTests[] = {
NL_TEST_DEF("TestFullDataDecoding", TestFullDataDecoding), //
NL_TEST_DEF("TestMetaDataOnlyDecoding", TestMetaDataOnlyDecoding), //
NL_TEST_DEF("TestEmptyClusterMetaDataDecode", TestEmptyClusterMetaDataDecode), //
NL_TEST_DEF("TestMissingDecodeData", TestMissingDecodeData), //
NL_TEST_DEF("TestWrongDecodeData", TestWrongDecodeData), //
NL_TEST_DEF("TestNestingOverflow", TestNestingOverflow), //
NL_TEST_SENTINEL() //
};
} // namespace
int TestDecode()
{
nlTestSuite theSuite = { "TestDecode", sTests, nullptr, nullptr };
nlTestRunner(&theSuite, nullptr);
return nlTestRunnerStats(&theSuite);
}
CHIP_REGISTER_TEST_SUITE(TestDecode)