xref: /aosp_15_r20/external/openthread/tests/unit/test_child_table.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2018, 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 "test_platform.h"
30*cfb92d14SAndroid Build Coastguard Worker 
31*cfb92d14SAndroid Build Coastguard Worker #include <openthread/config.h>
32*cfb92d14SAndroid Build Coastguard Worker 
33*cfb92d14SAndroid Build Coastguard Worker #include "test_util.h"
34*cfb92d14SAndroid Build Coastguard Worker #include "common/array.hpp"
35*cfb92d14SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
36*cfb92d14SAndroid Build Coastguard Worker #include "instance/instance.hpp"
37*cfb92d14SAndroid Build Coastguard Worker #include "thread/child_table.hpp"
38*cfb92d14SAndroid Build Coastguard Worker 
39*cfb92d14SAndroid Build Coastguard Worker namespace ot {
40*cfb92d14SAndroid Build Coastguard Worker 
41*cfb92d14SAndroid Build Coastguard Worker static Instance *sInstance;
42*cfb92d14SAndroid Build Coastguard Worker 
43*cfb92d14SAndroid Build Coastguard Worker enum
44*cfb92d14SAndroid Build Coastguard Worker {
45*cfb92d14SAndroid Build Coastguard Worker     kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN,
46*cfb92d14SAndroid Build Coastguard Worker };
47*cfb92d14SAndroid Build Coastguard Worker 
48*cfb92d14SAndroid Build Coastguard Worker struct TestChild
49*cfb92d14SAndroid Build Coastguard Worker {
50*cfb92d14SAndroid Build Coastguard Worker     Child::State mState;
51*cfb92d14SAndroid Build Coastguard Worker     uint16_t     mRloc16;
52*cfb92d14SAndroid Build Coastguard Worker     otExtAddress mExtAddress;
53*cfb92d14SAndroid Build Coastguard Worker };
54*cfb92d14SAndroid Build Coastguard Worker 
55*cfb92d14SAndroid Build Coastguard Worker const Child::StateFilter kAllFilters[] = {
56*cfb92d14SAndroid Build Coastguard Worker     Child::kInStateValid,
57*cfb92d14SAndroid Build Coastguard Worker     Child::kInStateValidOrRestoring,
58*cfb92d14SAndroid Build Coastguard Worker     Child::kInStateChildIdRequest,
59*cfb92d14SAndroid Build Coastguard Worker     Child::kInStateValidOrAttaching,
60*cfb92d14SAndroid Build Coastguard Worker     Child::kInStateAnyExceptInvalid,
61*cfb92d14SAndroid Build Coastguard Worker };
62*cfb92d14SAndroid Build Coastguard Worker 
63*cfb92d14SAndroid Build Coastguard Worker // Checks whether a `Child` matches the `TestChild` struct.
ChildMatches(const Child & aChild,const TestChild & aTestChild)64*cfb92d14SAndroid Build Coastguard Worker static bool ChildMatches(const Child &aChild, const TestChild &aTestChild)
65*cfb92d14SAndroid Build Coastguard Worker {
66*cfb92d14SAndroid Build Coastguard Worker     return (aChild.GetState() == aTestChild.mState) && (aChild.GetRloc16() == aTestChild.mRloc16) &&
67*cfb92d14SAndroid Build Coastguard Worker            (aChild.GetExtAddress() == static_cast<const Mac::ExtAddress &>(aTestChild.mExtAddress));
68*cfb92d14SAndroid Build Coastguard Worker }
69*cfb92d14SAndroid Build Coastguard Worker 
70*cfb92d14SAndroid Build Coastguard Worker // Checks whether a `Child::State` matches a `Child::StateFilter`.
StateMatchesFilter(Child::State aState,Child::StateFilter aFilter)71*cfb92d14SAndroid Build Coastguard Worker static bool StateMatchesFilter(Child::State aState, Child::StateFilter aFilter)
72*cfb92d14SAndroid Build Coastguard Worker {
73*cfb92d14SAndroid Build Coastguard Worker     bool  rval = false;
74*cfb92d14SAndroid Build Coastguard Worker     Child child;
75*cfb92d14SAndroid Build Coastguard Worker 
76*cfb92d14SAndroid Build Coastguard Worker     child.SetState(aState);
77*cfb92d14SAndroid Build Coastguard Worker 
78*cfb92d14SAndroid Build Coastguard Worker     switch (aFilter)
79*cfb92d14SAndroid Build Coastguard Worker     {
80*cfb92d14SAndroid Build Coastguard Worker     case Child::kInStateAnyExceptInvalid:
81*cfb92d14SAndroid Build Coastguard Worker         rval = (aState != Child::kStateInvalid);
82*cfb92d14SAndroid Build Coastguard Worker         break;
83*cfb92d14SAndroid Build Coastguard Worker 
84*cfb92d14SAndroid Build Coastguard Worker     case Child::kInStateValid:
85*cfb92d14SAndroid Build Coastguard Worker         rval = (aState == Child::kStateValid);
86*cfb92d14SAndroid Build Coastguard Worker         break;
87*cfb92d14SAndroid Build Coastguard Worker 
88*cfb92d14SAndroid Build Coastguard Worker     case Child::kInStateValidOrRestoring:
89*cfb92d14SAndroid Build Coastguard Worker         rval = child.IsStateValidOrRestoring();
90*cfb92d14SAndroid Build Coastguard Worker         break;
91*cfb92d14SAndroid Build Coastguard Worker 
92*cfb92d14SAndroid Build Coastguard Worker     case Child::kInStateChildIdRequest:
93*cfb92d14SAndroid Build Coastguard Worker         rval = (aState == Child::kStateChildIdRequest);
94*cfb92d14SAndroid Build Coastguard Worker         break;
95*cfb92d14SAndroid Build Coastguard Worker 
96*cfb92d14SAndroid Build Coastguard Worker     case Child::kInStateValidOrAttaching:
97*cfb92d14SAndroid Build Coastguard Worker         rval = child.IsStateValidOrAttaching();
98*cfb92d14SAndroid Build Coastguard Worker         break;
99*cfb92d14SAndroid Build Coastguard Worker 
100*cfb92d14SAndroid Build Coastguard Worker     case Child::kInStateInvalid:
101*cfb92d14SAndroid Build Coastguard Worker         rval = child.IsStateInvalid();
102*cfb92d14SAndroid Build Coastguard Worker         break;
103*cfb92d14SAndroid Build Coastguard Worker 
104*cfb92d14SAndroid Build Coastguard Worker     case Child::kInStateAnyExceptValidOrRestoring:
105*cfb92d14SAndroid Build Coastguard Worker         rval = !child.IsStateValidOrRestoring();
106*cfb92d14SAndroid Build Coastguard Worker         break;
107*cfb92d14SAndroid Build Coastguard Worker 
108*cfb92d14SAndroid Build Coastguard Worker     case Child::kInStateAny:
109*cfb92d14SAndroid Build Coastguard Worker         rval = true;
110*cfb92d14SAndroid Build Coastguard Worker         break;
111*cfb92d14SAndroid Build Coastguard Worker     }
112*cfb92d14SAndroid Build Coastguard Worker 
113*cfb92d14SAndroid Build Coastguard Worker     return rval;
114*cfb92d14SAndroid Build Coastguard Worker }
115*cfb92d14SAndroid Build Coastguard Worker 
116*cfb92d14SAndroid Build Coastguard Worker // Verifies that `ChildTable` contains a given list of `TestChild` entries.
VerifyChildTableContent(ChildTable & aTable,uint16_t aChildListLength,const TestChild * aChildList)117*cfb92d14SAndroid Build Coastguard Worker void VerifyChildTableContent(ChildTable &aTable, uint16_t aChildListLength, const TestChild *aChildList)
118*cfb92d14SAndroid Build Coastguard Worker {
119*cfb92d14SAndroid Build Coastguard Worker     printf("Test ChildTable with %d entries", aChildListLength);
120*cfb92d14SAndroid Build Coastguard Worker 
121*cfb92d14SAndroid Build Coastguard Worker     for (Child::StateFilter filter : kAllFilters)
122*cfb92d14SAndroid Build Coastguard Worker     {
123*cfb92d14SAndroid Build Coastguard Worker         // Verify that we can find all children from given list by rloc or extended address.
124*cfb92d14SAndroid Build Coastguard Worker 
125*cfb92d14SAndroid Build Coastguard Worker         for (uint16_t listIndex = 0; listIndex < aChildListLength; listIndex++)
126*cfb92d14SAndroid Build Coastguard Worker         {
127*cfb92d14SAndroid Build Coastguard Worker             Child       *child;
128*cfb92d14SAndroid Build Coastguard Worker             Mac::Address address;
129*cfb92d14SAndroid Build Coastguard Worker 
130*cfb92d14SAndroid Build Coastguard Worker             if (!StateMatchesFilter(aChildList[listIndex].mState, filter))
131*cfb92d14SAndroid Build Coastguard Worker             {
132*cfb92d14SAndroid Build Coastguard Worker                 continue;
133*cfb92d14SAndroid Build Coastguard Worker             }
134*cfb92d14SAndroid Build Coastguard Worker 
135*cfb92d14SAndroid Build Coastguard Worker             child = aTable.FindChild(aChildList[listIndex].mRloc16, filter);
136*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(child != nullptr, "FindChild(rloc) failed");
137*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(ChildMatches(*child, aChildList[listIndex]), "FindChild(rloc) returned incorrect child");
138*cfb92d14SAndroid Build Coastguard Worker 
139*cfb92d14SAndroid Build Coastguard Worker             child = aTable.FindChild(static_cast<const Mac::ExtAddress &>(aChildList[listIndex].mExtAddress), filter);
140*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(child != nullptr, "FindChild(ExtAddress) failed");
141*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(ChildMatches(*child, aChildList[listIndex]), "FindChild(ExtAddress) returned incorrect child");
142*cfb92d14SAndroid Build Coastguard Worker 
143*cfb92d14SAndroid Build Coastguard Worker             address.SetShort(aChildList[listIndex].mRloc16);
144*cfb92d14SAndroid Build Coastguard Worker             child = aTable.FindChild(address, filter);
145*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(child != nullptr, "FindChild(address) failed");
146*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(ChildMatches(*child, aChildList[listIndex]), "FindChild(address) returned incorrect child");
147*cfb92d14SAndroid Build Coastguard Worker 
148*cfb92d14SAndroid Build Coastguard Worker             address.SetExtended(static_cast<const Mac::ExtAddress &>(aChildList[listIndex].mExtAddress));
149*cfb92d14SAndroid Build Coastguard Worker             child = aTable.FindChild(address, filter);
150*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(child != nullptr, "FindChild(address) failed");
151*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(ChildMatches(*child, aChildList[listIndex]), "FindChild(address) returned incorrect child");
152*cfb92d14SAndroid Build Coastguard Worker         }
153*cfb92d14SAndroid Build Coastguard Worker 
154*cfb92d14SAndroid Build Coastguard Worker         // Verify `ChildTable::Iterator` behavior.
155*cfb92d14SAndroid Build Coastguard Worker 
156*cfb92d14SAndroid Build Coastguard Worker         {
157*cfb92d14SAndroid Build Coastguard Worker             ChildTable::Iterator iter(*sInstance, filter);
158*cfb92d14SAndroid Build Coastguard Worker             bool                 childObserved[kMaxChildren];
159*cfb92d14SAndroid Build Coastguard Worker             uint16_t             numChildren = 0;
160*cfb92d14SAndroid Build Coastguard Worker 
161*cfb92d14SAndroid Build Coastguard Worker             memset(childObserved, 0, sizeof(childObserved));
162*cfb92d14SAndroid Build Coastguard Worker 
163*cfb92d14SAndroid Build Coastguard Worker             // Use the iterator and verify that each returned `Child` entry is in the expected list.
164*cfb92d14SAndroid Build Coastguard Worker 
165*cfb92d14SAndroid Build Coastguard Worker             for (; !iter.IsDone(); iter++)
166*cfb92d14SAndroid Build Coastguard Worker             {
167*cfb92d14SAndroid Build Coastguard Worker                 Child   *child    = iter.GetChild();
168*cfb92d14SAndroid Build Coastguard Worker                 Child   &childRef = *iter;
169*cfb92d14SAndroid Build Coastguard Worker                 bool     didFind  = false;
170*cfb92d14SAndroid Build Coastguard Worker                 uint16_t childIndex;
171*cfb92d14SAndroid Build Coastguard Worker 
172*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(child != nullptr, "iter.GetChild() failed");
173*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(&childRef == child, "iter.operator*() failed");
174*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(iter->GetRloc16() == child->GetRloc16(), "iter.operator->() failed");
175*cfb92d14SAndroid Build Coastguard Worker 
176*cfb92d14SAndroid Build Coastguard Worker                 childIndex = aTable.GetChildIndex(*child);
177*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(childIndex < aTable.GetMaxChildrenAllowed(), "Child Index is out of bound");
178*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(aTable.GetChildAtIndex(childIndex) == child, "GetChildAtIndex() failed");
179*cfb92d14SAndroid Build Coastguard Worker 
180*cfb92d14SAndroid Build Coastguard Worker                 for (uint16_t index = 0; index < aChildListLength; index++)
181*cfb92d14SAndroid Build Coastguard Worker                 {
182*cfb92d14SAndroid Build Coastguard Worker                     if (ChildMatches(*iter.GetChild(), aChildList[index]))
183*cfb92d14SAndroid Build Coastguard Worker                     {
184*cfb92d14SAndroid Build Coastguard Worker                         childObserved[index] = true;
185*cfb92d14SAndroid Build Coastguard Worker                         numChildren++;
186*cfb92d14SAndroid Build Coastguard Worker                         didFind = true;
187*cfb92d14SAndroid Build Coastguard Worker                         break;
188*cfb92d14SAndroid Build Coastguard Worker                     }
189*cfb92d14SAndroid Build Coastguard Worker                 }
190*cfb92d14SAndroid Build Coastguard Worker 
191*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(didFind, "ChildTable::Iterator returned an entry not in the expected list");
192*cfb92d14SAndroid Build Coastguard Worker             }
193*cfb92d14SAndroid Build Coastguard Worker 
194*cfb92d14SAndroid Build Coastguard Worker             // Verify that when iterator is done, it points to `nullptr`.
195*cfb92d14SAndroid Build Coastguard Worker 
196*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(iter.GetChild() == nullptr);
197*cfb92d14SAndroid Build Coastguard Worker 
198*cfb92d14SAndroid Build Coastguard Worker             iter++;
199*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(iter.IsDone(), "iterator Advance() (after iterator is done) failed");
200*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(iter.GetChild() == nullptr);
201*cfb92d14SAndroid Build Coastguard Worker 
202*cfb92d14SAndroid Build Coastguard Worker             // Verify that the number of children matches the number of entries we get from iterator.
203*cfb92d14SAndroid Build Coastguard Worker 
204*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(aTable.GetNumChildren(filter) == numChildren);
205*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(aTable.HasChildren(filter) == (numChildren != 0));
206*cfb92d14SAndroid Build Coastguard Worker 
207*cfb92d14SAndroid Build Coastguard Worker             // Verify that there is no missing or extra entry between the expected list
208*cfb92d14SAndroid Build Coastguard Worker             // and what was observed/returned by the iterator.
209*cfb92d14SAndroid Build Coastguard Worker 
210*cfb92d14SAndroid Build Coastguard Worker             for (uint16_t index = 0; index < aChildListLength; index++)
211*cfb92d14SAndroid Build Coastguard Worker             {
212*cfb92d14SAndroid Build Coastguard Worker                 if (StateMatchesFilter(aChildList[index].mState, filter))
213*cfb92d14SAndroid Build Coastguard Worker                 {
214*cfb92d14SAndroid Build Coastguard Worker                     VerifyOrQuit(childObserved[index], "iterator failed to return an expected entry");
215*cfb92d14SAndroid Build Coastguard Worker                 }
216*cfb92d14SAndroid Build Coastguard Worker                 else
217*cfb92d14SAndroid Build Coastguard Worker                 {
218*cfb92d14SAndroid Build Coastguard Worker                     VerifyOrQuit(!childObserved[index], "iterator returned an extra unexpected entry");
219*cfb92d14SAndroid Build Coastguard Worker                 }
220*cfb92d14SAndroid Build Coastguard Worker             }
221*cfb92d14SAndroid Build Coastguard Worker 
222*cfb92d14SAndroid Build Coastguard Worker             // Verify the behavior of range-based `for` iteration.
223*cfb92d14SAndroid Build Coastguard Worker 
224*cfb92d14SAndroid Build Coastguard Worker             iter.Reset();
225*cfb92d14SAndroid Build Coastguard Worker 
226*cfb92d14SAndroid Build Coastguard Worker             for (Child &child : aTable.Iterate(filter))
227*cfb92d14SAndroid Build Coastguard Worker             {
228*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(&child == iter.GetChild(), "range-based for loop Iterate() failed");
229*cfb92d14SAndroid Build Coastguard Worker                 iter++;
230*cfb92d14SAndroid Build Coastguard Worker             }
231*cfb92d14SAndroid Build Coastguard Worker 
232*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(iter.IsDone(), "range-based for loop Iterate() did not return all entries");
233*cfb92d14SAndroid Build Coastguard Worker         }
234*cfb92d14SAndroid Build Coastguard Worker     }
235*cfb92d14SAndroid Build Coastguard Worker 
236*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
237*cfb92d14SAndroid Build Coastguard Worker }
238*cfb92d14SAndroid Build Coastguard Worker 
TestChildTable(void)239*cfb92d14SAndroid Build Coastguard Worker void TestChildTable(void)
240*cfb92d14SAndroid Build Coastguard Worker {
241*cfb92d14SAndroid Build Coastguard Worker     const TestChild testChildList[] = {
242*cfb92d14SAndroid Build Coastguard Worker         {
243*cfb92d14SAndroid Build Coastguard Worker             Child::kStateValid,
244*cfb92d14SAndroid Build Coastguard Worker             0x8001,
245*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x16}},
246*cfb92d14SAndroid Build Coastguard Worker         },
247*cfb92d14SAndroid Build Coastguard Worker         {
248*cfb92d14SAndroid Build Coastguard Worker             Child::kStateParentRequest,
249*cfb92d14SAndroid Build Coastguard Worker             0x8002,
250*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x17}},
251*cfb92d14SAndroid Build Coastguard Worker         },
252*cfb92d14SAndroid Build Coastguard Worker         {
253*cfb92d14SAndroid Build Coastguard Worker             Child::kStateValid,
254*cfb92d14SAndroid Build Coastguard Worker             0x8003,
255*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x18}},
256*cfb92d14SAndroid Build Coastguard Worker         },
257*cfb92d14SAndroid Build Coastguard Worker         {
258*cfb92d14SAndroid Build Coastguard Worker             Child::kStateValid,
259*cfb92d14SAndroid Build Coastguard Worker             0x8004,
260*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x19}},
261*cfb92d14SAndroid Build Coastguard Worker         },
262*cfb92d14SAndroid Build Coastguard Worker         {
263*cfb92d14SAndroid Build Coastguard Worker             Child::kStateRestored,
264*cfb92d14SAndroid Build Coastguard Worker             0x8005,
265*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x20}},
266*cfb92d14SAndroid Build Coastguard Worker         },
267*cfb92d14SAndroid Build Coastguard Worker         {
268*cfb92d14SAndroid Build Coastguard Worker             Child::kStateValid,
269*cfb92d14SAndroid Build Coastguard Worker             0x8006,
270*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x21}},
271*cfb92d14SAndroid Build Coastguard Worker         },
272*cfb92d14SAndroid Build Coastguard Worker         {
273*cfb92d14SAndroid Build Coastguard Worker             Child::kStateChildIdRequest,
274*cfb92d14SAndroid Build Coastguard Worker             0x8007,
275*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x22}},
276*cfb92d14SAndroid Build Coastguard Worker         },
277*cfb92d14SAndroid Build Coastguard Worker         {
278*cfb92d14SAndroid Build Coastguard Worker             Child::kStateChildUpdateRequest,
279*cfb92d14SAndroid Build Coastguard Worker             0x8008,
280*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x23}},
281*cfb92d14SAndroid Build Coastguard Worker         },
282*cfb92d14SAndroid Build Coastguard Worker         {
283*cfb92d14SAndroid Build Coastguard Worker             Child::kStateParentResponse,
284*cfb92d14SAndroid Build Coastguard Worker             0x8009,
285*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x24}},
286*cfb92d14SAndroid Build Coastguard Worker         },
287*cfb92d14SAndroid Build Coastguard Worker         {
288*cfb92d14SAndroid Build Coastguard Worker             Child::kStateRestored,
289*cfb92d14SAndroid Build Coastguard Worker             0x800a,
290*cfb92d14SAndroid Build Coastguard Worker             {{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x25}},
291*cfb92d14SAndroid Build Coastguard Worker         },
292*cfb92d14SAndroid Build Coastguard Worker     };
293*cfb92d14SAndroid Build Coastguard Worker 
294*cfb92d14SAndroid Build Coastguard Worker     const uint16_t testListLength = GetArrayLength(testChildList);
295*cfb92d14SAndroid Build Coastguard Worker 
296*cfb92d14SAndroid Build Coastguard Worker     uint16_t testNumAllowedChildren = 2;
297*cfb92d14SAndroid Build Coastguard Worker 
298*cfb92d14SAndroid Build Coastguard Worker     ChildTable *table;
299*cfb92d14SAndroid Build Coastguard Worker     Error       error;
300*cfb92d14SAndroid Build Coastguard Worker 
301*cfb92d14SAndroid Build Coastguard Worker     sInstance = testInitInstance();
302*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(sInstance != nullptr);
303*cfb92d14SAndroid Build Coastguard Worker 
304*cfb92d14SAndroid Build Coastguard Worker     table = &sInstance->Get<ChildTable>();
305*cfb92d14SAndroid Build Coastguard Worker 
306*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
307*cfb92d14SAndroid Build Coastguard Worker     printf("Checking initial state after child table is constructed");
308*cfb92d14SAndroid Build Coastguard Worker 
309*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(table->GetMaxChildrenAllowed() == table->GetMaxChildren(),
310*cfb92d14SAndroid Build Coastguard Worker                  "GetMaxChildrenAllowed() initial value is incorrect ");
311*cfb92d14SAndroid Build Coastguard Worker 
312*cfb92d14SAndroid Build Coastguard Worker     for (Child::StateFilter filter : kAllFilters)
313*cfb92d14SAndroid Build Coastguard Worker     {
314*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(table->HasChildren(filter) == false);
315*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(table->GetNumChildren(filter) == 0);
316*cfb92d14SAndroid Build Coastguard Worker     }
317*cfb92d14SAndroid Build Coastguard Worker 
318*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
319*cfb92d14SAndroid Build Coastguard Worker 
320*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
321*cfb92d14SAndroid Build Coastguard Worker 
322*cfb92d14SAndroid Build Coastguard Worker     VerifyChildTableContent(*table, 0, testChildList);
323*cfb92d14SAndroid Build Coastguard Worker 
324*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(table->GetMaxChildrenAllowed() >= testListLength,
325*cfb92d14SAndroid Build Coastguard Worker                  "Default child table size is too small for the unit test");
326*cfb92d14SAndroid Build Coastguard Worker 
327*cfb92d14SAndroid Build Coastguard Worker     // Add the child entries from test list one by one and verify the table content
328*cfb92d14SAndroid Build Coastguard Worker     for (uint16_t i = 0; i < testListLength; i++)
329*cfb92d14SAndroid Build Coastguard Worker     {
330*cfb92d14SAndroid Build Coastguard Worker         Child *child;
331*cfb92d14SAndroid Build Coastguard Worker 
332*cfb92d14SAndroid Build Coastguard Worker         child = table->GetNewChild();
333*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(child != nullptr, "GetNewChild() failed");
334*cfb92d14SAndroid Build Coastguard Worker 
335*cfb92d14SAndroid Build Coastguard Worker         child->SetState(testChildList[i].mState);
336*cfb92d14SAndroid Build Coastguard Worker         child->SetRloc16(testChildList[i].mRloc16);
337*cfb92d14SAndroid Build Coastguard Worker         child->SetExtAddress((static_cast<const Mac::ExtAddress &>(testChildList[i].mExtAddress)));
338*cfb92d14SAndroid Build Coastguard Worker 
339*cfb92d14SAndroid Build Coastguard Worker         VerifyChildTableContent(*table, i + 1, testChildList);
340*cfb92d14SAndroid Build Coastguard Worker     }
341*cfb92d14SAndroid Build Coastguard Worker 
342*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
343*cfb92d14SAndroid Build Coastguard Worker     // Verify Child Table clear
344*cfb92d14SAndroid Build Coastguard Worker 
345*cfb92d14SAndroid Build Coastguard Worker     table->Clear();
346*cfb92d14SAndroid Build Coastguard Worker 
347*cfb92d14SAndroid Build Coastguard Worker     VerifyChildTableContent(*table, 0, testChildList);
348*cfb92d14SAndroid Build Coastguard Worker 
349*cfb92d14SAndroid Build Coastguard Worker     // Add the child entries from test list in reverse order and verify the table content
350*cfb92d14SAndroid Build Coastguard Worker     for (uint16_t i = testListLength; i > 0; i--)
351*cfb92d14SAndroid Build Coastguard Worker     {
352*cfb92d14SAndroid Build Coastguard Worker         Child *child;
353*cfb92d14SAndroid Build Coastguard Worker 
354*cfb92d14SAndroid Build Coastguard Worker         child = table->GetNewChild();
355*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(child != nullptr, "GetNewChild() failed");
356*cfb92d14SAndroid Build Coastguard Worker 
357*cfb92d14SAndroid Build Coastguard Worker         child->SetState(testChildList[i - 1].mState);
358*cfb92d14SAndroid Build Coastguard Worker         child->SetRloc16(testChildList[i - 1].mRloc16);
359*cfb92d14SAndroid Build Coastguard Worker         child->SetExtAddress((static_cast<const Mac::ExtAddress &>(testChildList[i - 1].mExtAddress)));
360*cfb92d14SAndroid Build Coastguard Worker 
361*cfb92d14SAndroid Build Coastguard Worker         VerifyChildTableContent(*table, testListLength - i + 1, &testChildList[i - 1]);
362*cfb92d14SAndroid Build Coastguard Worker     }
363*cfb92d14SAndroid Build Coastguard Worker 
364*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
365*cfb92d14SAndroid Build Coastguard Worker     printf("Test Get/SetMaxChildrenAllowed");
366*cfb92d14SAndroid Build Coastguard Worker 
367*cfb92d14SAndroid Build Coastguard Worker     error = table->SetMaxChildrenAllowed(kMaxChildren - 1);
368*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(error == kErrorInvalidState, "SetMaxChildrenAllowed() should fail when table is not empty");
369*cfb92d14SAndroid Build Coastguard Worker 
370*cfb92d14SAndroid Build Coastguard Worker     table->Clear();
371*cfb92d14SAndroid Build Coastguard Worker     error = table->SetMaxChildrenAllowed(kMaxChildren + 1);
372*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(error == kErrorInvalidArgs, "SetMaxChildrenAllowed() did not fail with an invalid arg");
373*cfb92d14SAndroid Build Coastguard Worker 
374*cfb92d14SAndroid Build Coastguard Worker     error = table->SetMaxChildrenAllowed(0);
375*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(error == kErrorInvalidArgs, "SetMaxChildrenAllowed() did not fail with an invalid arg");
376*cfb92d14SAndroid Build Coastguard Worker 
377*cfb92d14SAndroid Build Coastguard Worker     error = table->SetMaxChildrenAllowed(testNumAllowedChildren);
378*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(error == kErrorNone, "SetMaxChildrenAllowed() failed");
379*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(table->GetMaxChildrenAllowed() == testNumAllowedChildren);
380*cfb92d14SAndroid Build Coastguard Worker 
381*cfb92d14SAndroid Build Coastguard Worker     for (uint16_t num = 0; num < testNumAllowedChildren; num++)
382*cfb92d14SAndroid Build Coastguard Worker     {
383*cfb92d14SAndroid Build Coastguard Worker         Child *child = table->GetNewChild();
384*cfb92d14SAndroid Build Coastguard Worker 
385*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(child != nullptr, "GetNewChild() failed");
386*cfb92d14SAndroid Build Coastguard Worker         child->SetState(Child::kStateValid);
387*cfb92d14SAndroid Build Coastguard Worker     }
388*cfb92d14SAndroid Build Coastguard Worker 
389*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(table->GetNewChild() == nullptr, "GetNewChild() did not fail when table was full");
390*cfb92d14SAndroid Build Coastguard Worker 
391*cfb92d14SAndroid Build Coastguard Worker     printf(" -- PASS\n");
392*cfb92d14SAndroid Build Coastguard Worker 
393*cfb92d14SAndroid Build Coastguard Worker     testFreeInstance(sInstance);
394*cfb92d14SAndroid Build Coastguard Worker }
395*cfb92d14SAndroid Build Coastguard Worker 
396*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
397*cfb92d14SAndroid Build Coastguard Worker 
main(void)398*cfb92d14SAndroid Build Coastguard Worker int main(void)
399*cfb92d14SAndroid Build Coastguard Worker {
400*cfb92d14SAndroid Build Coastguard Worker     ot::TestChildTable();
401*cfb92d14SAndroid Build Coastguard Worker     printf("\nAll tests passed.\n");
402*cfb92d14SAndroid Build Coastguard Worker     return 0;
403*cfb92d14SAndroid Build Coastguard Worker }
404