xref: /aosp_15_r20/external/openthread/tests/unit/test_spinel_decoder.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2017, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
30*cfb92d14SAndroid Build Coastguard Worker #include "instance/instance.hpp"
31*cfb92d14SAndroid Build Coastguard Worker #include "lib/spinel/spinel_decoder.hpp"
32*cfb92d14SAndroid Build Coastguard Worker 
33*cfb92d14SAndroid Build Coastguard Worker #include "test_util.hpp"
34*cfb92d14SAndroid Build Coastguard Worker 
35*cfb92d14SAndroid Build Coastguard Worker namespace ot {
36*cfb92d14SAndroid Build Coastguard Worker namespace Spinel {
37*cfb92d14SAndroid Build Coastguard Worker 
38*cfb92d14SAndroid Build Coastguard Worker enum
39*cfb92d14SAndroid Build Coastguard Worker {
40*cfb92d14SAndroid Build Coastguard Worker     kTestBufferSize = 800,
41*cfb92d14SAndroid Build Coastguard Worker };
42*cfb92d14SAndroid Build Coastguard Worker 
TestDecoder(void)43*cfb92d14SAndroid Build Coastguard Worker void TestDecoder(void)
44*cfb92d14SAndroid Build Coastguard Worker {
45*cfb92d14SAndroid Build Coastguard Worker     uint8_t         buffer[kTestBufferSize];
46*cfb92d14SAndroid Build Coastguard Worker     Spinel::Decoder decoder;
47*cfb92d14SAndroid Build Coastguard Worker 
48*cfb92d14SAndroid Build Coastguard Worker     spinel_ssize_t frameLen;
49*cfb92d14SAndroid Build Coastguard Worker 
50*cfb92d14SAndroid Build Coastguard Worker     const bool     kBool_1 = true;
51*cfb92d14SAndroid Build Coastguard Worker     const bool     kBool_2 = false;
52*cfb92d14SAndroid Build Coastguard Worker     const uint8_t  kUint8  = 0x42;
53*cfb92d14SAndroid Build Coastguard Worker     const int8_t   kInt8   = -73;
54*cfb92d14SAndroid Build Coastguard Worker     const uint16_t kUint16 = 0xabcd;
55*cfb92d14SAndroid Build Coastguard Worker     const int16_t  kInt16  = -567;
56*cfb92d14SAndroid Build Coastguard Worker     const uint32_t kUint32 = 0xdeadbeef;
57*cfb92d14SAndroid Build Coastguard Worker     const int32_t  kInt32  = -123455678L;
58*cfb92d14SAndroid Build Coastguard Worker     const uint64_t kUint64 = 0xfe10dc32ba549876ULL;
59*cfb92d14SAndroid Build Coastguard Worker     const int64_t  kInt64  = -9197712039090021561LL;
60*cfb92d14SAndroid Build Coastguard Worker 
61*cfb92d14SAndroid Build Coastguard Worker     const unsigned int kUint_1 = 9;
62*cfb92d14SAndroid Build Coastguard Worker     const unsigned int kUint_2 = 0xa3;
63*cfb92d14SAndroid Build Coastguard Worker     const unsigned int kUint_3 = 0x8765;
64*cfb92d14SAndroid Build Coastguard Worker     const unsigned int kUint_4 = SPINEL_MAX_UINT_PACKED - 1;
65*cfb92d14SAndroid Build Coastguard Worker 
66*cfb92d14SAndroid Build Coastguard Worker     const spinel_ipv6addr_t kIp6Addr = {
67*cfb92d14SAndroid Build Coastguard Worker         {0x6B, 0x41, 0x65, 0x73, 0x42, 0x68, 0x61, 0x76, 0x54, 0x61, 0x72, 0x7A, 0x49, 0x69, 0x61, 0x4E}};
68*cfb92d14SAndroid Build Coastguard Worker 
69*cfb92d14SAndroid Build Coastguard Worker     const spinel_eui48_t kEui48 = {
70*cfb92d14SAndroid Build Coastguard Worker         {4, 8, 15, 16, 23, 42} // "Lost" EUI48!
71*cfb92d14SAndroid Build Coastguard Worker     };
72*cfb92d14SAndroid Build Coastguard Worker 
73*cfb92d14SAndroid Build Coastguard Worker     const spinel_eui64_t kEui64 = {
74*cfb92d14SAndroid Build Coastguard Worker         {2, 3, 5, 7, 11, 13, 17, 19}, // "Prime" EUI64!
75*cfb92d14SAndroid Build Coastguard Worker     };
76*cfb92d14SAndroid Build Coastguard Worker 
77*cfb92d14SAndroid Build Coastguard Worker     const char kString_1[] = "OpenThread";
78*cfb92d14SAndroid Build Coastguard Worker     const char kString_2[] = "";
79*cfb92d14SAndroid Build Coastguard Worker 
80*cfb92d14SAndroid Build Coastguard Worker     const uint16_t kData[] = {10, 20, 3, 15, 1000, 60, 16}; // ... then comes 17,18,19,20  :)
81*cfb92d14SAndroid Build Coastguard Worker 
82*cfb92d14SAndroid Build Coastguard Worker     bool                     b_1, b_2;
83*cfb92d14SAndroid Build Coastguard Worker     uint8_t                  u8;
84*cfb92d14SAndroid Build Coastguard Worker     int8_t                   i8;
85*cfb92d14SAndroid Build Coastguard Worker     uint16_t                 u16;
86*cfb92d14SAndroid Build Coastguard Worker     int16_t                  i16;
87*cfb92d14SAndroid Build Coastguard Worker     uint32_t                 u32;
88*cfb92d14SAndroid Build Coastguard Worker     int32_t                  i32;
89*cfb92d14SAndroid Build Coastguard Worker     uint64_t                 u64;
90*cfb92d14SAndroid Build Coastguard Worker     int64_t                  i64;
91*cfb92d14SAndroid Build Coastguard Worker     unsigned int             u_1, u_2, u_3, u_4;
92*cfb92d14SAndroid Build Coastguard Worker     const spinel_ipv6addr_t *ip6Addr;
93*cfb92d14SAndroid Build Coastguard Worker     const spinel_eui48_t    *eui48;
94*cfb92d14SAndroid Build Coastguard Worker     const spinel_eui64_t    *eui64;
95*cfb92d14SAndroid Build Coastguard Worker     const char              *utf_1;
96*cfb92d14SAndroid Build Coastguard Worker     const char              *utf_2;
97*cfb92d14SAndroid Build Coastguard Worker     const uint8_t           *dataPtr_1;
98*cfb92d14SAndroid Build Coastguard Worker     const uint8_t           *dataPtr_2;
99*cfb92d14SAndroid Build Coastguard Worker     uint16_t                 dataLen_1;
100*cfb92d14SAndroid Build Coastguard Worker     uint16_t                 dataLen_2;
101*cfb92d14SAndroid Build Coastguard Worker 
102*cfb92d14SAndroid Build Coastguard Worker     memset(buffer, 0, sizeof(buffer));
103*cfb92d14SAndroid Build Coastguard Worker 
104*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
105*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 1: Decoding simple types");
106*cfb92d14SAndroid Build Coastguard Worker 
107*cfb92d14SAndroid Build Coastguard Worker     frameLen = spinel_datatype_pack(
108*cfb92d14SAndroid Build Coastguard Worker         buffer, sizeof(buffer),
109*cfb92d14SAndroid Build Coastguard Worker         (SPINEL_DATATYPE_BOOL_S SPINEL_DATATYPE_BOOL_S SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_INT8_S
110*cfb92d14SAndroid Build Coastguard Worker              SPINEL_DATATYPE_UINT16_S SPINEL_DATATYPE_INT16_S SPINEL_DATATYPE_UINT32_S SPINEL_DATATYPE_INT32_S
111*cfb92d14SAndroid Build Coastguard Worker                  SPINEL_DATATYPE_UINT64_S SPINEL_DATATYPE_INT64_S SPINEL_DATATYPE_UINT_PACKED_S
112*cfb92d14SAndroid Build Coastguard Worker                      SPINEL_DATATYPE_UINT_PACKED_S SPINEL_DATATYPE_UINT_PACKED_S SPINEL_DATATYPE_UINT_PACKED_S
113*cfb92d14SAndroid Build Coastguard Worker                          SPINEL_DATATYPE_IPv6ADDR_S SPINEL_DATATYPE_EUI48_S SPINEL_DATATYPE_EUI64_S
114*cfb92d14SAndroid Build Coastguard Worker                              SPINEL_DATATYPE_UTF8_S SPINEL_DATATYPE_UTF8_S SPINEL_DATATYPE_DATA_WLEN_S
115*cfb92d14SAndroid Build Coastguard Worker                                  SPINEL_DATATYPE_DATA_S),
116*cfb92d14SAndroid Build Coastguard Worker         kBool_1, kBool_2, kUint8, kInt8, kUint16, kInt16, kUint32, kInt32, kUint64, kInt64, kUint_1, kUint_2, kUint_3,
117*cfb92d14SAndroid Build Coastguard Worker         kUint_4, &kIp6Addr, &kEui48, &kEui64, kString_1, kString_2, kData, sizeof(kData), kData, sizeof(kData));
118*cfb92d14SAndroid Build Coastguard Worker 
119*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("Packed Spinel Frame", buffer, static_cast<uint16_t>(frameLen));
120*cfb92d14SAndroid Build Coastguard Worker 
121*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
122*cfb92d14SAndroid Build Coastguard Worker 
123*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetFrame() == &buffer[0]);
124*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetLength() == frameLen);
125*cfb92d14SAndroid Build Coastguard Worker 
126*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetReadLength() == 0);
127*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLength() == frameLen);
128*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == false);
129*cfb92d14SAndroid Build Coastguard Worker 
130*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadBool(b_1));
131*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadBool(b_2));
132*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint8(u8));
133*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt8(i8));
134*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint16(u16));
135*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt16(i16));
136*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint32(u32));
137*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt32(i32));
138*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint64(u64));
139*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt64(i64));
140*cfb92d14SAndroid Build Coastguard Worker 
141*cfb92d14SAndroid Build Coastguard Worker     // Check the state
142*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetReadLength() != 0);
143*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLength() == frameLen - decoder.GetReadLength());
144*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == false);
145*cfb92d14SAndroid Build Coastguard Worker 
146*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_1));
147*cfb92d14SAndroid Build Coastguard Worker 
148*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_2));
149*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_3));
150*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_4));
151*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadIp6Address(ip6Addr));
152*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadEui48(eui48));
153*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadEui64(eui64));
154*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUtf8(utf_1));
155*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUtf8(utf_2));
156*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadDataWithLen(dataPtr_1, dataLen_1));
157*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadData(dataPtr_2, dataLen_2));
158*cfb92d14SAndroid Build Coastguard Worker 
159*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetReadLength() == frameLen);
160*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLength() == 0);
161*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == true);
162*cfb92d14SAndroid Build Coastguard Worker 
163*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(b_1 == kBool_1);
164*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(b_2 == kBool_2);
165*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
166*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i8 == kInt8);
167*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u16 == kUint16);
168*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i16 == kInt16);
169*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u32 == kUint32);
170*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i32 == kInt32);
171*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u64 == kUint64);
172*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i64 == kInt64);
173*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_1 == kUint_1);
174*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_2 == kUint_2);
175*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_3 == kUint_3);
176*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_4 == kUint_4);
177*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0);
178*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0);
179*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(eui64, &kEui64, sizeof(spinel_eui64_t)) == 0);
180*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0);
181*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(utf_2, kString_2, sizeof(kString_2)) == 0);
182*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dataLen_1 == sizeof(kData));
183*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(dataPtr_1, &kData, sizeof(kData)) == 0);
184*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dataLen_2 == sizeof(kData));
185*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(dataPtr_2, &kData, sizeof(kData)) == 0);
186*cfb92d14SAndroid Build Coastguard Worker 
187*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
188*cfb92d14SAndroid Build Coastguard Worker 
189*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
190*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 2: Test Reset(), SavePosition(), ResetToSaved()");
191*cfb92d14SAndroid Build Coastguard Worker 
192*cfb92d14SAndroid Build Coastguard Worker     // `ResetToSaved()` should fail if there is no saved position
193*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.ResetToSaved() == OT_ERROR_INVALID_STATE);
194*cfb92d14SAndroid Build Coastguard Worker 
195*cfb92d14SAndroid Build Coastguard Worker     decoder.Reset();
196*cfb92d14SAndroid Build Coastguard Worker 
197*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetFrame() == &buffer[0]);
198*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetLength() == frameLen);
199*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetReadLength() == 0);
200*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLength() == frameLen);
201*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == false);
202*cfb92d14SAndroid Build Coastguard Worker 
203*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadBool(b_1));
204*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadBool(b_2));
205*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint8(u8));
206*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt8(i8));
207*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint16(u16));
208*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt16(i16));
209*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint32(u32));
210*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt32(i32));
211*cfb92d14SAndroid Build Coastguard Worker 
212*cfb92d14SAndroid Build Coastguard Worker     // `ResetToSaved()` should fail if there is no saved position
213*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.ResetToSaved() == OT_ERROR_INVALID_STATE);
214*cfb92d14SAndroid Build Coastguard Worker 
215*cfb92d14SAndroid Build Coastguard Worker     // Save position
216*cfb92d14SAndroid Build Coastguard Worker     decoder.SavePosition();
217*cfb92d14SAndroid Build Coastguard Worker 
218*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint64(u64));
219*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt64(i64));
220*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_1));
221*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_2));
222*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_3));
223*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_4));
224*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadIp6Address(ip6Addr));
225*cfb92d14SAndroid Build Coastguard Worker 
226*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(b_1 == kBool_1);
227*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(b_2 == kBool_2);
228*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
229*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i8 == kInt8);
230*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u16 == kUint16);
231*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i16 == kInt16);
232*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u32 == kUint32);
233*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i32 == kInt32);
234*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u64 == kUint64);
235*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i64 == kInt64);
236*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_1 == kUint_1);
237*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_2 == kUint_2);
238*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_3 == kUint_3);
239*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_4 == kUint_4);
240*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0);
241*cfb92d14SAndroid Build Coastguard Worker 
242*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ResetToSaved());
243*cfb92d14SAndroid Build Coastguard Worker 
244*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint64(u64));
245*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt64(i64));
246*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_1));
247*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_2));
248*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_3));
249*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_4));
250*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadIp6Address(ip6Addr));
251*cfb92d14SAndroid Build Coastguard Worker 
252*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u64 == kUint64);
253*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i64 == kInt64);
254*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_1 == kUint_1);
255*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_2 == kUint_2);
256*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_3 == kUint_3);
257*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_4 == kUint_4);
258*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0);
259*cfb92d14SAndroid Build Coastguard Worker 
260*cfb92d14SAndroid Build Coastguard Worker     // Go back to save position again.
261*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ResetToSaved());
262*cfb92d14SAndroid Build Coastguard Worker 
263*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint64(u64));
264*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt64(i64));
265*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_1));
266*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_2));
267*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_3));
268*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUintPacked(u_4));
269*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadIp6Address(ip6Addr));
270*cfb92d14SAndroid Build Coastguard Worker 
271*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u64 == kUint64);
272*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i64 == kInt64);
273*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_1 == kUint_1);
274*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_2 == kUint_2);
275*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_3 == kUint_3);
276*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_4 == kUint_4);
277*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0);
278*cfb92d14SAndroid Build Coastguard Worker 
279*cfb92d14SAndroid Build Coastguard Worker     // Ensure saved position is cleared when decoder is reset or re-initialized.
280*cfb92d14SAndroid Build Coastguard Worker 
281*cfb92d14SAndroid Build Coastguard Worker     decoder.Reset();
282*cfb92d14SAndroid Build Coastguard Worker 
283*cfb92d14SAndroid Build Coastguard Worker     // `ResetToSaved()` should fail if there is no saved position
284*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.ResetToSaved() == OT_ERROR_INVALID_STATE);
285*cfb92d14SAndroid Build Coastguard Worker 
286*cfb92d14SAndroid Build Coastguard Worker     decoder.SavePosition();
287*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ResetToSaved());
288*cfb92d14SAndroid Build Coastguard Worker 
289*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
290*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.ResetToSaved() == OT_ERROR_INVALID_STATE);
291*cfb92d14SAndroid Build Coastguard Worker 
292*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
293*cfb92d14SAndroid Build Coastguard Worker 
294*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
295*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 3: Test decoding a single simple struct.");
296*cfb92d14SAndroid Build Coastguard Worker 
297*cfb92d14SAndroid Build Coastguard Worker     frameLen = spinel_datatype_pack(buffer, sizeof(buffer),
298*cfb92d14SAndroid Build Coastguard Worker                                     (SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_STRUCT_S(
299*cfb92d14SAndroid Build Coastguard Worker                                         SPINEL_DATATYPE_UINT32_S SPINEL_DATATYPE_EUI48_S SPINEL_DATATYPE_UINT_PACKED_S)
300*cfb92d14SAndroid Build Coastguard Worker                                          SPINEL_DATATYPE_INT16_S
301*cfb92d14SAndroid Build Coastguard Worker 
302*cfb92d14SAndroid Build Coastguard Worker                                      ),
303*cfb92d14SAndroid Build Coastguard Worker                                     kUint8, kUint32, &kEui48, kUint_3, kInt16);
304*cfb92d14SAndroid Build Coastguard Worker 
305*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("Packed Spinel Frame (single struct)", buffer, static_cast<uint16_t>(frameLen));
306*cfb92d14SAndroid Build Coastguard Worker 
307*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
308*cfb92d14SAndroid Build Coastguard Worker 
309*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint8(u8));
310*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
311*cfb92d14SAndroid Build Coastguard Worker     {
312*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint32(u32));
313*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadEui48(eui48));
314*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUintPacked(u_3));
315*cfb92d14SAndroid Build Coastguard Worker     }
316*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
317*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt16(i16));
318*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == true);
319*cfb92d14SAndroid Build Coastguard Worker 
320*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
321*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i16 == kInt16);
322*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u32 == kUint32);
323*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_3 == kUint_3);
324*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0);
325*cfb92d14SAndroid Build Coastguard Worker 
326*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
327*cfb92d14SAndroid Build Coastguard Worker 
328*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
329*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 4: Test partial struct read");
330*cfb92d14SAndroid Build Coastguard Worker 
331*cfb92d14SAndroid Build Coastguard Worker     // Re-use same frame as the previous test.
332*cfb92d14SAndroid Build Coastguard Worker 
333*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
334*cfb92d14SAndroid Build Coastguard Worker 
335*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint8(u8));
336*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
337*cfb92d14SAndroid Build Coastguard Worker     {
338*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint32(u32));
339*cfb92d14SAndroid Build Coastguard Worker         // Skip the remaining fields in the struct
340*cfb92d14SAndroid Build Coastguard Worker     }
341*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
342*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt16(i16));
343*cfb92d14SAndroid Build Coastguard Worker 
344*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
345*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i16 == kInt16);
346*cfb92d14SAndroid Build Coastguard Worker 
347*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
348*cfb92d14SAndroid Build Coastguard Worker 
349*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
350*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 5: Test `GetRemainingLengthInStruct()` and `IsAllReadInStruct`() in and out of an struct");
351*cfb92d14SAndroid Build Coastguard Worker 
352*cfb92d14SAndroid Build Coastguard Worker     // Re-use same frame as the previous test.
353*cfb92d14SAndroid Build Coastguard Worker 
354*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
355*cfb92d14SAndroid Build Coastguard Worker 
356*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetFrame() == &buffer[0]);
357*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetLength() == frameLen);
358*cfb92d14SAndroid Build Coastguard Worker 
359*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetReadLength() == 0);
360*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLength() == frameLen);
361*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == false);
362*cfb92d14SAndroid Build Coastguard Worker 
363*cfb92d14SAndroid Build Coastguard Worker     // When not in an struct,  `etRemainingLengthInStruct()` should consider the whole frame.
364*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLengthInStruct() == frameLen);
365*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllReadInStruct() == false);
366*cfb92d14SAndroid Build Coastguard Worker 
367*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint8(u8));
368*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
369*cfb92d14SAndroid Build Coastguard Worker     {
370*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(decoder.IsAllReadInStruct() == false);
371*cfb92d14SAndroid Build Coastguard Worker 
372*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint32(u32));
373*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadEui48(eui48));
374*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUintPacked(u_3));
375*cfb92d14SAndroid Build Coastguard Worker 
376*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(decoder.IsAllReadInStruct() == true);
377*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(decoder.GetRemainingLengthInStruct() == 0);
378*cfb92d14SAndroid Build Coastguard Worker 
379*cfb92d14SAndroid Build Coastguard Worker         // Try reading beyond end of the struct and ensure it fails.
380*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(decoder.ReadUint8(u8) == OT_ERROR_PARSE);
381*cfb92d14SAndroid Build Coastguard Worker 
382*cfb92d14SAndroid Build Coastguard Worker         // `ReadData()` at end of struct should still succeed but return zero as the data length.
383*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadData(dataPtr_1, dataLen_1));
384*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(dataLen_1 == 0);
385*cfb92d14SAndroid Build Coastguard Worker     }
386*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
387*cfb92d14SAndroid Build Coastguard Worker 
388*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllReadInStruct() == false);
389*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt16(i16));
390*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == true);
391*cfb92d14SAndroid Build Coastguard Worker 
392*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLengthInStruct() == 0);
393*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllReadInStruct() == true);
394*cfb92d14SAndroid Build Coastguard Worker 
395*cfb92d14SAndroid Build Coastguard Worker     // `ReadData()` at end of frame should still succeed but return zero as the data length.
396*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadData(dataPtr_1, dataLen_1));
397*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(dataLen_1 == 0);
398*cfb92d14SAndroid Build Coastguard Worker 
399*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
400*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i16 == kInt16);
401*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u32 == kUint32);
402*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u_3 == kUint_3);
403*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0);
404*cfb92d14SAndroid Build Coastguard Worker 
405*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
406*cfb92d14SAndroid Build Coastguard Worker 
407*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
408*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 6: Test multiple nested structs");
409*cfb92d14SAndroid Build Coastguard Worker 
410*cfb92d14SAndroid Build Coastguard Worker     frameLen = spinel_datatype_pack(
411*cfb92d14SAndroid Build Coastguard Worker         buffer, sizeof(buffer),
412*cfb92d14SAndroid Build Coastguard Worker         (SPINEL_DATATYPE_STRUCT_S(SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_UTF8_S SPINEL_DATATYPE_STRUCT_S(
413*cfb92d14SAndroid Build Coastguard Worker             SPINEL_DATATYPE_BOOL_S SPINEL_DATATYPE_IPv6ADDR_S) SPINEL_DATATYPE_UINT16_S)
414*cfb92d14SAndroid Build Coastguard Worker              SPINEL_DATATYPE_EUI48_S SPINEL_DATATYPE_STRUCT_S(SPINEL_DATATYPE_UINT32_S) SPINEL_DATATYPE_INT32_S),
415*cfb92d14SAndroid Build Coastguard Worker         kUint8, kString_1, kBool_1, &kIp6Addr, kUint16, &kEui48, kUint32, kInt32);
416*cfb92d14SAndroid Build Coastguard Worker 
417*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("Packed Spinel Frame (multiple struct)", buffer, static_cast<uint16_t>(frameLen));
418*cfb92d14SAndroid Build Coastguard Worker 
419*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
420*cfb92d14SAndroid Build Coastguard Worker 
421*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
422*cfb92d14SAndroid Build Coastguard Worker     {
423*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint8(u8));
424*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUtf8(utf_1));
425*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.OpenStruct());
426*cfb92d14SAndroid Build Coastguard Worker         {
427*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadBool(b_1));
428*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadIp6Address(ip6Addr));
429*cfb92d14SAndroid Build Coastguard Worker         }
430*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.CloseStruct());
431*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint16(u16));
432*cfb92d14SAndroid Build Coastguard Worker     }
433*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
434*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadEui48(eui48));
435*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
436*cfb92d14SAndroid Build Coastguard Worker     {
437*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint32(u32));
438*cfb92d14SAndroid Build Coastguard Worker     }
439*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
440*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt32(i32));
441*cfb92d14SAndroid Build Coastguard Worker 
442*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetReadLength() == frameLen);
443*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLength() == 0);
444*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == true);
445*cfb92d14SAndroid Build Coastguard Worker 
446*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(b_1 == kBool_1);
447*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
448*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u16 == kUint16);
449*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u32 == kUint32);
450*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i32 == kInt32);
451*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0);
452*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0);
453*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0);
454*cfb92d14SAndroid Build Coastguard Worker 
455*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
456*cfb92d14SAndroid Build Coastguard Worker 
457*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
458*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 7: Test `SavePosition()`, `ResetToSaved()` for nested structs");
459*cfb92d14SAndroid Build Coastguard Worker 
460*cfb92d14SAndroid Build Coastguard Worker     // Re-use same frame as the previous test.
461*cfb92d14SAndroid Build Coastguard Worker 
462*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
463*cfb92d14SAndroid Build Coastguard Worker 
464*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
465*cfb92d14SAndroid Build Coastguard Worker     {
466*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint8(u8));
467*cfb92d14SAndroid Build Coastguard Worker 
468*cfb92d14SAndroid Build Coastguard Worker         decoder.SavePosition();
469*cfb92d14SAndroid Build Coastguard Worker 
470*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUtf8(utf_1));
471*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.OpenStruct());
472*cfb92d14SAndroid Build Coastguard Worker         {
473*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadBool(b_1));
474*cfb92d14SAndroid Build Coastguard Worker         }
475*cfb92d14SAndroid Build Coastguard Worker 
476*cfb92d14SAndroid Build Coastguard Worker         // Verify the read content so far.
477*cfb92d14SAndroid Build Coastguard Worker 
478*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(u8 == kUint8);
479*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(b_1 == kBool_1);
480*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0);
481*cfb92d14SAndroid Build Coastguard Worker 
482*cfb92d14SAndroid Build Coastguard Worker         // Do not close the inner struct and jump to previously saved position and re-read the content.
483*cfb92d14SAndroid Build Coastguard Worker 
484*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ResetToSaved());
485*cfb92d14SAndroid Build Coastguard Worker 
486*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUtf8(utf_1));
487*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.OpenStruct());
488*cfb92d14SAndroid Build Coastguard Worker         {
489*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadBool(b_1));
490*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadIp6Address(ip6Addr));
491*cfb92d14SAndroid Build Coastguard Worker         }
492*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.CloseStruct());
493*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint16(u16));
494*cfb92d14SAndroid Build Coastguard Worker     }
495*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
496*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadEui48(eui48));
497*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
498*cfb92d14SAndroid Build Coastguard Worker     {
499*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint32(u32));
500*cfb92d14SAndroid Build Coastguard Worker     }
501*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
502*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt32(i32));
503*cfb92d14SAndroid Build Coastguard Worker 
504*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetReadLength() == frameLen);
505*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLength() == 0);
506*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == true);
507*cfb92d14SAndroid Build Coastguard Worker 
508*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(b_1 == kBool_1);
509*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
510*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u16 == kUint16);
511*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u32 == kUint32);
512*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i32 == kInt32);
513*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0);
514*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0);
515*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0);
516*cfb92d14SAndroid Build Coastguard Worker 
517*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
518*cfb92d14SAndroid Build Coastguard Worker 
519*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
520*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 8: Test saving position at start of an open struct");
521*cfb92d14SAndroid Build Coastguard Worker 
522*cfb92d14SAndroid Build Coastguard Worker     // Re-use same frame as the previous test.
523*cfb92d14SAndroid Build Coastguard Worker 
524*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
525*cfb92d14SAndroid Build Coastguard Worker 
526*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
527*cfb92d14SAndroid Build Coastguard Worker     {
528*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint8(u8));
529*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUtf8(utf_1));
530*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.OpenStruct());
531*cfb92d14SAndroid Build Coastguard Worker         {
532*cfb92d14SAndroid Build Coastguard Worker             // Save position at start of the struct
533*cfb92d14SAndroid Build Coastguard Worker             decoder.SavePosition();
534*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadBool(b_1));
535*cfb92d14SAndroid Build Coastguard Worker 
536*cfb92d14SAndroid Build Coastguard Worker             // Verify the read content so far.
537*cfb92d14SAndroid Build Coastguard Worker 
538*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(u8 == kUint8);
539*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0);
540*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(b_1 == kBool_1);
541*cfb92d14SAndroid Build Coastguard Worker 
542*cfb92d14SAndroid Build Coastguard Worker             // Do not close the struct and jump to the previously saved position and re-read the content.
543*cfb92d14SAndroid Build Coastguard Worker 
544*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ResetToSaved());
545*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadBool(b_1));
546*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadIp6Address(ip6Addr));
547*cfb92d14SAndroid Build Coastguard Worker         }
548*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.CloseStruct());
549*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint16(u16));
550*cfb92d14SAndroid Build Coastguard Worker     }
551*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
552*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadEui48(eui48));
553*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
554*cfb92d14SAndroid Build Coastguard Worker     {
555*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint32(u32));
556*cfb92d14SAndroid Build Coastguard Worker     }
557*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.CloseStruct());
558*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadInt32(i32));
559*cfb92d14SAndroid Build Coastguard Worker 
560*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetReadLength() == frameLen);
561*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.GetRemainingLength() == 0);
562*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.IsAllRead() == true);
563*cfb92d14SAndroid Build Coastguard Worker 
564*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(b_1 == kBool_1);
565*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
566*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u16 == kUint16);
567*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u32 == kUint32);
568*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(i32 == kInt32);
569*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(ip6Addr, &kIp6Addr, sizeof(spinel_ipv6addr_t)) == 0);
570*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(eui48, &kEui48, sizeof(spinel_eui48_t)) == 0);
571*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(memcmp(utf_1, kString_1, sizeof(kString_1)) == 0);
572*cfb92d14SAndroid Build Coastguard Worker 
573*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
574*cfb92d14SAndroid Build Coastguard Worker 
575*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
576*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 9: Test `ResetToSaved()` failure case (jumping back to a saved position closed struct).");
577*cfb92d14SAndroid Build Coastguard Worker 
578*cfb92d14SAndroid Build Coastguard Worker     // Re-use same frame as the previous test.
579*cfb92d14SAndroid Build Coastguard Worker 
580*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
581*cfb92d14SAndroid Build Coastguard Worker 
582*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.OpenStruct());
583*cfb92d14SAndroid Build Coastguard Worker     {
584*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint8(u8));
585*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUtf8(utf_1));
586*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.OpenStruct());
587*cfb92d14SAndroid Build Coastguard Worker         {
588*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadBool(b_1));
589*cfb92d14SAndroid Build Coastguard Worker 
590*cfb92d14SAndroid Build Coastguard Worker             decoder.SavePosition();
591*cfb92d14SAndroid Build Coastguard Worker 
592*cfb92d14SAndroid Build Coastguard Worker             SuccessOrQuit(decoder.ReadIp6Address(ip6Addr));
593*cfb92d14SAndroid Build Coastguard Worker         }
594*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.CloseStruct());
595*cfb92d14SAndroid Build Coastguard Worker         SuccessOrQuit(decoder.ReadUint16(u16));
596*cfb92d14SAndroid Build Coastguard Worker 
597*cfb92d14SAndroid Build Coastguard Worker         // `ResetToSaved()` should fail since the enclosing struct for the saved position is closed.
598*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(decoder.ResetToSaved() == OT_ERROR_INVALID_STATE);
599*cfb92d14SAndroid Build Coastguard Worker     }
600*cfb92d14SAndroid Build Coastguard Worker 
601*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
602*cfb92d14SAndroid Build Coastguard Worker 
603*cfb92d14SAndroid Build Coastguard Worker     printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
604*cfb92d14SAndroid Build Coastguard Worker     printf("\nTest 10: Testing error cases and failures. (e.g., wrong struct length).");
605*cfb92d14SAndroid Build Coastguard Worker 
606*cfb92d14SAndroid Build Coastguard Worker     frameLen = spinel_datatype_pack(buffer, sizeof(buffer),
607*cfb92d14SAndroid Build Coastguard Worker                                     (SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_UINT16_S // Treat this as struct length
608*cfb92d14SAndroid Build Coastguard Worker                                          SPINEL_DATATYPE_BOOL_S),
609*cfb92d14SAndroid Build Coastguard Worker                                     kUint8, 10, kBool_1);
610*cfb92d14SAndroid Build Coastguard Worker 
611*cfb92d14SAndroid Build Coastguard Worker     DumpBuffer("Packed Spinel Frame (incorrect format)", buffer, static_cast<uint16_t>(frameLen));
612*cfb92d14SAndroid Build Coastguard Worker 
613*cfb92d14SAndroid Build Coastguard Worker     decoder.Init(buffer, static_cast<uint16_t>(frameLen));
614*cfb92d14SAndroid Build Coastguard Worker 
615*cfb92d14SAndroid Build Coastguard Worker     decoder.SavePosition();
616*cfb92d14SAndroid Build Coastguard Worker 
617*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint8(u8));
618*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
619*cfb92d14SAndroid Build Coastguard Worker 
620*cfb92d14SAndroid Build Coastguard Worker     // `OpenStruct()` should fail, since it expects a length 10 but there are not enough
621*cfb92d14SAndroid Build Coastguard Worker     // bytes in the frame.
622*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.OpenStruct() == OT_ERROR_PARSE);
623*cfb92d14SAndroid Build Coastguard Worker 
624*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ResetToSaved());
625*cfb92d14SAndroid Build Coastguard Worker 
626*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint8(u8));
627*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(u8 == kUint8);
628*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.ReadDataWithLen(dataPtr_1, dataLen_1) == OT_ERROR_PARSE);
629*cfb92d14SAndroid Build Coastguard Worker 
630*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ResetToSaved());
631*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint8(u8));
632*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadUint16(u16));
633*cfb92d14SAndroid Build Coastguard Worker     SuccessOrQuit(decoder.ReadBool(b_1));
634*cfb92d14SAndroid Build Coastguard Worker 
635*cfb92d14SAndroid Build Coastguard Worker     // Try reading beyond end of frame.
636*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(decoder.ReadUint8(u8) == OT_ERROR_PARSE);
637*cfb92d14SAndroid Build Coastguard Worker 
638*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
639*cfb92d14SAndroid Build Coastguard Worker }
640*cfb92d14SAndroid Build Coastguard Worker 
641*cfb92d14SAndroid Build Coastguard Worker } // namespace Spinel
642*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
643*cfb92d14SAndroid Build Coastguard Worker 
main(void)644*cfb92d14SAndroid Build Coastguard Worker int main(void)
645*cfb92d14SAndroid Build Coastguard Worker {
646*cfb92d14SAndroid Build Coastguard Worker     ot::Spinel::Decoder();
647*cfb92d14SAndroid Build Coastguard Worker     printf("\nAll tests passed.\n");
648*cfb92d14SAndroid Build Coastguard Worker     return 0;
649*cfb92d14SAndroid Build Coastguard Worker }
650