Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5c605c3

Browse files
committedAug 2, 2023
Implemented a mock clock in TestReadInteraction to reduce wait loops
1 parent 146cc01 commit 5c605c3

File tree

1 file changed

+57
-119
lines changed

1 file changed

+57
-119
lines changed
 

‎src/app/tests/TestReadInteraction.cpp

+57-119
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,17 @@ chip::EndpointId kInvalidTestEndpointId = 3;
6767
chip::DataVersion kTestDataVersion1 = 3;
6868
chip::DataVersion kTestDataVersion2 = 5;
6969

70+
static chip::System::Clock::Internal::MockClock mockClock;
71+
static chip::System::Clock::ClockBase * realClock;
72+
7073
class TestContext : public chip::Test::AppContext
7174
{
7275
public:
7376
static int Initialize(void * context)
7477
{
78+
realClock = &chip::System::SystemClock();
79+
chip::System::Clock::Internal::SetSystemClockForTesting(&mockClock);
80+
7581
if (AppContext::Initialize(context) != SUCCESS)
7682
return FAILURE;
7783

@@ -97,6 +103,7 @@ class TestContext : public chip::Test::AppContext
97103
static int Finalize(void * context)
98104
{
99105
chip::app::EventManagement::DestroyEventManagement();
106+
chip::System::Clock::Internal::SetSystemClockForTesting(realClock);
100107

101108
if (AppContext::Finalize(context) != SUCCESS)
102109
return FAILURE;
@@ -1598,17 +1605,9 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a
15981605

15991606
// Test report with 2 different path
16001607

1601-
// Wait for min interval to elapse
1602-
System::Clock::Timestamp startTime = System::SystemClock().GetMonotonicTimestamp();
1603-
while (true)
1604-
{
1605-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
1606-
System::Clock::Seconds16(readPrepareParams.mMinIntervalFloorSeconds))
1607-
{
1608-
break;
1609-
}
1610-
ctx.GetIOContext().DriveIO();
1611-
}
1608+
// Advance monotonic timestamp for min interval to elapse
1609+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMinIntervalFloorSeconds));
1610+
ctx.GetIOContext().DriveIO();
16121611

16131612
delegate.mGotReport = false;
16141613
delegate.mGotEventResponse = false;
@@ -1626,17 +1625,10 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a
16261625
NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2);
16271626

16281627
// Test report with 2 different path, and 1 same path
1629-
// Wait for min interval to elapse
1630-
startTime = System::SystemClock().GetMonotonicTimestamp();
1631-
while (true)
1632-
{
1633-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
1634-
System::Clock::Seconds16(readPrepareParams.mMinIntervalFloorSeconds))
1635-
{
1636-
break;
1637-
}
1638-
ctx.GetIOContext().DriveIO();
1639-
}
1628+
// Advance monotonic timestamp for min interval to elapse
1629+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMinIntervalFloorSeconds));
1630+
ctx.GetIOContext().DriveIO();
1631+
16401632
delegate.mGotReport = false;
16411633
delegate.mNumAttributeResponse = 0;
16421634
err = engine->GetReportingEngine().SetDirty(dirtyPath1);
@@ -1652,17 +1644,10 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a
16521644
NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2);
16531645

16541646
// Test report with 3 different path, and one path is overlapped with another
1655-
// Wait for min interval to elapse
1656-
startTime = System::SystemClock().GetMonotonicTimestamp();
1657-
while (true)
1658-
{
1659-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
1660-
System::Clock::Seconds16(readPrepareParams.mMinIntervalFloorSeconds))
1661-
{
1662-
break;
1663-
}
1664-
ctx.GetIOContext().DriveIO();
1665-
}
1647+
// Advance monotonic timestamp for min interval to elapse
1648+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMinIntervalFloorSeconds));
1649+
ctx.GetIOContext().DriveIO();
1650+
16661651
delegate.mGotReport = false;
16671652
delegate.mNumAttributeResponse = 0;
16681653
err = engine->GetReportingEngine().SetDirty(dirtyPath1);
@@ -1678,17 +1663,10 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a
16781663
NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2);
16791664

