1 /*
2 * Copyright (c) 2016, 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 "common/appender.hpp"
30 #include "common/debug.hpp"
31 #include "common/message.hpp"
32 #include "common/random.hpp"
33 #include "instance/instance.hpp"
34
35 #include "test_platform.h"
36 #include "test_util.hpp"
37
38 namespace ot {
39
TestMessage(void)40 void TestMessage(void)
41 {
42 enum : uint16_t
43 {
44 kMaxSize = (kBufferSize * 3 + 24),
45 kOffsetStep = 101,
46 kLengthStep = 21,
47 };
48
49 Instance *instance;
50 MessagePool *messagePool;
51 Message *message;
52 Message *message2;
53 Message *messageCopy;
54 uint8_t writeBuffer[kMaxSize];
55 uint8_t readBuffer[kMaxSize];
56 uint8_t zeroBuffer[kMaxSize];
57
58 printf("TestMessage\n");
59
60 memset(zeroBuffer, 0, sizeof(zeroBuffer));
61
62 instance = static_cast<Instance *>(testInitInstance());
63 VerifyOrQuit(instance != nullptr);
64
65 messagePool = &instance->Get<MessagePool>();
66
67 Random::NonCrypto::FillBuffer(writeBuffer, kMaxSize);
68
69 VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
70 message->SetLinkSecurityEnabled(Message::kWithLinkSecurity);
71 SuccessOrQuit(message->SetPriority(Message::Priority::kPriorityNet));
72 message->SetType(Message::Type::kType6lowpan);
73 message->SetSubType(Message::SubType::kSubTypeMleChildIdRequest);
74 message->SetLoopbackToHostAllowed(true);
75 message->SetOrigin(Message::kOriginHostUntrusted);
76 SuccessOrQuit(message->SetLength(kMaxSize));
77 message->WriteBytes(0, writeBuffer, kMaxSize);
78 SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
79 VerifyOrQuit(memcmp(writeBuffer, readBuffer, kMaxSize) == 0);
80 VerifyOrQuit(message->CompareBytes(0, readBuffer, kMaxSize));
81 VerifyOrQuit(message->Compare(0, readBuffer));
82 VerifyOrQuit(message->GetLength() == kMaxSize);
83
84 // Verify `Clone()` behavior
85 message->SetOffset(15);
86 messageCopy = message->Clone();
87 VerifyOrQuit(messageCopy->GetOffset() == message->GetOffset());
88 SuccessOrQuit(messageCopy->Read(0, readBuffer, kMaxSize));
89 VerifyOrQuit(memcmp(writeBuffer, readBuffer, kMaxSize) == 0);
90 VerifyOrQuit(messageCopy->CompareBytes(0, readBuffer, kMaxSize));
91 VerifyOrQuit(messageCopy->Compare(0, readBuffer));
92 VerifyOrQuit(messageCopy->GetLength() == kMaxSize);
93 VerifyOrQuit(messageCopy->GetType() == message->GetType());
94 VerifyOrQuit(messageCopy->GetSubType() == message->GetSubType());
95 VerifyOrQuit(messageCopy->IsLinkSecurityEnabled() == message->IsLinkSecurityEnabled());
96 VerifyOrQuit(messageCopy->GetPriority() == message->GetPriority());
97 VerifyOrQuit(messageCopy->IsLoopbackToHostAllowed() == message->IsLoopbackToHostAllowed());
98 VerifyOrQuit(messageCopy->GetOrigin() == message->GetOrigin());
99 VerifyOrQuit(messageCopy->Compare(0, readBuffer));
100 message->SetOffset(0);
101
102 messageCopy->Free();
103
104 for (uint16_t offset = 0; offset < kMaxSize; offset++)
105 {
106 for (uint16_t length = 0; length <= kMaxSize - offset; length++)
107 {
108 for (uint16_t i = 0; i < length; i++)
109 {
110 writeBuffer[offset + i]++;
111 }
112
113 message->WriteBytes(offset, &writeBuffer[offset], length);
114
115 SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
116 VerifyOrQuit(memcmp(writeBuffer, readBuffer, kMaxSize) == 0);
117 VerifyOrQuit(message->Compare(0, writeBuffer));
118
119 memset(readBuffer, 0, sizeof(readBuffer));
120 SuccessOrQuit(message->Read(offset, readBuffer, length));
121 VerifyOrQuit(memcmp(readBuffer, &writeBuffer[offset], length) == 0);
122 VerifyOrQuit(memcmp(&readBuffer[length], zeroBuffer, kMaxSize - length) == 0, "read after length");
123
124 VerifyOrQuit(message->CompareBytes(offset, &writeBuffer[offset], length));
125
126 if (length == 0)
127 {
128 continue;
129 }
130
131 // Change the first byte, and then last byte, and verify that
132 // `CompareBytes()` correctly fails.
133
134 writeBuffer[offset]++;
135 VerifyOrQuit(!message->CompareBytes(offset, &writeBuffer[offset], length));
136 writeBuffer[offset]--;
137
138 writeBuffer[offset + length - 1]++;
139 VerifyOrQuit(!message->CompareBytes(offset, &writeBuffer[offset], length));
140 writeBuffer[offset + length - 1]--;
141 }
142
143 // Verify `ReadBytes()` behavior when requested read length goes beyond available bytes in the message.
144
145 for (uint16_t length = kMaxSize - offset + 1; length <= kMaxSize + 1; length++)
146 {
147 uint16_t readLength;
148
149 memset(readBuffer, 0, sizeof(readBuffer));
150 readLength = message->ReadBytes(offset, readBuffer, length);
151
152 VerifyOrQuit(readLength < length, "Message::ReadBytes() returned longer length");
153 VerifyOrQuit(readLength == kMaxSize - offset);
154 VerifyOrQuit(memcmp(readBuffer, &writeBuffer[offset], readLength) == 0);
155 VerifyOrQuit(memcmp(&readBuffer[readLength], zeroBuffer, kMaxSize - readLength) == 0, "read after length");
156
157 VerifyOrQuit(!message->CompareBytes(offset, readBuffer, length));
158 VerifyOrQuit(message->CompareBytes(offset, readBuffer, readLength));
159 }
160 }
161
162 VerifyOrQuit(message->GetLength() == kMaxSize);
163
164 // Test `WriteBytesFromMessage()` behavior copying between different
165 // messages.
166
167 VerifyOrQuit((message2 = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
168 SuccessOrQuit(message2->SetLength(kMaxSize));
169
170 for (uint16_t readOffset = 0; readOffset < kMaxSize; readOffset += kOffsetStep)
171 {
172 for (uint16_t writeOffset = 0; writeOffset < kMaxSize; writeOffset += kOffsetStep)
173 {
174 for (uint16_t length = 0; length <= kMaxSize - Max(writeOffset, readOffset); length += kLengthStep)
175 {
176 message2->WriteBytes(0, zeroBuffer, kMaxSize);
177
178 message2->WriteBytesFromMessage(writeOffset, *message, readOffset, length);
179
180 SuccessOrQuit(message2->Read(0, readBuffer, kMaxSize));
181
182 VerifyOrQuit(memcmp(&readBuffer[0], zeroBuffer, writeOffset) == 0);
183 VerifyOrQuit(memcmp(&readBuffer[writeOffset], &writeBuffer[readOffset], length) == 0);
184 VerifyOrQuit(memcmp(&readBuffer[writeOffset + length], zeroBuffer, kMaxSize - length - writeOffset) ==
185 0);
186
187 VerifyOrQuit(message->CompareBytes(readOffset, *message2, writeOffset, length));
188 VerifyOrQuit(message2->CompareBytes(writeOffset, *message, readOffset, length));
189 }
190 }
191 }
192
193 // Verify `WriteBytesFromMessage()` behavior copying backwards within
194 // same message.
195
196 for (uint16_t readOffset = 0; readOffset < kMaxSize; readOffset++)
197 {
198 uint16_t length = kMaxSize - readOffset;
199
200 message->WriteBytes(0, writeBuffer, kMaxSize);
201
202 message->WriteBytesFromMessage(0, *message, readOffset, length);
203
204 SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
205
206 VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[readOffset], length) == 0);
207 VerifyOrQuit(memcmp(&readBuffer[length], &writeBuffer[length], kMaxSize - length) == 0);
208 }
209
210 // Verify `WriteBytesFromMessage()` behavior copying forward within
211 // same message.
212
213 for (uint16_t writeOffset = 0; writeOffset < kMaxSize; writeOffset++)
214 {
215 uint16_t length = kMaxSize - writeOffset;
216
217 message->WriteBytes(0, writeBuffer, kMaxSize);
218
219 message->WriteBytesFromMessage(writeOffset, *message, 0, length);
220
221 SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
222
223 VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[0], writeOffset) == 0);
224 VerifyOrQuit(memcmp(&readBuffer[writeOffset], &writeBuffer[0], length) == 0);
225 }
226
227 // Test `WriteBytesFromMessage()` behavior copying within same
228 // message at different read and write offsets and lengths.
229
230 for (uint16_t readOffset = 0; readOffset < kMaxSize; readOffset += kOffsetStep)
231 {
232 for (uint16_t writeOffset = 0; writeOffset < kMaxSize; writeOffset += kOffsetStep)
233 {
234 for (uint16_t length = 0; length <= kMaxSize - Max(writeOffset, readOffset); length += kLengthStep)
235 {
236 message->WriteBytes(0, writeBuffer, kMaxSize);
237
238 message->WriteBytesFromMessage(writeOffset, *message, readOffset, length);
239
240 SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
241
242 VerifyOrQuit(memcmp(&readBuffer[0], writeBuffer, writeOffset) == 0);
243 VerifyOrQuit(memcmp(&readBuffer[writeOffset], &writeBuffer[readOffset], length) == 0);
244 VerifyOrQuit(memcmp(&readBuffer[writeOffset + length], &writeBuffer[writeOffset + length],
245 kMaxSize - length - writeOffset) == 0);
246 }
247 }
248 }
249
250 // Verify `AppendBytesFromMessage()` with two different messages as source and destination.
251
252 message->WriteBytes(0, writeBuffer, kMaxSize);
253
254 for (uint16_t srcOffset = 0; srcOffset < kMaxSize; srcOffset += kOffsetStep)
255 {
256 for (uint16_t dstOffset = 0; dstOffset < kMaxSize; dstOffset += kOffsetStep)
257 {
258 for (uint16_t length = 0; length <= kMaxSize - srcOffset; length += kLengthStep)
259 {
260 IgnoreError(message2->SetLength(0));
261 SuccessOrQuit(message2->AppendBytes(zeroBuffer, dstOffset));
262
263 SuccessOrQuit(message2->AppendBytesFromMessage(*message, srcOffset, length));
264
265 VerifyOrQuit(message2->CompareBytes(dstOffset, *message, srcOffset, length));
266 }
267
268 VerifyOrQuit(message2->AppendBytesFromMessage(*message, srcOffset, kMaxSize - srcOffset + 1) ==
269 kErrorParse);
270 }
271 }
272
273 // Verify `AppendBytesFromMessage()` with the same message as source and destination.
274
275 for (uint16_t srcOffset = 0; srcOffset < kMaxSize; srcOffset += kOffsetStep)
276 {
277 uint16_t size = kMaxSize;
278
279 for (uint16_t length = 0; length <= kMaxSize - srcOffset; length++)
280 {
281 // Reset the `message` to its original size.
282 IgnoreError(message->SetLength(size));
283
284 SuccessOrQuit(message->AppendBytesFromMessage(*message, srcOffset, length));
285
286 VerifyOrQuit(message->CompareBytes(size, *message, srcOffset, length));
287 }
288 }
289
290 message->Free();
291 message2->Free();
292
293 // Verify `RemoveHeader()`
294
295 for (uint16_t offset = 0; offset < kMaxSize; offset += kOffsetStep)
296 {
297 for (uint16_t length = 0; length <= kMaxSize - offset; length += kLengthStep)
298 {
299 VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
300 SuccessOrQuit(message->AppendBytes(writeBuffer, kMaxSize));
301
302 message->RemoveHeader(offset, length);
303
304 VerifyOrQuit(message->GetLength() == kMaxSize - length);
305
306 SuccessOrQuit(message->Read(0, readBuffer, kMaxSize - length));
307
308 VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[0], offset) == 0);
309 VerifyOrQuit(memcmp(&readBuffer[offset], &writeBuffer[offset + length], kMaxSize - length - offset) == 0);
310 message->Free();
311 }
312 }
313
314 // Verify `InsertHeader()`
315
316 for (uint16_t offset = 0; offset < kMaxSize; offset += kOffsetStep)
317 {
318 for (uint16_t length = 0; length <= kMaxSize; length += kLengthStep)
319 {
320 VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
321 SuccessOrQuit(message->AppendBytes(writeBuffer, kMaxSize));
322
323 SuccessOrQuit(message->InsertHeader(offset, length));
324
325 VerifyOrQuit(message->GetLength() == kMaxSize + length);
326
327 SuccessOrQuit(message->Read(0, readBuffer, offset));
328 VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[0], offset) == 0);
329
330 SuccessOrQuit(message->Read(offset + length, readBuffer, kMaxSize - offset));
331 VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[offset], kMaxSize - offset) == 0);
332 message->Free();
333 }
334 }
335
336 testFreeInstance(instance);
337 }
338
TestAppender(void)339 void TestAppender(void)
340 {
341 const uint8_t kData1[] = {0x01, 0x02, 0x03, 0x04};
342 const uint8_t kData2[] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
343
344 static constexpr uint16_t kMaxBufferSize = sizeof(kData1) * 2 + sizeof(kData2);
345
346 Instance *instance;
347 Message *message;
348 uint8_t buffer[kMaxBufferSize];
349 uint8_t zeroBuffer[kMaxBufferSize];
350 Appender bufAppender(buffer, sizeof(buffer));
351 Data<kWithUint16Length> data;
352
353 printf("TestAppender\n");
354
355 instance = static_cast<Instance *>(testInitInstance());
356 VerifyOrQuit(instance != nullptr);
357
358 message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
359 VerifyOrQuit(message != nullptr);
360
361 memset(buffer, 0, sizeof(buffer));
362 memset(zeroBuffer, 0, sizeof(zeroBuffer));
363
364 // Test Buffer Appender
365 VerifyOrQuit(bufAppender.GetType() == Appender::kBuffer);
366 VerifyOrQuit(bufAppender.GetBufferStart() == buffer);
367 VerifyOrQuit(bufAppender.GetAppendedLength() == 0);
368
369 SuccessOrQuit(bufAppender.AppendBytes(kData1, sizeof(kData1)));
370 DumpBuffer("Data1", buffer, sizeof(buffer));
371 VerifyOrQuit(bufAppender.GetAppendedLength() == sizeof(kData1));
372 VerifyOrQuit(bufAppender.GetBufferStart() == buffer);
373 VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
374 VerifyOrQuit(memcmp(buffer + sizeof(kData1), zeroBuffer, sizeof(buffer) - sizeof(kData1)) == 0);
375
376 SuccessOrQuit(bufAppender.AppendBytes(kData2, sizeof(kData2)));
377 DumpBuffer("Data1+Data2", buffer, sizeof(buffer));
378 VerifyOrQuit(bufAppender.GetAppendedLength() == sizeof(kData1) + sizeof(kData2));
379 VerifyOrQuit(bufAppender.GetBufferStart() == buffer);
380 VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
381 VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData2, sizeof(kData2)) == 0);
382 VerifyOrQuit(memcmp(buffer + sizeof(kData1) + sizeof(kData2), zeroBuffer,
383 sizeof(buffer) - sizeof(kData1) - sizeof(kData2)) == 0);
384
385 VerifyOrQuit(bufAppender.Append(kData2) == kErrorNoBufs);
386
387 SuccessOrQuit(bufAppender.AppendBytes(kData1, sizeof(kData1)));
388 DumpBuffer("Data1+Data2+Data1", buffer, sizeof(buffer));
389 VerifyOrQuit(bufAppender.GetAppendedLength() == sizeof(kData1) + sizeof(kData2) + sizeof(kData1));
390 VerifyOrQuit(bufAppender.GetBufferStart() == buffer);
391 VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
392 VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData2, sizeof(kData2)) == 0);
393 VerifyOrQuit(memcmp(buffer + sizeof(kData1) + sizeof(kData2), kData1, sizeof(kData1)) == 0);
394
395 VerifyOrQuit(bufAppender.Append<uint8_t>(0) == kErrorNoBufs);
396
397 bufAppender.GetAsData(data);
398 VerifyOrQuit(data.GetBytes() == buffer);
399 VerifyOrQuit(data.GetLength() == sizeof(buffer));
400
401 // Test Message Appender
402
403 SuccessOrQuit(message->Append(kData2));
404 VerifyOrQuit(message->Compare(0, kData2));
405
406 {
407 Appender msgAppender(*message);
408 uint16_t offset = message->GetLength();
409
410 VerifyOrQuit(msgAppender.GetType() == Appender::kMessage);
411
412 SuccessOrQuit(msgAppender.AppendBytes(kData1, sizeof(kData1)));
413 VerifyOrQuit(msgAppender.GetAppendedLength() == sizeof(kData1));
414
415 VerifyOrQuit(message->GetLength() == sizeof(kData2) + sizeof(kData1));
416 VerifyOrQuit(message->Compare(offset, kData1));
417
418 SuccessOrQuit(msgAppender.AppendBytes(kData2, sizeof(kData2)));
419 VerifyOrQuit(msgAppender.GetAppendedLength() == sizeof(kData1) + sizeof(kData2));
420 VerifyOrQuit(message->Compare(offset, kData1));
421 VerifyOrQuit(message->Compare(offset + sizeof(kData1), kData2));
422 }
423
424 message->Free();
425 testFreeInstance(instance);
426 }
427
428 } // namespace ot
429
main(void)430 int main(void)
431 {
432 ot::TestMessage();
433 ot::TestAppender();
434 printf("All tests passed\n");
435 return 0;
436 }
437