1 /*
2 * Copyright (c) 2021, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <stdarg.h>
30 #include <string.h>
31
32 #include "test_platform.h"
33
34 #include <openthread/config.h>
35
36 #include "common/array.hpp"
37 #include "common/debug.hpp"
38 #include "common/instance.hpp"
39 #include "common/type_traits.hpp"
40
41 #include "test_util.h"
42
43 namespace ot {
44
TestArray(void)45 void TestArray(void)
46 {
47 constexpr uint16_t kMaxSize = 10;
48 constexpr uint16_t kStartValue = 100;
49
50 Array<uint16_t, kMaxSize> array;
51 uint8_t index;
52 uint16_t seed;
53
54 // All methods after constructor
55 VerifyOrQuit(array.IsEmpty());
56 VerifyOrQuit(!array.IsFull());
57 VerifyOrQuit(array.GetLength() == 0);
58 VerifyOrQuit(array.GetMaxSize() == kMaxSize);
59 VerifyOrQuit(array.At(0) == nullptr);
60 VerifyOrQuit(array.Front() == nullptr);
61 VerifyOrQuit(array.Back() == nullptr);
62 VerifyOrQuit(array.PopBack() == nullptr);
63
64 seed = kStartValue;
65
66 for (uint8_t len = 1; len <= kMaxSize; len++)
67 {
68 for (uint8_t iter = 0; iter < 2; iter++)
69 {
70 // On `iter == 0` use `PushBack(aEntry)` and on `iter == 1`
71 // `PushBack()` version which returns a pointer to the newly
72 // added entry.
73
74 if (iter == 0)
75 {
76 SuccessOrQuit(array.PushBack(seed + len));
77 }
78 else
79 {
80 uint16_t *entry = array.PushBack();
81
82 VerifyOrQuit(entry != nullptr);
83 *entry = seed + len;
84 }
85
86 VerifyOrQuit(!array.IsEmpty());
87 VerifyOrQuit(array.IsFull() == (len == kMaxSize));
88 VerifyOrQuit(array.GetLength() == len);
89
90 VerifyOrQuit(array.Front() != nullptr);
91 VerifyOrQuit(*array.Front() == seed + 1);
92 VerifyOrQuit(array.Back() != nullptr);
93 VerifyOrQuit(*array.Back() == seed + len);
94
95 for (index = 0; index < len; index++)
96 {
97 VerifyOrQuit(array[index] == seed + index + 1);
98 VerifyOrQuit(array.At(index) != nullptr);
99 VerifyOrQuit(*array.At(index) == seed + index + 1);
100
101 VerifyOrQuit(array.Contains(seed + index + 1));
102 VerifyOrQuit(array.Find(seed + index + 1) == &array[index]);
103
104 VerifyOrQuit(!array.Contains(seed));
105 VerifyOrQuit(array.Find(seed) == nullptr);
106 }
107
108 index = 0;
109
110 for (uint16_t value : array)
111 {
112 VerifyOrQuit(value == array[index]);
113 index++;
114 }
115
116 index = 0;
117
118 for (uint16_t &entry : array)
119 {
120 // Uddate the value stored at the entry
121 entry++;
122
123 VerifyOrQuit(entry == array[index]);
124 VerifyOrQuit(array.IndexOf(entry) == index);
125
126 index++;
127 }
128
129 seed++;
130
131 // On `iter == 0` we verify `PopBack()` and remove the
132 // last entry. It will be added again from next `iter`
133 // loop (on `iter == 1`).
134
135 if (iter == 0)
136 {
137 uint16_t *entry = array.PopBack();
138
139 VerifyOrQuit(entry != nullptr);
140 VerifyOrQuit(*entry == seed + len);
141 VerifyOrQuit(array.GetLength() == len - 1);
142 }
143 }
144 }
145
146 VerifyOrQuit(array.IsFull());
147 VerifyOrQuit(array.PushBack(0) == kErrorNoBufs);
148 VerifyOrQuit(array.PushBack() == nullptr);
149
150 for (uint8_t len = kMaxSize; len >= 1; len--)
151 {
152 uint16_t *entry;
153
154 VerifyOrQuit(array.GetLength() == len);
155 VerifyOrQuit(array.Back() == &array[len - 1]);
156
157 entry = array.PopBack();
158 VerifyOrQuit(entry != nullptr);
159 VerifyOrQuit(*entry == seed + len);
160
161 VerifyOrQuit(array.GetLength() == len - 1);
162 VerifyOrQuit(!array.IsFull());
163 }
164
165 VerifyOrQuit(array.IsEmpty());
166
167 SuccessOrQuit(array.PushBack(seed));
168 VerifyOrQuit(!array.IsEmpty());
169
170 array.Clear();
171 VerifyOrQuit(array.IsEmpty());
172 }
173
TestArrayCopyAndFindMatching(void)174 void TestArrayCopyAndFindMatching(void)
175 {
176 constexpr uint16_t kMaxSize = 10;
177
178 struct Entry
179 {
180 Entry(void) = default;
181
182 Entry(const char *aName, uint16_t aYear)
183 : mName(aName)
184 , mYear(aYear)
185 {
186 }
187
188 bool operator==(const Entry &aOther) { return (mName == aOther.mName) && (mYear == aOther.mYear); }
189 bool Matches(const char *aName) const { return strcmp(aName, mName) == 0; }
190 bool Matches(uint16_t aYear) const { return aYear == mYear; }
191
192 const char *mName;
193 uint16_t mYear;
194 };
195
196 Entry ps1("PS", 1994);
197 Entry ps2("PS2", 2000);
198 Entry ps3("PS3", 2006);
199 Entry ps4("PS4", 2013);
200 Entry ps5("PS5", 2020);
201
202 Array<Entry, kMaxSize> array1;
203 Array<Entry, kMaxSize> array2;
204 Array<Entry, kMaxSize> array3(array1);
205
206 VerifyOrQuit(array1.IsEmpty());
207 VerifyOrQuit(array2.IsEmpty());
208 VerifyOrQuit(array3.IsEmpty());
209
210 SuccessOrQuit(array1.PushBack(ps1));
211 SuccessOrQuit(array1.PushBack(ps2));
212 SuccessOrQuit(array1.PushBack(ps3));
213 SuccessOrQuit(array1.PushBack(ps4));
214 VerifyOrQuit(array1.GetLength() == 4);
215
216 SuccessOrQuit(array2.PushBack(ps3));
217 SuccessOrQuit(array2.PushBack(ps5));
218 VerifyOrQuit(array2.GetLength() == 2);
219
220 array3 = array2 = array1;
221
222 VerifyOrQuit(array1.GetLength() == 4);
223 VerifyOrQuit(array2.GetLength() == 4);
224 VerifyOrQuit(array3.GetLength() == 4);
225
226 for (uint8_t index = 0; index < array1.GetLength(); index++)
227 {
228 VerifyOrQuit(array1[index] == array2[index]);
229 VerifyOrQuit(array1[index] == array3[index]);
230 }
231
232 array3.Clear();
233
234 array1 = array3;
235 VerifyOrQuit(array1.IsEmpty());
236 VerifyOrQuit(array1.GetLength() == 0);
237
238 {
239 Array<Entry, kMaxSize> array4(array2);
240
241 VerifyOrQuit(array4.GetLength() == 4);
242
243 for (uint8_t index = 0; index < array1.GetLength(); index++)
244 {
245 VerifyOrQuit(array2[index] == array4[index]);
246 }
247 }
248
249 SuccessOrQuit(array2.PushBack(ps5));
250 VerifyOrQuit(array2.GetLength() == 5);
251
252 for (const Entry &entry : array2)
253 {
254 Entry *match;
255
256 printf("- Name:%-3s Year:%d\n", entry.mName, entry.mYear);
257
258 match = array2.FindMatching(entry.mName);
259 VerifyOrQuit(match != nullptr);
260 VerifyOrQuit(match == &entry);
261 VerifyOrQuit(array2.ContainsMatching(entry.mName));
262
263 match = array2.FindMatching(entry.mYear);
264 VerifyOrQuit(match != nullptr);
265 VerifyOrQuit(match == &entry);
266 VerifyOrQuit(array2.ContainsMatching(entry.mYear));
267 }
268
269 VerifyOrQuit(array2.FindMatching("PS6") == nullptr);
270 VerifyOrQuit(!array2.ContainsMatching("PS6"));
271 VerifyOrQuit(array2.FindMatching(static_cast<uint16_t>(2001)) == nullptr);
272 VerifyOrQuit(!array2.ContainsMatching(static_cast<uint16_t>(2001)));
273
274 printf("\n");
275 }
276
TestArrayIndexType(void)277 void TestArrayIndexType(void)
278 {
279 typedef Array<uint16_t, 255> Array1;
280 typedef Array<uint16_t, 256> Array2;
281 typedef Array<uint16_t, 100, uint16_t> Array3;
282
283 static_assert(TypeTraits::IsSame<Array1::IndexType, uint8_t>::kValue, "Array1::IndexType is incorrect");
284 static_assert(TypeTraits::IsSame<Array2::IndexType, uint16_t>::kValue, "Array2::IndexType is incorrect");
285 static_assert(TypeTraits::IsSame<Array3::IndexType, uint16_t>::kValue, "Array3::IndexType is incorrect");
286 }
287
288 } // namespace ot
289
main(void)290 int main(void)
291 {
292 ot::TestArray();
293 ot::TestArrayCopyAndFindMatching();
294 ot::TestArrayIndexType();
295
296 printf("All tests passed\n");
297 return 0;
298 }
299