16801665
// Test report with 3 different path, all are not overlapped, one path is not interested for current subscription
1681-
// Wait for min interval to elapse
1682-
startTime = System::SystemClock().GetMonotonicTimestamp();
1683-
while (true)
1684-
{
1685-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
1686-
System::Clock::Seconds16(readPrepareParams.mMinIntervalFloorSeconds))
1687-
{
1688-
break;
1689-
}
1690-
ctx.GetIOContext().DriveIO();
1691-
}
1666+
// Advance monotonic timestamp for min interval to elapse
1667+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMinIntervalFloorSeconds));
1668+
ctx.GetIOContext().DriveIO();
1669+
16921670
delegate.mGotReport = false;
16931671
delegate.mNumAttributeResponse = 0;
16941672
err = engine->GetReportingEngine().SetDirty(dirtyPath1);
@@ -1704,16 +1682,8 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a
17041682
NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2);
17051683

17061684
// Test empty report
1707-
// Wait for max interval to elapse
1708-
startTime = System::SystemClock().GetMonotonicTimestamp();
1709-
while (true)
1710-
{
1711-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
1712-
System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds))
1713-
{
1714-
break;
1715-
}
1716-
}
1685+
// Advance monotonic timestamp for min interval to elapse
1686+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds));
17171687
ctx.GetIOContext().DriveIO();
17181688

17191689
NL_TEST_ASSERT(apSuite, engine->GetReportingEngine().IsRunScheduled());
@@ -1788,8 +1758,7 @@ void TestReadInteraction::TestSubscribeUrgentWildcardEvent(nlTestSuite * apSuite
17881758
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
17891759

17901760
ctx.DrainAndServiceIO();
1791-
1792-
System::Clock::Timestamp startTime = System::SystemClock().GetMonotonicTimestamp();
1761+
System::Clock::Timestamp startTime = mockClock.GetMonotonicTimestamp();
17931762

17941763
NL_TEST_ASSERT(apSuite, engine->GetNumActiveReadHandlers() == 2);
17951764
NL_TEST_ASSERT(apSuite, engine->ActiveHandlerAt(0) != nullptr);
@@ -1813,60 +1782,60 @@ void TestReadInteraction::TestSubscribeUrgentWildcardEvent(nlTestSuite * apSuite
18131782
nonUrgentDelegate.mGotEventResponse = false;
18141783
nonUrgentDelegate.mGotReport = false;
18151784

1816-
// wait for min interval 2 seconds (in test, we use 1.6 seconds considering the time variation), expect no event is
1785+
// wait for min interval 1 seconds (in test, we use 0.6 seconds considering the time variation), expect no event is
18171786
// received, then wait for 0.8 seconds, then the urgent event would be sent out
18181787
// currently DriveIOUntil will call `DriveIO` at least once, which means that if there is any CPU scheduling issues,
18191788
// there's a chance 1.9s will already have elapsed by the time we get there, which will result in DriveIO being called when
18201789
// it shouldn't. Better fix could happen inside DriveIOUntil, not sure the sideeffect there.
1790+
1791+
// Advance monotonic looping to allow events to trigger
18211792
while (true)
18221793
{
1823-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(600))
1794+
ctx.GetIOContext().DriveIO();
1795+
if ((mockClock.GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(600))
18241796
{
18251797
break;
18261798
}
1827-
ctx.GetIOContext().DriveIO(); // at least one IO loop is guaranteed
1799+
mockClock.AdvanceMonotonic(System::Clock::Milliseconds32(10));
18281800
}
1801+
ctx.GetIOContext().DriveIO();
18291802

18301803
NL_TEST_ASSERT(apSuite, !delegate.mGotEventResponse);
18311804
NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mGotEventResponse);
18321805

1833-
startTime = System::SystemClock().GetMonotonicTimestamp();
1806+
// Advance monotonic timestamp for min interval to elapse
1807+
startTime = mockClock.GetMonotonicTimestamp();
18341808
while (true)
18351809
{
1836-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(800))
1810+
ctx.GetIOContext().DriveIO();
1811+
if ((mockClock.GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(800))
18371812
{
18381813
break;
18391814
}
1840-
ctx.GetIOContext().DriveIO(); // at least one IO loop is guaranteed
1815+
mockClock.AdvanceMonotonic(System::Clock::Milliseconds32(10));
18411816
}
1817+
ctx.GetIOContext().DriveIO();
1818+
18421819
NL_TEST_ASSERT(apSuite, delegate.mGotEventResponse);
18431820
NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mGotEventResponse);
18441821

