blob: e063e0e888ac0e64f107cbf7e0320b78dfa6f52a [file] [log] [blame]
Boris Zbarskyc95449a2021-10-07 02:40:27 -04001/*
2 *
3 * Copyright (c) 2021 Project CHIP Authors
4 * All rights reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/**
20 * @file
21 * This file implements unit tests for CommandPathParams
22 *
23 */
24
Song GUOf2e7df82021-12-09 23:20:47 +080025#include <app-common/zap-generated/cluster-objects.h>
Boris Zbarskyc95449a2021-10-07 02:40:27 -040026#include <app/AttributeAccessInterface.h>
yunhanw-googleb717b362021-11-08 13:34:19 -080027#include <app/MessageDef/AttributeDataIB.h>
Boris Zbarskyc95449a2021-10-07 02:40:27 -040028#include <lib/support/CodeUtils.h>
29#include <lib/support/UnitTestRegistration.h>
30#include <nlunit-test.h>
31
32using namespace chip;
33using namespace chip::app;
34using namespace chip::TLV;
35
Song GUOf2e7df82021-12-09 23:20:47 +080036// TODO: This unit tests contains hard code TLV data, they should be replaced with some decoding code to improve readability.
37
Boris Zbarskyc95449a2021-10-07 02:40:27 -040038namespace {
39
Song GUObfdbd452021-12-06 15:53:34 +080040// These values are easier to be recognized in the encoded buffer
41constexpr EndpointId kRandomEndpointId = 0x55;
42constexpr ClusterId kRandomClusterId = 0xaa;
43constexpr AttributeId kRandomAttributeId = 0xcc;
44constexpr DataVersion kRandomDataVersion = 0x99;
Song GUOf2e7df82021-12-09 23:20:47 +080045constexpr FabricIndex kTestFabricIndex = 1;
Song GUObfdbd452021-12-06 15:53:34 +080046
47template <size_t N>
48struct LimitedTestSetup
Boris Zbarskyc95449a2021-10-07 02:40:27 -040049{
Song GUOe17d7672022-01-22 10:11:27 +080050 LimitedTestSetup(nlTestSuite * aSuite, const FabricIndex aFabricIndex = kUndefinedFabricIndex,
Song GUObfdbd452021-12-06 15:53:34 +080051 const AttributeValueEncoder::AttributeEncodeState & aState = AttributeValueEncoder::AttributeEncodeState()) :
Song GUOf2e7df82021-12-09 23:20:47 +080052 encoder(builder, aFabricIndex, ConcreteAttributePath(kRandomEndpointId, kRandomClusterId, kRandomAttributeId),
Song GUOe17d7672022-01-22 10:11:27 +080053 kRandomDataVersion, aFabricIndex != kUndefinedFabricIndex, aState)
Boris Zbarskyc95449a2021-10-07 02:40:27 -040054 {
55 writer.Init(buf);
Song GUObfdbd452021-12-06 15:53:34 +080056 {
57 TLVType ignored;
Boris Zbarsky5c096ec2021-12-23 13:28:39 -050058 CHIP_ERROR err = writer.StartContainer(AnonymousTag(), kTLVType_Structure, ignored);
Song GUObfdbd452021-12-06 15:53:34 +080059 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
60 }
61 {
62 CHIP_ERROR err = builder.Init(&writer, 1);
63 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
64 }
Boris Zbarskyc95449a2021-10-07 02:40:27 -040065 }
66
Song GUObfdbd452021-12-06 15:53:34 +080067 AttributeReportIBs::Builder builder;
Boris Zbarskyc95449a2021-10-07 02:40:27 -040068 AttributeValueEncoder encoder;
Song GUObfdbd452021-12-06 15:53:34 +080069 uint8_t buf[N];
Boris Zbarskyc95449a2021-10-07 02:40:27 -040070 TLVWriter writer;
71};
72
Song GUObfdbd452021-12-06 15:53:34 +080073using TestSetup = LimitedTestSetup<1024>;
74
Boris Zbarskyc95449a2021-10-07 02:40:27 -040075// Macro so we get better error reporting in terms of which test failed, because
76// the reporting uses __LINE__.
77#define VERIFY_BUFFER_STATE(aSuite, aSetup, aExpected) \
78 do \
79 { \
80 NL_TEST_ASSERT(aSuite, aSetup.writer.GetLengthWritten() == sizeof(aExpected)); \
81 NL_TEST_ASSERT(aSuite, memcmp(aSetup.buf, aExpected, sizeof(aExpected)) == 0); \
Song GUObfdbd452021-12-06 15:53:34 +080082 if (aSetup.writer.GetLengthWritten() != sizeof(aExpected) || memcmp(aSetup.buf, aExpected, sizeof(aExpected)) != 0) \
83 { \
84 printf("Encoded: \n"); \
85 for (size_t i = 0; i < aSetup.writer.GetLengthWritten(); i++) \
86 { \
Boris Zbarsky21553282022-02-11 18:23:49 -050087 printf("0x%02x,", aSetup.buf[i]); \
Song GUObfdbd452021-12-06 15:53:34 +080088 } \
89 printf("\n"); \
90 printf("Expected: \n"); \
91 for (size_t i = 0; i < sizeof(aExpected); i++) \
92 { \
Boris Zbarsky21553282022-02-11 18:23:49 -050093 printf("0x%02x,", aExpected[i]); \
Song GUObfdbd452021-12-06 15:53:34 +080094 } \
95 printf("\n"); \
96 } \
Boris Zbarskyc95449a2021-10-07 02:40:27 -040097 } while (0)
98
99void TestEncodeNothing(nlTestSuite * aSuite, void * aContext)
100{
101 TestSetup test(aSuite);
Song GUObfdbd452021-12-06 15:53:34 +0800102 // Just have an anonymous struct marker, and the AttributeReportIBs opened.
103 const uint8_t expected[] = { 0x15, 0x36, 0x01 };
Boris Zbarskyc95449a2021-10-07 02:40:27 -0400104 VERIFY_BUFFER_STATE(aSuite, test, expected);
105}
106
107void TestEncodeBool(nlTestSuite * aSuite, void * aContext)
108{
109 TestSetup test(aSuite);
110 CHIP_ERROR err = test.encoder.Encode(true);
111 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
Song GUObfdbd452021-12-06 15:53:34 +0800112 const uint8_t expected[] = {
113 // clang-format off
114 0x15, 0x36, 0x01, // Test overhead, Start Anonymous struct + Start 1 byte Tag Array + Tag (01)
115 0x15, // Start anonymous struct
116 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
117 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
118 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
119 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
120 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
121 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
122 0x18, // End of container
123 0x29, 0x02, // Tag (02) Value True (Attribute Value)
124 0x18, // End of container
125 0x18, // End of container
126 // clang-format on
127 };
Boris Zbarskyc95449a2021-10-07 02:40:27 -0400128 VERIFY_BUFFER_STATE(aSuite, test, expected);
129}
130
131void TestEncodeListOfBools1(nlTestSuite * aSuite, void * aContext)
132{
133 TestSetup test(aSuite);
134 bool list[] = { true, false };
135 CHIP_ERROR err = test.encoder.Encode(DataModel::List<bool>(list));
136 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
Song GUObfdbd452021-12-06 15:53:34 +0800137 const uint8_t expected[] = {
138 // clang-format off
139 0x15, 0x36, 0x01, // Test overhead, Start Anonymous struct + Start 1 byte Tag Array + Tag (01)
140 0x15, // Start anonymous struct
141 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
142 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
143 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
144 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
145 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
146 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
147 0x18, // End of container
148 0x36, 0x02, // Start 1 byte tag array + Tag (02) (Attribute Value)
149 0x09, // True
150 0x08, // False
151 0x18,
152 0x18, // End of container
153 0x18, // End of container
154 // clang-format on
155 };
Boris Zbarskyc95449a2021-10-07 02:40:27 -0400156 VERIFY_BUFFER_STATE(aSuite, test, expected);
157}
158
159void TestEncodeListOfBools2(nlTestSuite * aSuite, void * aContext)
160{
161 TestSetup test(aSuite);
162 bool list[] = { true, false };
Song GUObfdbd452021-12-06 15:53:34 +0800163 CHIP_ERROR err = test.encoder.EncodeList([&list](const auto & encoder) -> CHIP_ERROR {
Boris Zbarskyc95449a2021-10-07 02:40:27 -0400164 for (auto & item : list)
165 {
166 ReturnErrorOnFailure(encoder.Encode(item));
167 }
168 return CHIP_NO_ERROR;
169 });
170 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
Song GUObfdbd452021-12-06 15:53:34 +0800171 const uint8_t expected[] = {
172 // clang-format off
173 0x15, 0x36, 0x01, // Test overhead, Start Anonymous struct + Start 1 byte Tag Array + Tag (01)
174 0x15, // Start anonymous struct
175 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
176 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
177 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
178 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
179 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
180 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
181 0x18, // End of container
182 // Intended empty array
183 0x36, 0x02, // Start 1 byte tag array + Tag (02) (Attribute Value)
184 0x18, // End of container
185 0x18, // End of container
186 0x18, // End of container
187
188 0x15, // Start anonymous struct
189 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
190 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
191 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
192 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
193 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
194 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
195 0x34, 0x05, // Tag (05) Null
196 0x18, // End of container
197 0x29, 0x02, // Tag (02) Value True (Attribute Value)
198 0x18, // End of container
199 0x18, // End of container
200
201 0x15, // Start anonymous struct
202 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
203 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
204 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
205 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
206 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
207 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
208 0x34, 0x05, // Tag (05) Null
209 0x18, // End of container
210 0x28, 0x02, // Tag (02) Value False (Attribute Value)
211 0x18, // End of container
212 0x18, // End of container
213
214 // clang-format on
215 };
Boris Zbarskyc95449a2021-10-07 02:40:27 -0400216 VERIFY_BUFFER_STATE(aSuite, test, expected);
217}
218
Boris Zbarsky27488482021-12-19 21:17:58 -0500219constexpr uint8_t emptyListExpected[] = {
220 // clang-format off
221 0x15, 0x36, 0x01, // Test overhead, Start Anonymous struct + Start 1 byte Tag Array + Tag (01)
222 0x15, // Start anonymous struct
223 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
224 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
225 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
226 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
227 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
228 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
229 0x18, // End of container
230 // Intended empty array
231 0x36, 0x02, // Start 1 byte tag array + Tag (02) (Attribute Value)
232 0x18, // End of container
233 0x18, // End of container
234 0x18, // End of container
235 // clang-format on
236};
237
238void TestEncodeEmptyList1(nlTestSuite * aSuite, void * aContext)
Song GUObfdbd452021-12-06 15:53:34 +0800239{
240 TestSetup test(aSuite);
241 CHIP_ERROR err = test.encoder.EncodeList([](const auto & encoder) -> CHIP_ERROR { return CHIP_NO_ERROR; });
242 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
Boris Zbarsky27488482021-12-19 21:17:58 -0500243 VERIFY_BUFFER_STATE(aSuite, test, emptyListExpected);
244}
245
246void TestEncodeEmptyList2(nlTestSuite * aSuite, void * aContext)
247{
248 TestSetup test(aSuite);
249 CHIP_ERROR err = test.encoder.EncodeEmptyList();
250 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
251 VERIFY_BUFFER_STATE(aSuite, test, emptyListExpected);
Song GUObfdbd452021-12-06 15:53:34 +0800252}
253
Song GUOf2e7df82021-12-09 23:20:47 +0800254void TestEncodeFabricScoped(nlTestSuite * aSuite, void * aContext)
255{
256 TestSetup test(aSuite, kTestFabricIndex);
257 Clusters::AccessControl::Structs::ExtensionEntry::Type items[3];
Jerry Johns11a5b142022-02-17 15:21:39 -0800258 items[0].fabricIndex = 1;
259 items[1].fabricIndex = 2;
260 items[2].fabricIndex = 3;
Song GUOf2e7df82021-12-09 23:20:47 +0800261
262 // We tried to encode three items, however, the encoder should only put the item with matching fabric index into the final list.
263 CHIP_ERROR err = test.encoder.EncodeList([items](const auto & encoder) -> CHIP_ERROR {
264 for (size_t i = 0; i < 3; i++)
265 {
266 ReturnErrorOnFailure(encoder.Encode(items[i]));
267 }
268 return CHIP_NO_ERROR;
269 });
270 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
271 const uint8_t expected[] = {
272 // clang-format off
273 0x15, 0x36, 0x01, // Test overhead, Start Anonymous struct + Start 1 byte Tag Array + Tag (01)
274 0x15, // Start anonymous struct
275 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
276 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
277 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
278 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
279 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
280 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
281 0x18, // End of container
282 // Intended empty array
283 0x36, 0x02, // Start 1 byte tag array + Tag (02) (Attribute Value)
284 0x18, // End of container
285 0x18, // End of container
286 0x18, // End of container
287 0x15, // Start anonymous struct
288 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
289 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
290 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
291 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
292 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
293 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
294 0x34, 0x05, // Tag (05) Null
295 0x18, // End of container (attribute path)
296 0x35, 0x02, // Tag 02 (attribute data)
Song GUOf2e7df82021-12-09 23:20:47 +0800297 0x30, 0x01, 0x00, // Tag 1, OCTET_STRING length 0 (data)
Song GUOcd089382022-03-17 13:31:51 +0800298 0x24, 0xFE, 0x01, // Tag 0xFE, UINT8 Value 1 (fabric index)
Song GUOf2e7df82021-12-09 23:20:47 +0800299 0x18,
300 0x18,
301 0x18,
302 // clang-format on
303 };
304 VERIFY_BUFFER_STATE(aSuite, test, expected);
305}
306
Song GUObfdbd452021-12-06 15:53:34 +0800307void TestEncodeListChunking(nlTestSuite * aSuite, void * aContext)
308{
309 AttributeValueEncoder::AttributeEncodeState state;
310
311 bool list[] = { true, false };
312 auto listEncoder = [&list](const auto & encoder) -> CHIP_ERROR {
313 for (auto & item : list)
314 {
315 ReturnErrorOnFailure(encoder.Encode(item));
316 }
317 return CHIP_NO_ERROR;
318 };
319
320 {
Song GUOf2e7df82021-12-09 23:20:47 +0800321 // Use 60 bytes buffer to force chunking. The kTestFabricIndex is not effective in this test.
322 LimitedTestSetup<60> test1(aSuite, kTestFabricIndex);
Song GUObfdbd452021-12-06 15:53:34 +0800323 CHIP_ERROR err = test1.encoder.EncodeList(listEncoder);
324 NL_TEST_ASSERT(aSuite, err == CHIP_ERROR_NO_MEMORY || err == CHIP_ERROR_BUFFER_TOO_SMALL);
325 state = test1.encoder.GetState();
326
327 const uint8_t expected[] = {
328 // clang-format off
329 0x15, 0x36, 0x01, // Test overhead, Start Anonymous struct + Start 1 byte Tag Array + Tag (01)
330 0x15, // Start anonymous struct
331 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
332 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
333 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
334 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
335 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
336 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
337 0x18, // End of container
338 // Intended empty array
339 0x36, 0x02, // Start 1 byte tag array + Tag (02) (Attribute Value)
340 0x18, // End of container
341 0x18, // End of container
342 0x18, // End of container
343
344 0x15, // Start anonymous struct
345 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
346 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
347 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
348 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
349 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
350 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
351 0x34, 0x05, // Tag (05) Null
352 0x18, // End of container
353 0x29, 0x02, // Tag (02) Value True (Attribute Value)
354 0x18, // End of container
355 0x18, // End of container
356 // clang-format on
357 };
358 VERIFY_BUFFER_STATE(aSuite, test1, expected);
359 }
360 {
Song GUOf2e7df82021-12-09 23:20:47 +0800361 // Use 60 bytes buffer to force chunking. The kTestFabricIndex is not effective in this test.
362 LimitedTestSetup<60> test2(aSuite, 0, state);
Song GUObfdbd452021-12-06 15:53:34 +0800363 CHIP_ERROR err = test2.encoder.EncodeList(listEncoder);
364 NL_TEST_ASSERT(aSuite, err == CHIP_NO_ERROR);
365
366 const uint8_t expected[] = {
367 // clang-format off
368 0x15, 0x36, 0x01, // Test overhead, Start Anonymous struct + Start 1 byte Tag Array + Tag (01)
369 0x15, // Start anonymous struct
370 0x35, 0x01, // Start 1 byte tag struct + Tag (01)
371 0x24, 0x00, 0x99, // Tag (00) Value (1 byte uint) 0x99 (Attribute Version)
372 0x37, 0x01, // Start 1 byte tag list + Tag (01) (Attribute Path)
373 0x24, 0x02, 0x55, // Tag (02) Value (1 byte uint) 0x55
374 0x24, 0x03, 0xaa, // Tag (03) Value (1 byte uint) 0xaa
375 0x24, 0x04, 0xcc, // Tag (04) Value (1 byte uint) 0xcc
376 0x34, 0x05, // Tag (05) Null
377 0x18, // End of container
378 0x28, 0x02, // Tag (02) Value False (Attribute Value)
379 0x18, // End of container
380 0x18, // End of container
381 // clang-format on
382 };
383 VERIFY_BUFFER_STATE(aSuite, test2, expected);
384 }
385}
386
Boris Zbarsky27488482021-12-19 21:17:58 -0500387#undef VERIFY_BUFFER_STATE
Boris Zbarskyc95449a2021-10-07 02:40:27 -0400388
389} // anonymous namespace
390
391namespace {
Boris Zbarsky27488482021-12-19 21:17:58 -0500392const nlTest sTests[] = { NL_TEST_DEF("TestEncodeNothing", TestEncodeNothing),
393 NL_TEST_DEF("TestEncodeBool", TestEncodeBool),
394 NL_TEST_DEF("TestEncodeEmptyList1", TestEncodeEmptyList1),
395 NL_TEST_DEF("TestEncodeEmptyList2", TestEncodeEmptyList2),
396 NL_TEST_DEF("TestEncodeListOfBools1", TestEncodeListOfBools1),
397 NL_TEST_DEF("TestEncodeListOfBools2", TestEncodeListOfBools2),
398 NL_TEST_DEF("TestEncodeListChunking", TestEncodeListChunking),
399 NL_TEST_DEF("TestEncodeFabricScoped", TestEncodeFabricScoped),
400 NL_TEST_SENTINEL() };
Boris Zbarskyc95449a2021-10-07 02:40:27 -0400401}
402
403int TestAttributeValueEncoder()
404{
405 nlTestSuite theSuite = { "AttributeValueEncoder", &sTests[0], nullptr, nullptr };
406
407 nlTestRunner(&theSuite, nullptr);
408
409 return (nlTestRunnerStats(&theSuite));
410}
411
412CHIP_REGISTER_TEST_SUITE(TestAttributeValueEncoder)