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