18451822
// Since we just sent a report for our urgent subscription, the min interval of the urgent subcription should have been
18461823
// updated
18471824
NL_TEST_ASSERT(apSuite,
1848-
reportScheduler->GetMinTimestampForHandler(delegate.mpReadHandler) >
1849-
System::SystemClock().GetMonotonicTimestamp());
1825+
reportScheduler->GetMinTimestampForHandler(delegate.mpReadHandler) > mockClock.GetMonotonicTimestamp());
18501826
NL_TEST_ASSERT(apSuite, !delegate.mpReadHandler->IsDirty());
18511827
delegate.mGotEventResponse = false;
18521828

18531829
// For our non-urgent subscription, we did not send anything, so the min interval should of the non urgent subcription
18541830
// should be in the past
18551831
NL_TEST_ASSERT(apSuite,
18561832
reportScheduler->GetMinTimestampForHandler(nonUrgentDelegate.mpReadHandler) <
1857-
System::SystemClock().GetMonotonicTimestamp());
1833+
mockClock.GetMonotonicTimestamp());
18581834
NL_TEST_ASSERT(apSuite, !nonUrgentDelegate.mpReadHandler->IsDirty());
18591835

1860-
// Wait for the min interval timer to fire.
1861-
startTime = System::SystemClock().GetMonotonicTimestamp();
1862-
while (true)
1863-
{
1864-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(2100))
1865-
{
1866-
break;
1867-
}
1868-
ctx.GetIOContext().DriveIO(); // at least one IO loop is guaranteed
1869-
}
1836+
// Advance monotonic timestamp for min interval to elapse
1837+
mockClock.AdvanceMonotonic(System::Clock::Milliseconds32(2100));
1838+
ctx.GetIOContext().DriveIO();
18701839

18711840
// No reporting should have happened.
18721841
NL_TEST_ASSERT(apSuite, !delegate.mGotEventResponse);
@@ -2338,16 +2307,8 @@ void TestReadInteraction::TestSubscribeInvalidAttributePathRoundtrip(nlTestSuite
23382307
NL_TEST_ASSERT(apSuite, engine->ActiveHandlerAt(0) != nullptr);
23392308
delegate.mpReadHandler = engine->ActiveHandlerAt(0);
23402309

2341-
// Wait for max interval to elapse
2342-
System::Clock::Timestamp startTime = System::SystemClock().GetMonotonicTimestamp();
2343-
while (true)
2344-
{
2345-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
2346-
System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds))
2347-
{
2348-
break;
2349-
}
2350-
}
2310+
// Advance monotonic timestamp for min interval to elapse
2311+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds));
23512312
ctx.GetIOContext().DriveIO();
23522313

23532314
NL_TEST_ASSERT(apSuite, engine->GetReportingEngine().IsRunScheduled());
@@ -2540,15 +2501,7 @@ void TestReadInteraction::TestPostSubscribeRoundtripStatusReportTimeout(nlTestSu
25402501
NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 2);
25412502

