@@ -168,6 +168,158 @@ static void CheckStarvation(nlTestSuite * inSuite, void * aContext)
168
168
ServiceEvents (lSys);
169
169
}
170
170
171
+ // Test the implementation helper classes TimerPool, TimerList, and TimerData.
172
+ namespace chip {
173
+ namespace System {
174
+ class TestTimer
175
+ {
176
+ public:
177
+ static void CheckTimerPool (nlTestSuite * inSuite, void * aContext);
178
+ };
179
+ } // namespace System
180
+ } // namespace chip
181
+
182
+ void chip::System::TestTimer::CheckTimerPool (nlTestSuite * inSuite, void * aContext)
183
+ {
184
+ TestContext & testContext = *static_cast <TestContext *>(aContext);
185
+ Layer & systemLayer = *testContext.mLayer ;
186
+ nlTestSuite * const suite = testContext.mTestSuite ;
187
+
188
+ using Timer = TimerList::Node;
189
+ struct TestState
190
+ {
191
+ int count = 0 ;
192
+ static void Increment (Layer * layer, void * state) { ++static_cast <TestState *>(state)->count ; }
193
+ static void Reset (Layer * layer, void * state) { static_cast <TestState *>(state)->count = 0 ; }
194
+ };
195
+ TestState testState;
196
+
197
+ using namespace Clock ::Literals;
198
+ struct
199
+ {
200
+ Clock::Timestamp awakenTime;
201
+ TimerCompleteCallback onComplete;
202
+ Timer * timer;
203
+ } testTimer[] = {
204
+ { 111_ms, TestState::Increment }, // 0
205
+ { 100_ms, TestState::Increment }, // 1
206
+ { 202_ms, TestState::Reset }, // 2
207
+ { 303_ms, TestState::Increment }, // 3
208
+ };
209
+
210
+ TimerPool<Timer> pool;
211
+ NL_TEST_ASSERT (suite, pool.mTimerPool .Allocated () == 0 );
212
+ SYSTEM_STATS_RESET (Stats::kSystemLayer_NumTimers );
213
+
214
+ // Test TimerPool::Create() and TimerData accessors.
215
+
216
+ for (auto & timer : testTimer)
217
+ {
218
+ timer.timer = pool.Create (systemLayer, timer.awakenTime , timer.onComplete , &testState);
219
+ }
220
+ #if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS
221
+ NL_TEST_ASSERT (suite, Stats::GetResourcesInUse ()[Stats::kSystemLayer_NumTimers ] == 4 );
222
+ #endif // CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS
223
+
224
+ for (auto & timer : testTimer)
225
+ {
226
+ NL_TEST_ASSERT (suite, timer.timer != nullptr );
227
+ NL_TEST_ASSERT (suite, timer.timer ->AwakenTime () == timer.awakenTime );
228
+ NL_TEST_ASSERT (suite, timer.timer ->GetCallback ().GetOnComplete () == timer.onComplete );
229
+ NL_TEST_ASSERT (suite, timer.timer ->GetCallback ().GetAppState () == &testState);
230
+ NL_TEST_ASSERT (suite, timer.timer ->GetCallback ().GetSystemLayer () == &systemLayer);
231
+ }
232
+
233
+ // Test TimerList operations.
234
+
235
+ TimerList list;
236
+ NL_TEST_ASSERT (suite, list.Remove (nullptr ) == nullptr );
237
+ NL_TEST_ASSERT (suite, list.Remove (nullptr , nullptr ) == nullptr );
238
+ NL_TEST_ASSERT (suite, list.PopEarliest () == nullptr );
239
+ NL_TEST_ASSERT (suite, list.PopIfEarlier (500_ms) == nullptr );
240
+ NL_TEST_ASSERT (suite, list.Earliest () == nullptr );
241
+ NL_TEST_ASSERT (suite, list.Empty ());
242
+
243
+ Timer * earliest = list.Add (testTimer[0 ].timer ); // list: () → (0) returns: 0
244
+ NL_TEST_ASSERT (suite, earliest == testTimer[0 ].timer );
245
+ NL_TEST_ASSERT (suite, list.PopIfEarlier (10_ms) == nullptr );
246
+ NL_TEST_ASSERT (suite, list.Earliest () == testTimer[0 ].timer );
247
+ NL_TEST_ASSERT (suite, !list.Empty ());
248
+
249
+ earliest = list.Add (testTimer[1 ].timer ); // list: (0) → (1 0) returns: 1
250
+ NL_TEST_ASSERT (suite, earliest == testTimer[1 ].timer );
251
+ NL_TEST_ASSERT (suite, list.Earliest () == testTimer[1 ].timer );
252
+
253
+ earliest = list.Add (testTimer[2 ].timer ); // list: (1 0) → (1 0 2) returns: 1
254
+ NL_TEST_ASSERT (suite, earliest == testTimer[1 ].timer );
255
+ NL_TEST_ASSERT (suite, list.Earliest () == testTimer[1 ].timer );
256
+
257
+ earliest = list.Add (testTimer[3 ].timer ); // list: (1 0 2) → (1 0 2 3) returns: 1
258
+ NL_TEST_ASSERT (suite, earliest == testTimer[1 ].timer );
259
+ NL_TEST_ASSERT (suite, list.Earliest () == testTimer[1 ].timer );
260
+
261
+ earliest = list.Remove (earliest); // list: (1 0 2 3) → (0 2 3) returns: 0
262
+ NL_TEST_ASSERT (suite, earliest == testTimer[0 ].timer );
263
+ NL_TEST_ASSERT (suite, list.Earliest () == testTimer[0 ].timer );
264
+
265
+ earliest = list.Remove (TestState::Reset, &testState); // list: (0 2 3) → (0 3) returns: 2
266
+ NL_TEST_ASSERT (suite, earliest == testTimer[2 ].timer );
267
+ NL_TEST_ASSERT (suite, list.Earliest () == testTimer[0 ].timer );
268
+
269
+ earliest = list.PopEarliest (); // list: (0 3) → (3) returns: 0
270
+ NL_TEST_ASSERT (suite, earliest == testTimer[0 ].timer );
271
+ NL_TEST_ASSERT (suite, list.Earliest () == testTimer[3 ].timer );
272
+
273
+ earliest = list.PopIfEarlier (10_ms); // list: (3) → (3) returns: nullptr
274
+ NL_TEST_ASSERT (suite, earliest == nullptr );
275
+
276
+ earliest = list.PopIfEarlier (500_ms); // list: (3) → () returns: 3
277
+ NL_TEST_ASSERT (suite, earliest == testTimer[3 ].timer );
278
+ NL_TEST_ASSERT (suite, list.Empty ());
279
+
280
+ earliest = list.Add (testTimer[3 ].timer ); // list: () → (3) returns: 3
281
+ list.Clear (); // list: (3) → ()
282
+ NL_TEST_ASSERT (suite, earliest == testTimer[3 ].timer );
283
+ NL_TEST_ASSERT (suite, list.Empty ());
284
+
285
+ for (auto & timer : testTimer)
286
+ {
287
+ list.Add (timer.timer );
288
+ }
289
+ TimerList early = list.ExtractEarlier (200_ms); // list: (1 0 2 3) → (2 3) returns: (1 0)
290
+ NL_TEST_ASSERT (suite, list.PopEarliest () == testTimer[2 ].timer );
291
+ NL_TEST_ASSERT (suite, list.PopEarliest () == testTimer[3 ].timer );
292
+ NL_TEST_ASSERT (suite, list.PopEarliest () == nullptr );
293
+ NL_TEST_ASSERT (suite, early.PopEarliest () == testTimer[1 ].timer );
294
+ NL_TEST_ASSERT (suite, early.PopEarliest () == testTimer[0 ].timer );
295
+ NL_TEST_ASSERT (suite, early.PopEarliest () == nullptr );
296
+
297
+ // Test TimerPool::Invoke()
298
+ NL_TEST_ASSERT (suite, testState.count == 0 );
299
+ pool.Invoke (testTimer[0 ].timer );
300
+ testTimer[0 ].timer = nullptr ;
301
+ NL_TEST_ASSERT (suite, testState.count == 1 );
302
+ NL_TEST_ASSERT (suite, pool.mTimerPool .Allocated () == 3 );
303
+ #if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS
304
+ NL_TEST_ASSERT (suite, Stats::GetResourcesInUse ()[Stats::kSystemLayer_NumTimers ] == 3 );
305
+ #endif // CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS
306
+
307
+ // Test TimerPool::Release()
308
+ pool.Release (testTimer[1 ].timer );
309
+ testTimer[1 ].timer = nullptr ;
310
+ NL_TEST_ASSERT (suite, testState.count == 1 );
311
+ NL_TEST_ASSERT (suite, pool.mTimerPool .Allocated () == 2 );
312
+ #if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS
313
+ NL_TEST_ASSERT (suite, Stats::GetResourcesInUse ()[Stats::kSystemLayer_NumTimers ] == 2 );
314
+ #endif // CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS
315
+
316
+ pool.ReleaseAll ();
317
+ NL_TEST_ASSERT (suite, pool.mTimerPool .Allocated () == 0 );
318
+ #if CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS
319
+ NL_TEST_ASSERT (suite, Stats::GetResourcesInUse ()[Stats::kSystemLayer_NumTimers ] == 0 );
320
+ #endif // CHIP_SYSTEM_CONFIG_PROVIDE_STATISTICS
321
+ }
322
+
171
323
// Test Suite
172
324
173
325
/* *
@@ -178,6 +330,7 @@ static const nlTest sTests[] =
178
330
{
179
331
NL_TEST_DEF (" Timer::TestOverflow" , CheckOverflow),
180
332
NL_TEST_DEF (" Timer::TestTimerStarvation" , CheckStarvation),
333
+ NL_TEST_DEF (" Timer::TestTimerPool" , chip::System::TestTimer::CheckTimerPool),
181
334
NL_TEST_SENTINEL ()
182
335
};
183
336
// clang-format on
0 commit comments