1 /*
2 * Copyright (c) 2018, 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 <ctype.h>
30
31 #include "common/code_utils.hpp"
32 #include "common/instance.hpp"
33 #include "lib/hdlc/hdlc.hpp"
34
35 #include "test_util.h"
36
37 namespace ot {
38 namespace Ncp {
39
40 enum
41 {
42 kBufferSize = 1500, // Frame buffer size
43 kMaxFrameLength = 500, // Maximum allowed frame length (used when randomly generating frames)
44 kFuzzTestIteration = 50000, // Number of iteration during fuzz test (randomly generating frames)
45 kFrameHeaderSize = 4, // Frame header size
46
47 kFlagXOn = 0x11,
48 kFlagXOff = 0x13,
49 kFlagSequence = 0x7e, ///< HDLC Flag value
50 kEscapeSequence = 0x7d, ///< HDLC Escape value
51 kFlagSpecial = 0xf8,
52
53 };
54
55 static const uint8_t sOpenThreadText[] = "OpenThread Rocks";
56 static const uint8_t sHelloText[] = "Hello there!";
57 static const uint8_t sMottoText[] = "Think good thoughts, say good words, do good deeds!";
58 static const uint8_t sHexText[] = "0123456789abcdef";
59 static const uint8_t sSkipText[] = "Skip text";
60 static const uint8_t sHdlcSpecials[] = {kFlagSequence, kFlagXOn, kFlagXOff,
61 kFlagSequence, kEscapeSequence, kFlagSpecial};
62
WriteToBuffer(const uint8_t * aText,Hdlc::FrameWritePointer & aWritePointer)63 otError WriteToBuffer(const uint8_t *aText, Hdlc::FrameWritePointer &aWritePointer)
64 {
65 otError error = OT_ERROR_NONE;
66
67 while (*aText != 0)
68 {
69 SuccessOrExit(aWritePointer.WriteByte(*aText++));
70 }
71
72 exit:
73 return error;
74 }
75
TestHdlcFrameBuffer(void)76 void TestHdlcFrameBuffer(void)
77 {
78 Hdlc::FrameBuffer<kBufferSize> frameBuffer;
79
80 printf("Testing Hdlc::FrameBuffer");
81
82 VerifyOrQuit(frameBuffer.IsEmpty(), "after constructor");
83 VerifyOrQuit(frameBuffer.GetLength() == 0, "after constructor");
84
85 SuccessOrQuit(WriteToBuffer(sOpenThreadText, frameBuffer));
86
87 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sOpenThreadText) - 1);
88 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sOpenThreadText, frameBuffer.GetLength()) == 0);
89
90 VerifyOrQuit(frameBuffer.CanWrite(1));
91 VerifyOrQuit(!frameBuffer.IsEmpty());
92
93 SuccessOrQuit(WriteToBuffer(sHelloText, frameBuffer));
94 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sOpenThreadText) + sizeof(sHelloText) - 2);
95
96 frameBuffer.UndoLastWrites(sizeof(sHelloText) - 1);
97 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sOpenThreadText) - 1);
98 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sOpenThreadText, frameBuffer.GetLength()) == 0);
99
100 VerifyOrQuit(!frameBuffer.IsEmpty());
101 frameBuffer.Clear();
102 VerifyOrQuit(frameBuffer.IsEmpty(), "after Clear()");
103 VerifyOrQuit(frameBuffer.GetLength() == 0, "after Clear()");
104
105 SuccessOrQuit(WriteToBuffer(sMottoText, frameBuffer));
106
107 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sMottoText) - 1);
108 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sMottoText, frameBuffer.GetLength()) == 0);
109
110 frameBuffer.Clear();
111 VerifyOrQuit(frameBuffer.CanWrite(kBufferSize));
112 VerifyOrQuit(frameBuffer.CanWrite(kBufferSize + 1) == false, "CanWrite(kBufferSize + 1) did not fail as expected");
113
114 for (uint16_t i = 0; i < kBufferSize; i++)
115 {
116 VerifyOrQuit(frameBuffer.CanWrite(1));
117 SuccessOrQuit(frameBuffer.WriteByte(i & 0xff));
118 }
119
120 VerifyOrQuit(frameBuffer.CanWrite(1) == false, "did not fail with full buffer");
121 VerifyOrQuit(frameBuffer.WriteByte(0) == OT_ERROR_NO_BUFS, "did not fail with full buffer");
122
123 printf(" -- PASS\n");
124 }
125
TestHdlcMultiFrameBuffer(void)126 void TestHdlcMultiFrameBuffer(void)
127 {
128 Hdlc::MultiFrameBuffer<kBufferSize> frameBuffer;
129 uint8_t * frame = nullptr;
130 uint8_t * newFrame = nullptr;
131 uint16_t length;
132 uint16_t newLength;
133
134 printf("Testing Hdlc::MultiFrameBuffer");
135
136 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
137 // Check state after constructor
138
139 VerifyOrQuit(!frameBuffer.HasFrame(), "after constructor");
140 VerifyOrQuit(!frameBuffer.HasSavedFrame(), "after constructor");
141 VerifyOrQuit(frameBuffer.GetLength() == 0, "after constructor");
142 VerifyOrQuit(frameBuffer.GetNextSavedFrame(frame, length) == OT_ERROR_NOT_FOUND, "after constructor");
143
144 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
145 // Write multiple frames, save them and read later
146
147 SuccessOrQuit(WriteToBuffer(sMottoText, frameBuffer));
148
149 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sMottoText) - 1);
150 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sMottoText, frameBuffer.GetLength()) == 0);
151
152 frameBuffer.SaveFrame();
153
154 VerifyOrQuit(!frameBuffer.HasFrame(), "after SaveFrame()");
155 VerifyOrQuit(frameBuffer.HasSavedFrame(), "after SaveFrame()");
156 VerifyOrQuit(frameBuffer.GetLength() == 0, "after SaveFrame()");
157
158 SuccessOrQuit(WriteToBuffer(sHelloText, frameBuffer));
159 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sHelloText) - 1);
160 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sHelloText, frameBuffer.GetLength()) == 0);
161
162 frameBuffer.SaveFrame();
163
164 VerifyOrQuit(!frameBuffer.HasFrame(), "after SaveFrame()");
165 VerifyOrQuit(frameBuffer.HasSavedFrame(), "after SaveFrame()");
166 VerifyOrQuit(frameBuffer.GetLength() == 0, "after SaveFrame()");
167
168 SuccessOrQuit(WriteToBuffer(sOpenThreadText, frameBuffer));
169 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sOpenThreadText) - 1);
170 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sOpenThreadText, frameBuffer.GetLength()) == 0);
171
172 frameBuffer.DiscardFrame();
173
174 VerifyOrQuit(!frameBuffer.HasFrame(), "after DiscardFrame()");
175 VerifyOrQuit(frameBuffer.HasSavedFrame(), "after SaveFrame()");
176 VerifyOrQuit(frameBuffer.GetLength() == 0, "after DiscardFrame()");
177
178 SuccessOrQuit(WriteToBuffer(sMottoText, frameBuffer));
179 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sMottoText) - 1);
180 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sMottoText, frameBuffer.GetLength()) == 0);
181
182 frameBuffer.DiscardFrame();
183
184 VerifyOrQuit(!frameBuffer.HasFrame(), "after DiscardFrame()");
185 VerifyOrQuit(frameBuffer.GetLength() == 0, "after DiscardFrame()");
186
187 SuccessOrQuit(WriteToBuffer(sHexText, frameBuffer));
188 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sHexText) - 1);
189 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sHexText, frameBuffer.GetLength()) == 0);
190
191 frameBuffer.SaveFrame();
192
193 VerifyOrQuit(!frameBuffer.HasFrame(), "after SaveFrame()");
194 VerifyOrQuit(frameBuffer.HasSavedFrame(), "after SaveFrame()");
195 VerifyOrQuit(frameBuffer.GetLength() == 0, "after SaveFrame()");
196
197 SuccessOrQuit(WriteToBuffer(sOpenThreadText, frameBuffer));
198 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sOpenThreadText) - 1);
199 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sOpenThreadText, frameBuffer.GetLength()) == 0);
200
201 // Read the first saved frame and check the content
202 frame = nullptr;
203 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
204 VerifyOrQuit(length == sizeof(sMottoText) - 1, "GetNextSavedFrame() length is incorrect");
205 VerifyOrQuit(memcmp(frame, sMottoText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
206
207 // Read the second saved frame and check the content
208 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
209 VerifyOrQuit(length == sizeof(sHelloText) - 1, "GetNextSavedFrame() length is incorrect");
210 VerifyOrQuit(memcmp(frame, sHelloText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
211
212 // Read the third saved frame and check the content
213 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
214 VerifyOrQuit(length == sizeof(sHexText) - 1, "GetNextSavedFrame() length is incorrect");
215 VerifyOrQuit(memcmp(frame, sHexText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
216
217 newFrame = frame;
218 newLength = length;
219 VerifyOrQuit(frameBuffer.GetNextSavedFrame(newFrame, newLength) == OT_ERROR_NOT_FOUND,
220 "GetNextSavedFrame() incorrect behavior after all frames were read");
221 VerifyOrQuit(newFrame == nullptr, "GetNextSavedFrame() incorrect behavior after all frames were read");
222
223 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sOpenThreadText) - 1);
224 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sOpenThreadText, frameBuffer.GetLength()) == 0,
225 "GetFrame() content is incorrect");
226
227 frameBuffer.SaveFrame();
228
229 // Read the fourth saved frame and check the content
230 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
231 VerifyOrQuit(length == sizeof(sOpenThreadText) - 1, "GetNextSavedFrame() length is incorrect");
232 VerifyOrQuit(memcmp(frame, sOpenThreadText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
233
234 // Re-read all the saved frames
235 frame = nullptr;
236 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
237 VerifyOrQuit(length == sizeof(sMottoText) - 1, "GetNextSavedFrame() length is incorrect");
238 VerifyOrQuit(memcmp(frame, sMottoText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
239
240 // Second saved frame
241 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
242 VerifyOrQuit(length == sizeof(sHelloText) - 1, "GetNextSavedFrame() length is incorrect");
243 VerifyOrQuit(memcmp(frame, sHelloText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
244
245 // Third saved frame
246 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
247 VerifyOrQuit(length == sizeof(sHexText) - 1, "GetNextSavedFrame() length is incorrect");
248 VerifyOrQuit(memcmp(frame, sHexText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
249
250 // Fourth saved frame and check the content
251 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
252 VerifyOrQuit(length == sizeof(sOpenThreadText) - 1, "GetNextSavedFrame() length is incorrect");
253 VerifyOrQuit(memcmp(frame, sOpenThreadText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
254
255 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
256 // Verify behavior of `Clear()`
257
258 frameBuffer.Clear();
259
260 VerifyOrQuit(!frameBuffer.HasFrame(), "after Clear()");
261 VerifyOrQuit(!frameBuffer.HasSavedFrame(), "after Clear()");
262 VerifyOrQuit(frameBuffer.GetLength() == 0, "after Clear()");
263
264 SuccessOrQuit(WriteToBuffer(sOpenThreadText, frameBuffer));
265 frameBuffer.SaveFrame();
266
267 SuccessOrQuit(WriteToBuffer(sHelloText, frameBuffer));
268 frameBuffer.SaveFrame();
269 VerifyOrQuit(frameBuffer.HasSavedFrame(), "after SaveFrame()");
270
271 frame = nullptr;
272 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
273 VerifyOrQuit(frameBuffer.HasSavedFrame(), "after GetNextSavedFrame()");
274
275 frameBuffer.Clear();
276
277 frame = nullptr;
278 VerifyOrQuit(frameBuffer.GetNextSavedFrame(frame, length) == OT_ERROR_NOT_FOUND, "after Clear()");
279
280 VerifyOrQuit(!frameBuffer.HasFrame(), "after Clear()");
281 VerifyOrQuit(!frameBuffer.HasSavedFrame(), "after Clear()");
282 VerifyOrQuit(frameBuffer.CanWrite(kBufferSize - (kFrameHeaderSize - 1)) == false, "after Clear()");
283 VerifyOrQuit(frameBuffer.CanWrite(kBufferSize - kFrameHeaderSize) == true, "after Clear()");
284
285 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
286 // Verify behavior of `ClearSavedFrames()`
287
288 SuccessOrQuit(WriteToBuffer(sHelloText, frameBuffer));
289 frameBuffer.SaveFrame();
290 SuccessOrQuit(WriteToBuffer(sOpenThreadText, frameBuffer));
291 frameBuffer.SaveFrame();
292 SuccessOrQuit(WriteToBuffer(sMottoText, frameBuffer));
293 frameBuffer.SaveFrame();
294 SuccessOrQuit(WriteToBuffer(sHexText, frameBuffer));
295
296 frame = nullptr;
297 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
298 VerifyOrQuit(length == sizeof(sHelloText) - 1, "GetNextSavedFrame() length is incorrect");
299 VerifyOrQuit(memcmp(frame, sHelloText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
300
301 frameBuffer.ClearSavedFrames();
302
303 VerifyOrQuit(frameBuffer.HasFrame(), "after ClearSavedFrames()");
304 VerifyOrQuit(!frameBuffer.HasSavedFrame(), "after ClearSavedFrames()");
305
306 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sHexText) - 1, "after ClearSavedFrames()");
307 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sHexText, frameBuffer.GetLength()) == 0);
308
309 frameBuffer.SaveFrame();
310
311 SuccessOrQuit(WriteToBuffer(sHelloText, frameBuffer));
312
313 frame = nullptr;
314 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
315 VerifyOrQuit(length == sizeof(sHexText) - 1, "GetNextSavedFrame() length is incorrect");
316 VerifyOrQuit(memcmp(frame, sHexText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
317
318 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sHelloText) - 1, "after ClearSavedFrames()");
319 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sHelloText, frameBuffer.GetLength()) == 0, "after ClearSavedFrames()");
320
321 frameBuffer.ClearSavedFrames();
322 frameBuffer.DiscardFrame();
323
324 VerifyOrQuit(!frameBuffer.HasFrame(), "after all frames are read and discarded");
325 VerifyOrQuit(!frameBuffer.HasSavedFrame(), "after all read or discarded");
326 VerifyOrQuit(frameBuffer.CanWrite(kBufferSize - (kFrameHeaderSize - 1)) == false, "after all read or discarded");
327 VerifyOrQuit(frameBuffer.CanWrite(kBufferSize - kFrameHeaderSize) == true, "after all read of discarded");
328
329 SuccessOrQuit(WriteToBuffer(sHelloText, frameBuffer));
330
331 frameBuffer.ClearSavedFrames();
332
333 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sHelloText) - 1);
334 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sHelloText, frameBuffer.GetLength()) == 0);
335
336 frameBuffer.SaveFrame();
337 frame = nullptr;
338 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
339 VerifyOrQuit(length == sizeof(sHelloText) - 1, "GetNextSavedFrame() length is incorrect");
340 VerifyOrQuit(memcmp(frame, sHelloText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
341
342 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
343 // Verify behavior of `SetSkipLength()` and `GetSkipLength()`
344
345 frameBuffer.Clear();
346
347 VerifyOrQuit(frameBuffer.GetSkipLength() == 0, "after Clear()");
348 VerifyOrQuit(frameBuffer.SetSkipLength(sizeof(sSkipText)) == OT_ERROR_NONE);
349 SuccessOrQuit(WriteToBuffer(sMottoText, frameBuffer));
350 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sMottoText, frameBuffer.GetLength()) == 0);
351 memcpy(frameBuffer.GetFrame() - sizeof(sSkipText), sSkipText, sizeof(sSkipText));
352 VerifyOrQuit(frameBuffer.GetSkipLength() == sizeof(sSkipText));
353 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sMottoText) - 1);
354 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sMottoText, frameBuffer.GetLength()) == 0);
355
356 frameBuffer.SaveFrame();
357 VerifyOrQuit(!frameBuffer.HasFrame(), "after SaveFrame()");
358 VerifyOrQuit(frameBuffer.HasSavedFrame(), "after SaveFrame()");
359 VerifyOrQuit(frameBuffer.GetSkipLength() == 0, "after SaveFrame()");
360
361 VerifyOrQuit(frameBuffer.SetSkipLength(sizeof(sSkipText)) == OT_ERROR_NONE);
362 SuccessOrQuit(WriteToBuffer(sOpenThreadText, frameBuffer));
363 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sOpenThreadText, frameBuffer.GetLength()) == 0);
364 memcpy(frameBuffer.GetFrame() - sizeof(sSkipText), sSkipText, sizeof(sSkipText));
365 VerifyOrQuit(frameBuffer.GetSkipLength() == sizeof(sSkipText));
366 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sOpenThreadText) - 1);
367 VerifyOrQuit(memcmp(frameBuffer.GetFrame(), sOpenThreadText, frameBuffer.GetLength()) == 0);
368
369 frameBuffer.SaveFrame();
370 VerifyOrQuit(!frameBuffer.HasFrame(), "after SaveFrame()");
371 VerifyOrQuit(frameBuffer.HasSavedFrame(), "after SaveFrame()");
372 VerifyOrQuit(frameBuffer.GetSkipLength() == 0, "after SaveFrame()");
373
374 frame = nullptr;
375 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
376 VerifyOrQuit(length == sizeof(sMottoText) - 1, "GetNextSavedFrame() length is incorrect");
377 VerifyOrQuit(memcmp(frame, sMottoText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
378 VerifyOrQuit(memcmp(frame - sizeof(sSkipText), sSkipText, sizeof(sSkipText)) == 0,
379 "GetNextSavedFrame() reserved frame buffer content is incorrect");
380
381 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
382 VerifyOrQuit(length == sizeof(sOpenThreadText) - 1, "GetNextSavedFrame() length is incorrect");
383 VerifyOrQuit(memcmp(frame, sOpenThreadText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
384 VerifyOrQuit(memcmp(frame - sizeof(sSkipText), sSkipText, sizeof(sSkipText)) == 0,
385 "GetNextSavedFrame() reserved frame buffer content is incorrect");
386
387 frameBuffer.Clear();
388 VerifyOrQuit(frameBuffer.SetSkipLength(kBufferSize - (kFrameHeaderSize - 1)) == OT_ERROR_NO_BUFS, "after Clear()");
389 VerifyOrQuit(frameBuffer.SetSkipLength(kBufferSize - kFrameHeaderSize) == OT_ERROR_NONE, "after Clear()");
390
391 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
392 // Verify behavior of `SetLength()` and `GetLength()`
393
394 frameBuffer.Clear();
395 VerifyOrQuit((frame = frameBuffer.GetFrame()) != nullptr);
396 memcpy(frame, sHelloText, sizeof(sHelloText));
397 VerifyOrQuit(frameBuffer.SetLength(sizeof(sHelloText)) == OT_ERROR_NONE);
398 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sHelloText));
399 VerifyOrQuit(frameBuffer.HasFrame());
400 frameBuffer.SaveFrame();
401
402 VerifyOrQuit((frame = frameBuffer.GetFrame()) != nullptr);
403 memcpy(frame, sMottoText, sizeof(sMottoText));
404 VerifyOrQuit(frameBuffer.SetLength(sizeof(sMottoText)) == OT_ERROR_NONE);
405 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sMottoText));
406 VerifyOrQuit(frameBuffer.HasFrame());
407 frameBuffer.SaveFrame();
408
409 VerifyOrQuit((frame = frameBuffer.GetFrame()) != nullptr);
410 memcpy(frame, sHexText, sizeof(sHexText));
411 VerifyOrQuit(frameBuffer.SetLength(sizeof(sHexText)) == OT_ERROR_NONE);
412 VerifyOrQuit(frameBuffer.GetLength() == sizeof(sHexText));
413 frameBuffer.DiscardFrame();
414 VerifyOrQuit(!frameBuffer.HasFrame());
415
416 frame = nullptr;
417 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
418 VerifyOrQuit(length == sizeof(sHelloText), "GetNextSavedFrame() length is incorrect");
419 VerifyOrQuit(memcmp(frame, sHelloText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
420
421 SuccessOrQuit(frameBuffer.GetNextSavedFrame(frame, length));
422 VerifyOrQuit(length == sizeof(sMottoText), "GetNextSavedFrame() length is incorrect");
423 VerifyOrQuit(memcmp(frame, sMottoText, length) == 0, "GetNextSavedFrame() frame content is incorrect");
424
425 SuccessOrQuit(!frameBuffer.GetNextSavedFrame(frame, length));
426
427 frameBuffer.Clear();
428 VerifyOrQuit(frameBuffer.SetLength(kBufferSize - (kFrameHeaderSize - 1)) == OT_ERROR_NO_BUFS, "after Clear()");
429 VerifyOrQuit(frameBuffer.SetLength(kBufferSize - kFrameHeaderSize) == OT_ERROR_NONE, "after Clear()");
430
431 printf(" -- PASS\n");
432 }
433
434 struct DecoderContext
435 {
436 bool mWasCalled;
437 otError mError;
438 };
439
ProcessDecodedFrame(void * aContext,otError aError)440 void ProcessDecodedFrame(void *aContext, otError aError)
441 {
442 DecoderContext &decoderContext = *static_cast<DecoderContext *>(aContext);
443
444 decoderContext.mError = aError;
445 decoderContext.mWasCalled = true;
446 }
447
TestEncoderDecoder(void)448 void TestEncoderDecoder(void)
449 {
450 otError error;
451 uint8_t byte;
452 Hdlc::MultiFrameBuffer<kBufferSize> encoderBuffer;
453 Hdlc::MultiFrameBuffer<kBufferSize> decoderBuffer;
454 DecoderContext decoderContext;
455 Hdlc::Encoder encoder(encoderBuffer);
456 Hdlc::Decoder decoder(decoderBuffer, ProcessDecodedFrame, &decoderContext);
457 uint8_t * frame;
458 uint16_t length;
459 uint8_t badShortFrame[3] = {kFlagSequence, 0xaa, kFlagSequence};
460
461 printf("Testing Hdlc::Encoder and Hdlc::Decoder");
462
463 SuccessOrQuit(encoder.BeginFrame());
464 SuccessOrQuit(encoder.Encode(sOpenThreadText, sizeof(sOpenThreadText) - 1));
465 SuccessOrQuit(encoder.EndFrame());
466 encoderBuffer.SaveFrame();
467
468 SuccessOrQuit(encoder.BeginFrame());
469 SuccessOrQuit(encoder.Encode(sMottoText, sizeof(sMottoText) - 1));
470 SuccessOrQuit(encoder.EndFrame());
471 encoderBuffer.SaveFrame();
472
473 SuccessOrQuit(encoder.BeginFrame());
474 SuccessOrQuit(encoder.Encode(sHdlcSpecials, sizeof(sHdlcSpecials)));
475 SuccessOrQuit(encoder.EndFrame());
476 encoderBuffer.SaveFrame();
477
478 SuccessOrQuit(encoder.BeginFrame());
479 SuccessOrQuit(encoder.Encode(sHelloText, sizeof(sHelloText) - 1));
480 SuccessOrQuit(encoder.EndFrame());
481 encoderBuffer.SaveFrame();
482
483 SuccessOrQuit(encoder.BeginFrame());
484 // Empty frame
485 SuccessOrQuit(encoder.EndFrame());
486 encoderBuffer.SaveFrame();
487
488 byte = kFlagSequence;
489 SuccessOrQuit(encoder.BeginFrame());
490 SuccessOrQuit(encoder.Encode(&byte, sizeof(uint8_t)));
491 SuccessOrQuit(encoder.EndFrame());
492 encoderBuffer.SaveFrame();
493
494 // Feed the encoded frames to decoder and save the content
495 for (frame = nullptr; encoderBuffer.GetNextSavedFrame(frame, length) == OT_ERROR_NONE;)
496 {
497 decoderContext.mWasCalled = false;
498
499 decoder.Decode(frame, length);
500
501 VerifyOrQuit(decoderContext.mWasCalled);
502 VerifyOrQuit(decoderContext.mError == OT_ERROR_NONE, "Decoder::Decode() returned incorrect error code");
503
504 decoderBuffer.SaveFrame();
505 }
506
507 // Verify the decoded frames match the original frames
508 frame = nullptr;
509 SuccessOrQuit(decoderBuffer.GetNextSavedFrame(frame, length));
510 VerifyOrQuit(length == sizeof(sOpenThreadText) - 1, "Decoded frame length does not match original frame");
511 VerifyOrQuit(memcmp(frame, sOpenThreadText, length) == 0, "Decoded frame content does not match original frame");
512
513 SuccessOrQuit(decoderBuffer.GetNextSavedFrame(frame, length));
514 VerifyOrQuit(length == sizeof(sMottoText) - 1, "Decoded frame length does not match original frame");
515 VerifyOrQuit(memcmp(frame, sMottoText, length) == 0, "Decoded frame content does not match original frame");
516
517 SuccessOrQuit(decoderBuffer.GetNextSavedFrame(frame, length));
518 VerifyOrQuit(length == sizeof(sHdlcSpecials), "Decoded frame length does not match original frame");
519 VerifyOrQuit(memcmp(frame, sHdlcSpecials, length) == 0, "Decoded frame content does not match original frame");
520
521 SuccessOrQuit(decoderBuffer.GetNextSavedFrame(frame, length));
522 VerifyOrQuit(length == sizeof(sHelloText) - 1, "Decoded frame length does not match original frame");
523 VerifyOrQuit(memcmp(frame, sHelloText, length) == 0, "Decoded frame content does not match original frame");
524
525 SuccessOrQuit(decoderBuffer.GetNextSavedFrame(frame, length));
526 VerifyOrQuit(length == 0, "Decoded frame length does not match original frame");
527
528 SuccessOrQuit(decoderBuffer.GetNextSavedFrame(frame, length));
529 VerifyOrQuit(length == sizeof(uint8_t), "Decoded frame length does not match original frame");
530 VerifyOrQuit(*frame == kFlagSequence, "Decoded frame content does not match original frame");
531
532 VerifyOrQuit(decoderBuffer.GetNextSavedFrame(frame, length) == OT_ERROR_NOT_FOUND, "Extra decoded frame");
533
534 encoderBuffer.Clear();
535 decoderBuffer.Clear();
536
537 // Test `Encoder` behavior when running out of buffer space
538 SuccessOrQuit(encoder.BeginFrame());
539
540 error = OT_ERROR_NONE;
541
542 for (uint16_t i = 0; error == OT_ERROR_NONE; i++)
543 {
544 byte = i & 0xff;
545 error = encoder.Encode(&byte, sizeof(uint8_t));
546 }
547
548 VerifyOrQuit(encoder.Encode(&byte, sizeof(uint8_t)) == OT_ERROR_NO_BUFS,
549 "Encoder::Encode() did not fail with a full buffer");
550 VerifyOrQuit(encoder.EndFrame(), "Encoder::EndFrame() did not fail with a full buffer");
551
552 encoderBuffer.Clear();
553
554 // Test `Decoder` behavior with incorrect FCS
555
556 SuccessOrQuit(encoder.BeginFrame());
557 SuccessOrQuit(encoder.Encode(sMottoText, sizeof(sMottoText) - 1));
558 SuccessOrQuit(encoder.EndFrame());
559
560 encoderBuffer.GetFrame()[0] ^= 0x0a; // Change the first byte in the frame to cause FCS failure
561
562 decoderContext.mWasCalled = false;
563 decoder.Decode(encoderBuffer.GetFrame(), encoderBuffer.GetLength());
564 VerifyOrQuit(decoderContext.mWasCalled);
565 VerifyOrQuit(decoderContext.mError == OT_ERROR_PARSE, "Decoder::Decode() did not fail with bad FCS");
566
567 decoderBuffer.Clear();
568
569 // Test `Decoder` behavior with short frame (smaller than FCS)
570
571 decoderContext.mWasCalled = false;
572 decoder.Decode(badShortFrame, sizeof(badShortFrame));
573 VerifyOrQuit(decoderContext.mWasCalled);
574 VerifyOrQuit(decoderContext.mError == OT_ERROR_PARSE, "Decoder::Decode() did not fail for short frame");
575
576 decoderBuffer.Clear();
577
578 // Test `Decoder` with back to back `kFlagSequence` and ensure callback is not invoked.
579
580 byte = kFlagSequence;
581 decoderContext.mWasCalled = false;
582 decoder.Decode(&byte, sizeof(uint8_t));
583 VerifyOrQuit(!decoderContext.mWasCalled);
584 decoder.Decode(&byte, sizeof(uint8_t));
585 VerifyOrQuit(!decoderContext.mWasCalled);
586 decoder.Decode(&byte, sizeof(uint8_t));
587 VerifyOrQuit(!decoderContext.mWasCalled);
588 decoder.Decode(&byte, sizeof(uint8_t));
589 VerifyOrQuit(!decoderContext.mWasCalled);
590
591 printf(" -- PASS\n");
592 }
593
GetRandom(uint32_t max)594 uint32_t GetRandom(uint32_t max)
595 {
596 return static_cast<uint32_t>(rand()) % max;
597 }
598
TestFuzzEncoderDecoder(void)599 void TestFuzzEncoderDecoder(void)
600 {
601 uint16_t length;
602 uint8_t frame[kMaxFrameLength];
603 Hdlc::FrameBuffer<kBufferSize> encoderBuffer;
604 Hdlc::FrameBuffer<kBufferSize> decoderBuffer;
605 DecoderContext decoderContext;
606 Hdlc::Encoder encoder(encoderBuffer);
607 Hdlc::Decoder decoder(decoderBuffer, ProcessDecodedFrame, &decoderContext);
608
609 printf("Testing Hdlc::Encoder and Hdlc::Decoder with randomly generated frames");
610
611 for (uint32_t iter = 0; iter < kFuzzTestIteration; iter++)
612 {
613 encoderBuffer.Clear();
614 decoderBuffer.Clear();
615
616 do
617 {
618 length = static_cast<uint16_t>(GetRandom(kMaxFrameLength));
619 } while (length == 0);
620
621 for (uint16_t i = 0; i < length; i++)
622 {
623 frame[i] = static_cast<uint8_t>(GetRandom(256));
624 }
625
626 SuccessOrQuit(encoder.BeginFrame());
627 SuccessOrQuit(encoder.Encode(frame, length));
628 SuccessOrQuit(encoder.EndFrame());
629
630 VerifyOrQuit(!encoderBuffer.IsEmpty(), "Encoded frame is empty");
631 VerifyOrQuit(encoderBuffer.GetLength() > length, "Encoded frame is too short");
632
633 decoderContext.mWasCalled = false;
634 decoder.Decode(encoderBuffer.GetFrame(), encoderBuffer.GetLength());
635 VerifyOrQuit(decoderContext.mWasCalled);
636 VerifyOrQuit(decoderContext.mError == OT_ERROR_NONE, "Decoder::Decode() returned incorrect error code");
637
638 VerifyOrQuit(!decoderBuffer.IsEmpty(), "Decoded frame is empty");
639 VerifyOrQuit(decoderBuffer.GetLength() == length, "Decoded frame length does not match original frame");
640 VerifyOrQuit(memcmp(decoderBuffer.GetFrame(), frame, length) == 0,
641 "Decoded frame content does not match original frame");
642 }
643
644 printf(" -- PASS\n");
645 }
646
647 } // namespace Ncp
648 } // namespace ot
649
main(void)650 int main(void)
651 {
652 ot::Ncp::TestHdlcFrameBuffer();
653 ot::Ncp::TestHdlcMultiFrameBuffer();
654 ot::Ncp::TestEncoderDecoder();
655 ot::Ncp::TestFuzzEncoderDecoder();
656 printf("\nAll tests passed.\n");
657 return 0;
658 }
659