25422503
// Wait for max interval to elapse
2543-
System::Clock::Timestamp startTime = System::SystemClock().GetMonotonicTimestamp();
2544-
while (true)
2545-
{
2546-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
2547-
System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds))
2548-
{
2549-
break;
2550-
}
2551-
}
2504+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds));
25522505
ctx.GetIOContext().DriveIO();
25532506

25542507
delegate.mGotReport = false;
@@ -2898,15 +2851,7 @@ void TestReadInteraction::TestPostSubscribeRoundtripChunkStatusReportTimeout(nlT
28982851
dirtyPath1.mEndpointId = Test::kMockEndpoint3;
28992852
dirtyPath1.mAttributeId = Test::MockAttributeId(4);
29002853

2901-
System::Clock::Timestamp startTime = System::SystemClock().GetMonotonicTimestamp();
2902-
while (true)
2903-
{
2904-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
2905-
System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds))
2906-
{
2907-
break;
2908-
}
2909-
}
2854+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds));
29102855
ctx.GetIOContext().DriveIO();
29112856

29122857
err = engine->GetReportingEngine().SetDirty(dirtyPath1);
@@ -3010,15 +2955,7 @@ void TestReadInteraction::TestPostSubscribeRoundtripChunkReportTimeout(nlTestSui
30102955
dirtyPath1.mEndpointId = Test::kMockEndpoint3;
30112956
dirtyPath1.mAttributeId = Test::MockAttributeId(4);
30122957

3013-
System::Clock::Timestamp startTime = System::SystemClock().GetMonotonicTimestamp();
3014-
while (true)
3015-
{
3016-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >=
3017-
System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds))
3018-
{
3019-
break;
3020-
}
3021-
}
2958+
mockClock.AdvanceMonotonic(System::Clock::Seconds16(readPrepareParams.mMaxIntervalCeilingSeconds));
30222959
ctx.GetIOContext().DriveIO();
30232960

30242961
err = engine->GetReportingEngine().SetDirty(dirtyPath1);
@@ -3127,26 +3064,27 @@ void TestReadInteraction::TestPostSubscribeRoundtripChunkReport(nlTestSuite * ap
31273064

31283065
// wait for min interval 1 seconds(in test, we use 0.9second considering the time variation), expect no event is received,
31293066
// then wait for 0.5 seconds, then all chunked dirty reports are sent out, which would not honor minInterval
3130-
System::Clock::Timestamp startTime = System::SystemClock().GetMonotonicTimestamp();
3067+
System::Clock::Timestamp startTime = mockClock.GetMonotonicTimestamp();
31313068
while (true)
31323069
{
3133-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(900))
3070+
ctx.GetIOContext().DriveIO();
3071+
if ((mockClock.GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(900))
31343072
{
31353073
break;
31363074
}
3137-
ctx.GetIOContext().DriveIO();
3075+
mockClock.AdvanceMonotonic(System::Clock::Milliseconds32(10));
31383076
}
31393077
NL_TEST_ASSERT(apSuite, delegate.mNumAttributeResponse == 0);
3140-
startTime = System::SystemClock().GetMonotonicTimestamp();
3078+
startTime = mockClock.GetMonotonicTimestamp();
31413079
while (true)
31423080
{
3143-
if ((System::SystemClock().GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(500))
3081+
ctx.GetIOContext().DriveIO();
3082+
if ((mockClock.GetMonotonicTimestamp() - startTime) >= System::Clock::Milliseconds32(500))
31443083
{
31453084
break;
31463085
}
3147-
ctx.GetIOContext().DriveIO();
3086+
mockClock.AdvanceMonotonic(System::Clock::Milliseconds32(10));
31483087
}
3149-
ctx.DrainAndServiceIO();
31503088
}
31513089
// Two chunked reports carry 4 attributeDataIB: 1 with a list of 3 items,
31523090
// and then one per remaining item.

0 commit comments

Comments
 (0)
Please sign in to comment.