1 /*
2 * Copyright (c) 2024, 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 "test_platform.h"
30 #include "test_util.h"
31
32 #include <openthread/config.h>
33
34 #include "instance/instance.hpp"
35
36 namespace ot {
37
38 #define Log(aMessage) fprintf(stderr, aMessage "\n\r")
39
40 static Instance *sInstance = nullptr;
41 static bool sTask1Handled = false;
42 static bool sTask2Handled = false;
43 static bool sTask3Handled = false;
44 static bool sSignalPendingCalled = false;
45 static bool sShouldTask3RepostItself = false;
46
otTaskletsSignalPending(otInstance * aInstance)47 extern "C" void otTaskletsSignalPending(otInstance *aInstance)
48 {
49 Log(" otTaskletsSignalPending()");
50
51 if (sInstance != nullptr)
52 {
53 VerifyOrQuit(aInstance == sInstance);
54 }
55
56 sSignalPendingCalled = true;
57 }
58
ResetTestFlags(void)59 void ResetTestFlags(void)
60 {
61 sTask1Handled = false;
62 sTask2Handled = false;
63 sTask3Handled = false;
64 sSignalPendingCalled = false;
65 }
66
CheckTaskeltFromHandler(Tasklet & aTasklet)67 void CheckTaskeltFromHandler(Tasklet &aTasklet)
68 {
69 VerifyOrQuit(&aTasklet.GetInstance() == sInstance);
70 VerifyOrQuit(!aTasklet.IsPosted());
71 }
72
HandleTask1(Tasklet & aTasklet)73 void HandleTask1(Tasklet &aTasklet)
74 {
75 Log(" HandleTask1()");
76 CheckTaskeltFromHandler(aTasklet);
77 VerifyOrQuit(!sTask1Handled);
78 sTask1Handled = true;
79 }
80
HandleTask2(Tasklet & aTasklet)81 void HandleTask2(Tasklet &aTasklet)
82 {
83 Log(" HandleTask2()");
84 CheckTaskeltFromHandler(aTasklet);
85 VerifyOrQuit(!sTask2Handled);
86 sTask2Handled = true;
87 }
88
HandleTask3(Tasklet & aTasklet)89 void HandleTask3(Tasklet &aTasklet)
90 {
91 Log(" HandleTask3()");
92 CheckTaskeltFromHandler(aTasklet);
93 VerifyOrQuit(!sTask3Handled);
94 sTask3Handled = true;
95
96 if (sShouldTask3RepostItself)
97 {
98 aTasklet.Post();
99 }
100 }
101
TestTasklet(void)102 void TestTasklet(void)
103 {
104 Log("TestTasklet");
105
106 sInstance = static_cast<Instance *>(testInitInstance());
107 VerifyOrQuit(sInstance != nullptr);
108
109 sInstance->Get<Tasklet::Scheduler>().ProcessQueuedTasklets();
110
111 {
112 Tasklet::Scheduler &scheduler = sInstance->Get<Tasklet::Scheduler>();
113 Tasklet task1(*sInstance, HandleTask1);
114 Tasklet task2(*sInstance, HandleTask2);
115 Tasklet task3(*sInstance, HandleTask3);
116
117 VerifyOrQuit(!task1.IsPosted());
118 VerifyOrQuit(!task2.IsPosted());
119 VerifyOrQuit(!task3.IsPosted());
120 VerifyOrQuit(!scheduler.AreTaskletsPending());
121
122 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
123 Log("Posting a single task");
124
125 ResetTestFlags();
126
127 task1.Post();
128 VerifyOrQuit(task1.IsPosted());
129 VerifyOrQuit(!task2.IsPosted());
130 VerifyOrQuit(!task3.IsPosted());
131
132 VerifyOrQuit(sSignalPendingCalled);
133 VerifyOrQuit(scheduler.AreTaskletsPending());
134
135 scheduler.ProcessQueuedTasklets();
136
137 VerifyOrQuit(sTask1Handled);
138 VerifyOrQuit(!sTask2Handled);
139 VerifyOrQuit(!sTask3Handled);
140
141 VerifyOrQuit(!scheduler.AreTaskletsPending());
142
143 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
144 Log("Posting multiple tasks");
145
146 ResetTestFlags();
147
148 task3.Post();
149
150 VerifyOrQuit(sSignalPendingCalled);
151 sSignalPendingCalled = false;
152
153 VerifyOrQuit(scheduler.AreTaskletsPending());
154
155 task2.Post();
156 task1.Post();
157
158 VerifyOrQuit(!sSignalPendingCalled);
159
160 VerifyOrQuit(task1.IsPosted());
161 VerifyOrQuit(task2.IsPosted());
162 VerifyOrQuit(task3.IsPosted());
163
164 scheduler.ProcessQueuedTasklets();
165
166 VerifyOrQuit(sTask1Handled);
167 VerifyOrQuit(sTask2Handled);
168 VerifyOrQuit(sTask3Handled);
169
170 VerifyOrQuit(!scheduler.AreTaskletsPending());
171 VerifyOrQuit(!sSignalPendingCalled);
172
173 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174 Log("Posting the same task multiple times");
175
176 ResetTestFlags();
177
178 task2.Post();
179
180 VerifyOrQuit(sSignalPendingCalled);
181 sSignalPendingCalled = false;
182
183 VerifyOrQuit(scheduler.AreTaskletsPending());
184
185 task2.Post();
186
187 VerifyOrQuit(!task1.IsPosted());
188 VerifyOrQuit(task2.IsPosted());
189 VerifyOrQuit(!task3.IsPosted());
190
191 task1.Post();
192 task2.Post();
193 task1.Post();
194
195 VerifyOrQuit(!sSignalPendingCalled);
196
197 VerifyOrQuit(task1.IsPosted());
198 VerifyOrQuit(task2.IsPosted());
199 VerifyOrQuit(!task3.IsPosted());
200
201 scheduler.ProcessQueuedTasklets();
202
203 VerifyOrQuit(sTask1Handled);
204 VerifyOrQuit(sTask2Handled);
205 VerifyOrQuit(!sTask3Handled);
206
207 VerifyOrQuit(!scheduler.AreTaskletsPending());
208 VerifyOrQuit(!sSignalPendingCalled);
209
210 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
211 Log("Task posting itself from its handler");
212
213 ResetTestFlags();
214 sShouldTask3RepostItself = true;
215
216 task3.Post();
217
218 VerifyOrQuit(sSignalPendingCalled);
219 sSignalPendingCalled = false;
220 VerifyOrQuit(scheduler.AreTaskletsPending());
221
222 task2.Post();
223 VerifyOrQuit(!sSignalPendingCalled);
224 VerifyOrQuit(scheduler.AreTaskletsPending());
225
226 VerifyOrQuit(!task1.IsPosted());
227 VerifyOrQuit(task2.IsPosted());
228 VerifyOrQuit(task3.IsPosted());
229
230 scheduler.ProcessQueuedTasklets();
231
232 VerifyOrQuit(!sTask1Handled);
233 VerifyOrQuit(sTask2Handled);
234 VerifyOrQuit(sTask3Handled);
235
236 VerifyOrQuit(scheduler.AreTaskletsPending());
237 VerifyOrQuit(sSignalPendingCalled);
238
239 ResetTestFlags();
240
241 sShouldTask3RepostItself = false;
242
243 scheduler.ProcessQueuedTasklets();
244 VerifyOrQuit(!sTask1Handled);
245 VerifyOrQuit(!sTask2Handled);
246 VerifyOrQuit(sTask3Handled);
247
248 VerifyOrQuit(!sSignalPendingCalled);
249 VerifyOrQuit(!scheduler.AreTaskletsPending());
250
251 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
252 Log("Un-posting a single posted task");
253
254 ResetTestFlags();
255
256 task1.Post();
257
258 VerifyOrQuit(sSignalPendingCalled);
259 sSignalPendingCalled = false;
260 VerifyOrQuit(scheduler.AreTaskletsPending());
261
262 VerifyOrQuit(task1.IsPosted());
263
264 task1.Unpost();
265
266 VerifyOrQuit(!sSignalPendingCalled);
267 VerifyOrQuit(!scheduler.AreTaskletsPending());
268
269 VerifyOrQuit(!task1.IsPosted());
270
271 scheduler.ProcessQueuedTasklets();
272
273 VerifyOrQuit(!sTask1Handled);
274 VerifyOrQuit(!sTask2Handled);
275 VerifyOrQuit(!sTask3Handled);
276
277 VerifyOrQuit(!sSignalPendingCalled);
278 VerifyOrQuit(!scheduler.AreTaskletsPending());
279
280 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
281 Log("Post multiple tasks and then un-post the first one");
282
283 ResetTestFlags();
284
285 task1.Post();
286 task2.Post();
287 task3.Post();
288
289 VerifyOrQuit(sSignalPendingCalled);
290 sSignalPendingCalled = false;
291 VerifyOrQuit(scheduler.AreTaskletsPending());
292
293 VerifyOrQuit(task1.IsPosted());
294 VerifyOrQuit(task2.IsPosted());
295 VerifyOrQuit(task3.IsPosted());
296
297 task1.Unpost();
298
299 VerifyOrQuit(!task1.IsPosted());
300 VerifyOrQuit(task2.IsPosted());
301 VerifyOrQuit(task3.IsPosted());
302
303 scheduler.ProcessQueuedTasklets();
304
305 VerifyOrQuit(!sTask1Handled);
306 VerifyOrQuit(sTask2Handled);
307 VerifyOrQuit(sTask3Handled);
308
309 VerifyOrQuit(!sSignalPendingCalled);
310 VerifyOrQuit(!scheduler.AreTaskletsPending());
311
312 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
313 Log("Post multiple tasks and then un-post the middle one");
314
315 ResetTestFlags();
316
317 task1.Post();
318 task2.Post();
319 task3.Post();
320
321 VerifyOrQuit(sSignalPendingCalled);
322 sSignalPendingCalled = false;
323 VerifyOrQuit(scheduler.AreTaskletsPending());
324
325 VerifyOrQuit(task1.IsPosted());
326 VerifyOrQuit(task2.IsPosted());
327 VerifyOrQuit(task3.IsPosted());
328
329 task2.Unpost();
330
331 VerifyOrQuit(task1.IsPosted());
332 VerifyOrQuit(!task2.IsPosted());
333 VerifyOrQuit(task3.IsPosted());
334
335 scheduler.ProcessQueuedTasklets();
336
337 VerifyOrQuit(sTask1Handled);
338 VerifyOrQuit(!sTask2Handled);
339 VerifyOrQuit(sTask3Handled);
340
341 VerifyOrQuit(!sSignalPendingCalled);
342 VerifyOrQuit(!scheduler.AreTaskletsPending());
343
344 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
345 Log("Post multiple tasks and then un-post the last one");
346
347 ResetTestFlags();
348
349 task1.Post();
350 task2.Post();
351 task3.Post();
352
353 VerifyOrQuit(sSignalPendingCalled);
354 sSignalPendingCalled = false;
355 VerifyOrQuit(scheduler.AreTaskletsPending());
356
357 VerifyOrQuit(task1.IsPosted());
358 VerifyOrQuit(task2.IsPosted());
359 VerifyOrQuit(task3.IsPosted());
360
361 task3.Unpost();
362
363 VerifyOrQuit(task1.IsPosted());
364 VerifyOrQuit(task2.IsPosted());
365 VerifyOrQuit(!task3.IsPosted());
366
367 scheduler.ProcessQueuedTasklets();
368
369 VerifyOrQuit(sTask1Handled);
370 VerifyOrQuit(sTask2Handled);
371 VerifyOrQuit(!sTask3Handled);
372
373 VerifyOrQuit(!sSignalPendingCalled);
374 VerifyOrQuit(!scheduler.AreTaskletsPending());
375
376 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
377 Log("Post multiple tasks and then un-post the first and last ones");
378
379 ResetTestFlags();
380
381 task1.Post();
382 task2.Post();
383 task3.Post();
384
385 VerifyOrQuit(sSignalPendingCalled);
386 sSignalPendingCalled = false;
387 VerifyOrQuit(scheduler.AreTaskletsPending());
388
389 VerifyOrQuit(task1.IsPosted());
390 VerifyOrQuit(task2.IsPosted());
391 VerifyOrQuit(task3.IsPosted());
392
393 task1.Unpost();
394 task3.Unpost();
395
396 VerifyOrQuit(!task1.IsPosted());
397 VerifyOrQuit(task2.IsPosted());
398 VerifyOrQuit(!task3.IsPosted());
399
400 scheduler.ProcessQueuedTasklets();
401
402 VerifyOrQuit(!sTask1Handled);
403 VerifyOrQuit(sTask2Handled);
404 VerifyOrQuit(!sTask3Handled);
405
406 VerifyOrQuit(!sSignalPendingCalled);
407 VerifyOrQuit(!scheduler.AreTaskletsPending());
408
409 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
410 Log("Post multiple tasks and then un-post all in the same order added");
411
412 ResetTestFlags();
413
414 task1.Post();
415 task2.Post();
416 task3.Post();
417
418 VerifyOrQuit(sSignalPendingCalled);
419 sSignalPendingCalled = false;
420 VerifyOrQuit(scheduler.AreTaskletsPending());
421
422 VerifyOrQuit(task1.IsPosted());
423 VerifyOrQuit(task2.IsPosted());
424 VerifyOrQuit(task3.IsPosted());
425
426 task1.Unpost();
427 task2.Unpost();
428 task3.Unpost();
429
430 VerifyOrQuit(!task1.IsPosted());
431 VerifyOrQuit(!task2.IsPosted());
432 VerifyOrQuit(!task3.IsPosted());
433
434 VerifyOrQuit(!scheduler.AreTaskletsPending());
435
436 scheduler.ProcessQueuedTasklets();
437
438 VerifyOrQuit(!sTask1Handled);
439 VerifyOrQuit(!sTask2Handled);
440 VerifyOrQuit(!sTask3Handled);
441
442 VerifyOrQuit(!sSignalPendingCalled);
443 VerifyOrQuit(!scheduler.AreTaskletsPending());
444
445 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
446 Log("Post multiple tasks and then un-post all in the reverse order added");
447
448 ResetTestFlags();
449
450 task1.Post();
451 task2.Post();
452 task3.Post();
453
454 VerifyOrQuit(sSignalPendingCalled);
455 sSignalPendingCalled = false;
456 VerifyOrQuit(scheduler.AreTaskletsPending());
457
458 VerifyOrQuit(task1.IsPosted());
459 VerifyOrQuit(task2.IsPosted());
460 VerifyOrQuit(task3.IsPosted());
461
462 task3.Unpost();
463 task2.Unpost();
464 task1.Unpost();
465
466 VerifyOrQuit(!task1.IsPosted());
467 VerifyOrQuit(!task2.IsPosted());
468 VerifyOrQuit(!task3.IsPosted());
469
470 VerifyOrQuit(!scheduler.AreTaskletsPending());
471
472 scheduler.ProcessQueuedTasklets();
473
474 VerifyOrQuit(!sTask1Handled);
475 VerifyOrQuit(!sTask2Handled);
476 VerifyOrQuit(!sTask3Handled);
477
478 VerifyOrQuit(!sSignalPendingCalled);
479 VerifyOrQuit(!scheduler.AreTaskletsPending());
480
481 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
482 Log("Post multiple tasks and then un-post all in different order (middle first)");
483
484 ResetTestFlags();
485
486 task1.Post();
487 task2.Post();
488 task3.Post();
489
490 VerifyOrQuit(sSignalPendingCalled);
491 sSignalPendingCalled = false;
492 VerifyOrQuit(scheduler.AreTaskletsPending());
493
494 VerifyOrQuit(task1.IsPosted());
495 VerifyOrQuit(task2.IsPosted());
496 VerifyOrQuit(task3.IsPosted());
497
498 task2.Unpost();
499 task3.Unpost();
500 task1.Unpost();
501
502 VerifyOrQuit(!task1.IsPosted());
503 VerifyOrQuit(!task2.IsPosted());
504 VerifyOrQuit(!task3.IsPosted());
505
506 VerifyOrQuit(!scheduler.AreTaskletsPending());
507
508 scheduler.ProcessQueuedTasklets();
509
510 VerifyOrQuit(!sTask1Handled);
511 VerifyOrQuit(!sTask2Handled);
512 VerifyOrQuit(!sTask3Handled);
513
514 VerifyOrQuit(!sSignalPendingCalled);
515 VerifyOrQuit(!scheduler.AreTaskletsPending());
516
517 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
518 Log("Un-posting tasks not yet posted");
519
520 ResetTestFlags();
521
522 task1.Unpost();
523
524 VerifyOrQuit(!task1.IsPosted());
525
526 VerifyOrQuit(!sSignalPendingCalled);
527 VerifyOrQuit(!scheduler.AreTaskletsPending());
528
529 task2.Post();
530
531 VerifyOrQuit(sSignalPendingCalled);
532 sSignalPendingCalled = false;
533 VerifyOrQuit(scheduler.AreTaskletsPending());
534
535 task1.Unpost();
536 task3.Unpost();
537
538 VerifyOrQuit(!task1.IsPosted());
539 VerifyOrQuit(task2.IsPosted());
540 VerifyOrQuit(!task3.IsPosted());
541
542 VerifyOrQuit(scheduler.AreTaskletsPending());
543
544 task3.Post();
545
546 VerifyOrQuit(!task1.IsPosted());
547 VerifyOrQuit(task2.IsPosted());
548 VerifyOrQuit(task3.IsPosted());
549
550 VerifyOrQuit(!sSignalPendingCalled);
551 VerifyOrQuit(scheduler.AreTaskletsPending());
552
553 scheduler.ProcessQueuedTasklets();
554
555 VerifyOrQuit(!sTask1Handled);
556 VerifyOrQuit(sTask2Handled);
557 VerifyOrQuit(sTask3Handled);
558
559 VerifyOrQuit(!sSignalPendingCalled);
560 VerifyOrQuit(!scheduler.AreTaskletsPending());
561 }
562 }
563
564 } // namespace ot
565
main(void)566 int main(void)
567 {
568 ot::TestTasklet();
569 printf("All tests passed\n");
570 return 0;
571 }
572