|
28 | 28 | #include <stdlib.h>
|
29 | 29 | #include <string.h>
|
30 | 30 |
|
| 31 | +#include <atomic> |
| 32 | + |
31 | 33 | #include <lib/support/CHIPMem.h>
|
32 | 34 | #include <lib/support/CodeUtils.h>
|
33 | 35 | #include <lib/support/UnitTestRegistration.h>
|
@@ -55,14 +57,52 @@ static void TestPlatformMgr_InitShutdown(nlTestSuite * inSuite, void * inContext
|
55 | 57 |
|
56 | 58 | static void TestPlatformMgr_BasicEventLoopTask(nlTestSuite * inSuite, void * inContext)
|
57 | 59 | {
|
| 60 | + std::atomic<int> counterRun{ 0 }; |
| 61 | + |
58 | 62 | CHIP_ERROR err = PlatformMgr().InitChipStack();
|
59 | 63 | NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
|
60 | 64 |
|
61 |
| - err = PlatformMgr().StartEventLoopTask(); |
62 |
| - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); |
| 65 | + // Start/stop the event loop task a few times. |
| 66 | + for (size_t i = 0; i < 3; i++) |
| 67 | + { |
| 68 | + err = PlatformMgr().StartEventLoopTask(); |
| 69 | + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); |
| 70 | + |
| 71 | + std::atomic<int> counterSync{ 2 }; |
| 72 | + |
| 73 | + // Verify that the event loop will not exit until we tell it to by |
| 74 | + // scheduling few lambdas (for the test to pass, the event loop will |
| 75 | + // have to process more than one event). |
| 76 | + DeviceLayer::SystemLayer().ScheduleLambda([&]() { |
| 77 | + counterRun++; |
| 78 | + counterSync--; |
| 79 | + }); |
| 80 | + |
| 81 | + // Sleep for a short time to allow the event loop to process the |
| 82 | + // scheduled event and go to idle state. Without this sleep, the |
| 83 | + // event loop may process both scheduled lambdas during single |
| 84 | + // iteration of the event loop which would defeat the purpose of |
| 85 | + // this test on POSIX platforms where the event loop is implemented |
| 86 | + // using a "do { ... } while (shouldRun)" construct. |
| 87 | + chip::test_utils::SleepMillis(10); |
| 88 | + |
| 89 | + DeviceLayer::SystemLayer().ScheduleLambda([&]() { |
| 90 | + counterRun++; |
| 91 | + counterSync--; |
| 92 | + }); |
| 93 | + |
| 94 | + // Wait for the event loop to process the scheduled events. |
| 95 | + // Note, that we can not use any synchronization primitives like |
| 96 | + // condition variables or barriers, because the test has to compile |
| 97 | + // on all platforms. Instead we use a busy loop with a timeout. |
| 98 | + for (size_t t = 0; counterSync != 0 && t < 1000; t++) |
| 99 | + chip::test_utils::SleepMillis(1); |
| 100 | + |
| 101 | + err = PlatformMgr().StopEventLoopTask(); |
| 102 | + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); |
| 103 | + } |
63 | 104 |
|
64 |
| - err = PlatformMgr().StopEventLoopTask(); |
65 |
| - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); |
| 105 | + NL_TEST_ASSERT(inSuite, counterRun == (3 * 2)); |
66 | 106 |
|
67 | 107 | PlatformMgr().Shutdown();
|
68 | 108 | }
|
|
0 commit comments