|
15 | 15 | * See the License for the specific language governing permissions and
|
16 | 16 | * limitations under the License.
|
17 | 17 | */
|
| 18 | +#include <app/EventManagement.h> |
| 19 | +#include <app/tests/AppTestContext.h> |
| 20 | +#include <lib/support/TestPersistentStorageDelegate.h> |
| 21 | +#include <lib/support/UnitTestContext.h> |
18 | 22 | #include <lib/support/UnitTestRegistration.h>
|
19 | 23 | #include <nlunit-test.h>
|
| 24 | +#include <system/SystemLayerImpl.h> |
20 | 25 |
|
21 |
| -int TestICDManager() |
| 26 | +#include <app/icd/ICDManager.h> |
| 27 | +#include <app/icd/ICDStateObserver.h> |
| 28 | +#include <app/icd/IcdManagementServer.h> |
| 29 | + |
| 30 | +using namespace chip; |
| 31 | +using namespace chip::app; |
| 32 | +using namespace chip::System; |
| 33 | + |
| 34 | +namespace { |
| 35 | + |
| 36 | +class TestICDStateObserver : public app::ICDStateObserver |
| 37 | +{ |
| 38 | +public: |
| 39 | + void OnEnterActiveMode() {} |
| 40 | +}; |
| 41 | + |
| 42 | +TestICDStateObserver mICDStateObserver; |
| 43 | +static Clock::Internal::MockClock gMockClock; |
| 44 | +static Clock::ClockBase * gRealClock; |
| 45 | + |
| 46 | +class TestContext : public Test::AppContext |
| 47 | +{ |
| 48 | +public: |
| 49 | + static int Initialize(void * context) |
| 50 | + { |
| 51 | + if (AppContext::Initialize(context) != SUCCESS) |
| 52 | + return FAILURE; |
| 53 | + |
| 54 | + auto * ctx = static_cast<TestContext *>(context); |
| 55 | + DeviceLayer::SetSystemLayerForTesting(&ctx->GetSystemLayer()); |
| 56 | + |
| 57 | + gRealClock = &SystemClock(); |
| 58 | + Clock::Internal::SetSystemClockForTesting(&gMockClock); |
| 59 | + |
| 60 | + if (ctx->mEventCounter.Init(0) != CHIP_NO_ERROR) |
| 61 | + { |
| 62 | + return FAILURE; |
| 63 | + } |
| 64 | + |
| 65 | + ctx->mICDManager.Init(&ctx->testStorage, &ctx->GetFabricTable(), &mICDStateObserver); |
| 66 | + return SUCCESS; |
| 67 | + } |
| 68 | + |
| 69 | + static int Finalize(void * context) |
| 70 | + { |
| 71 | + auto * ctx = static_cast<TestContext *>(context); |
| 72 | + ctx->mICDManager.Shutdown(); |
| 73 | + app::EventManagement::DestroyEventManagement(); |
| 74 | + System::Clock::Internal::SetSystemClockForTesting(gRealClock); |
| 75 | + DeviceLayer::SetSystemLayerForTesting(nullptr); |
| 76 | + |
| 77 | + if (AppContext::Finalize(context) != SUCCESS) |
| 78 | + return FAILURE; |
| 79 | + |
| 80 | + return SUCCESS; |
| 81 | + } |
| 82 | + |
| 83 | + app::ICDManager mICDManager; |
| 84 | + |
| 85 | +private: |
| 86 | + TestPersistentStorageDelegate testStorage; |
| 87 | + MonotonicallyIncreasingCounter<EventNumber> mEventCounter; |
| 88 | +}; |
| 89 | + |
| 90 | +} // namespace |
| 91 | + |
| 92 | +namespace chip { |
| 93 | +namespace app { |
| 94 | +class TestICDManager |
22 | 95 | {
|
23 |
| - static nlTest sTests[] = { NL_TEST_SENTINEL() }; |
| 96 | +public: |
| 97 | + /* |
| 98 | + * Advance the test Mock clock time by the amout passed in argument |
| 99 | + * and then force the SystemLayer Timer event loop. It will check for any expired timer, |
| 100 | + * and invoke their callbacks if there are any. |
| 101 | + * |
| 102 | + * @param time_ms: Value in milliseconds. |
| 103 | + */ |
| 104 | + static void AdvanceClockAndRunEventLoop(TestContext * ctx, uint32_t time_ms) |
| 105 | + { |
| 106 | + gMockClock.AdvanceMonotonic(System::Clock::Timeout(time_ms)); |
| 107 | + ctx->GetIOContext().DriveIO(); |
| 108 | + } |
24 | 109 |
|
25 |
| - nlTestSuite cmSuite = { "TestICDManager", &sTests[0], nullptr, nullptr }; |
| 110 | + static void TestICDModeIntervals(nlTestSuite * aSuite, void * aContext) |
| 111 | + { |
| 112 | + TestContext * ctx = static_cast<TestContext *>(aContext); |
26 | 113 |
|
27 |
| - nlTestRunner(&cmSuite, nullptr); |
28 |
| - return (nlTestRunnerStats(&cmSuite)); |
| 114 | + // After the init we should be in active mode |
| 115 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 116 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetActiveModeInterval() + 1); |
| 117 | + // Active mode interval expired, ICDManager transitioned to the IdleMode. |
| 118 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); |
| 119 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetIdleModeInterval() + 1); |
| 120 | + // Idle mode interval expired, ICDManager transitioned to the ActiveMode. |
| 121 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 122 | + |
| 123 | + // Events updating the Operation to Active mode can extend the current active mode time by 1 Active mode threshold. |
| 124 | + // Kick an active Threshold just before the end of the Active interval and validate that the active mode is extended. |
| 125 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetActiveModeInterval() - 1); |
| 126 | + ctx->mICDManager.UpdateOperationState(ICDManager::OperationalState::ActiveMode); |
| 127 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetActiveModeThreshold() / 2); |
| 128 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 129 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetActiveModeThreshold()); |
| 130 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); |
| 131 | + } |
| 132 | + |
| 133 | + static void TestKeepActivemodeRequests(nlTestSuite * aSuite, void * aContext) |
| 134 | + { |
| 135 | + TestContext * ctx = static_cast<TestContext *>(aContext); |
| 136 | + |
| 137 | + // Setting a requirement will transition the ICD to active mode. |
| 138 | + ctx->mICDManager.SetKeepActiveModeRequirements(ICDManager::KeepActiveFlags::kCommissioningWindowOpen, true); |
| 139 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 140 | + // Advance time so active mode interval expires. |
| 141 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetActiveModeInterval() + 1); |
| 142 | + // Requirement flag still set. We stay in active mode |
| 143 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 144 | + |
| 145 | + // Remove requirement. we should directly transition to idle mode. |
| 146 | + ctx->mICDManager.SetKeepActiveModeRequirements(ICDManager::KeepActiveFlags::kCommissioningWindowOpen, false); |
| 147 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); |
| 148 | + |
| 149 | + ctx->mICDManager.SetKeepActiveModeRequirements(ICDManager::KeepActiveFlags::kFailSafeArmed, true); |
| 150 | + // Requirement will transition us to active mode. |
| 151 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 152 | + |
| 153 | + // Advance time, but by less than the active mode interval and remove the requirement. |
| 154 | + // We should stay in active mode. |
| 155 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetActiveModeInterval() / 2); |
| 156 | + ctx->mICDManager.SetKeepActiveModeRequirements(ICDManager::KeepActiveFlags::kFailSafeArmed, false); |
| 157 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 158 | + |
| 159 | + // Advance time again, The activemode interval is completed. |
| 160 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetActiveModeInterval() + 1); |
| 161 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); |
| 162 | + |
| 163 | + // Set two requirements |
| 164 | + ctx->mICDManager.SetKeepActiveModeRequirements(ICDManager::KeepActiveFlags::kExpectingMsgResponse, true); |
| 165 | + ctx->mICDManager.SetKeepActiveModeRequirements(ICDManager::KeepActiveFlags::kAwaitingMsgAck, true); |
| 166 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 167 | + // advance time so the active mode interval expires. |
| 168 | + AdvanceClockAndRunEventLoop(ctx, IcdManagementServer::GetInstance().GetActiveModeInterval() + 1); |
| 169 | + // A requirement flag is still set. We stay in active mode. |
| 170 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 171 | + |
| 172 | + // remove 1 requirement. Active mode is maintained |
| 173 | + ctx->mICDManager.SetKeepActiveModeRequirements(ICDManager::KeepActiveFlags::kExpectingMsgResponse, false); |
| 174 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); |
| 175 | + // remove the last requirement |
| 176 | + ctx->mICDManager.SetKeepActiveModeRequirements(ICDManager::KeepActiveFlags::kAwaitingMsgAck, false); |
| 177 | + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); |
| 178 | + } |
| 179 | +}; |
| 180 | + |
| 181 | +} // namespace app |
| 182 | +} // namespace chip |
| 183 | + |
| 184 | +namespace { |
| 185 | +/** |
| 186 | + * Test Suite. It lists all the test functions. |
| 187 | + */ |
| 188 | +// clang-format off |
| 189 | +static const nlTest sTests[] = |
| 190 | +{ |
| 191 | + NL_TEST_DEF("TestICDModeIntervals", TestICDManager::TestICDModeIntervals), |
| 192 | + NL_TEST_DEF("TestKeepActivemodeRequests", TestICDManager::TestKeepActivemodeRequests), |
| 193 | + NL_TEST_SENTINEL() |
| 194 | +}; |
| 195 | +// clang-format on |
| 196 | + |
| 197 | +// clang-format off |
| 198 | +nlTestSuite cmSuite = |
| 199 | +{ |
| 200 | + "TestICDManager", |
| 201 | + &sTests[0], |
| 202 | + TestContext::Initialize, |
| 203 | + TestContext::Finalize |
| 204 | +}; |
| 205 | +// clang-format on |
| 206 | +} // namespace |
| 207 | + |
| 208 | +int TestSuiteICDManager() |
| 209 | +{ |
| 210 | + return ExecuteTestsWithContext<TestContext>(&cmSuite); |
29 | 211 | }
|
30 | 212 |
|
31 |
| -CHIP_REGISTER_TEST_SUITE(TestICDManager) |
| 213 | +CHIP_REGISTER_TEST_SUITE(TestSuiteICDManager) |
0 commit comments