Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / system / tests / TestSystemWakeEvent.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 /**
19  *    @file
20  *      This is a unit test suite for <tt>chip::System::SystemWakeEvent</tt>
21  *
22  */
23
24 #ifndef __STDC_LIMIT_MACROS
25 #define __STDC_LIMIT_MACROS
26 #endif
27
28 #include <system/SystemConfig.h>
29
30 #include <nlunit-test.h>
31 #include <support/CodeUtils.h>
32 #include <support/ErrorStr.h>
33 #include <support/UnitTestRegistration.h>
34 #include <system/SystemError.h>
35 #include <system/SystemLayer.h>
36 #include <system/SystemWakeEvent.h>
37
38 #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
39 #include <pthread.h>
40 #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING
41
42 using namespace chip::System;
43
44 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
45 namespace {
46
47 struct TestContext
48 {
49     SystemWakeEvent mWakeEvent;
50     fd_set mReadSet;
51     fd_set mWriteSet;
52     fd_set mErrorSet;
53
54     TestContext() { mWakeEvent.Open(); }
55     ~TestContext() { mWakeEvent.Close(); }
56
57     int SelectWakeEvent(timeval timeout = {})
58     {
59         FD_ZERO(&mReadSet);
60         FD_ZERO(&mWriteSet);
61         FD_ZERO(&mErrorSet);
62         FD_SET(mWakeEvent.GetNotifFD(), &mReadSet);
63         return select(mWakeEvent.GetNotifFD() + 1, &mReadSet, &mWriteSet, &mErrorSet, &timeout);
64     }
65 };
66
67 void TestOpen(nlTestSuite * inSuite, void * aContext)
68 {
69     TestContext & lContext = *static_cast<TestContext *>(aContext);
70     NL_TEST_ASSERT(inSuite, lContext.mWakeEvent.GetNotifFD() >= 0);
71     NL_TEST_ASSERT(inSuite, lContext.SelectWakeEvent() == 0);
72 }
73
74 void TestNotify(nlTestSuite * inSuite, void * aContext)
75 {
76     TestContext & lContext = *static_cast<TestContext *>(aContext);
77     NL_TEST_ASSERT(inSuite, lContext.SelectWakeEvent() == 0);
78
79     // Check that select() succeeds after Notify() has been called
80     lContext.mWakeEvent.Notify();
81     NL_TEST_ASSERT(inSuite, lContext.SelectWakeEvent() == 1);
82     NL_TEST_ASSERT(inSuite, FD_ISSET(lContext.mWakeEvent.GetNotifFD(), &lContext.mReadSet));
83
84     // ...and state of the event is not cleared automatically
85     NL_TEST_ASSERT(inSuite, lContext.SelectWakeEvent() == 1);
86     NL_TEST_ASSERT(inSuite, FD_ISSET(lContext.mWakeEvent.GetNotifFD(), &lContext.mReadSet));
87 }
88
89 void TestConfirm(nlTestSuite * inSuite, void * aContext)
90 {
91     TestContext & lContext = *static_cast<TestContext *>(aContext);
92
93     // Check that select() succeeds after Notify() has been called
94     lContext.mWakeEvent.Notify();
95     NL_TEST_ASSERT(inSuite, lContext.SelectWakeEvent() == 1);
96     NL_TEST_ASSERT(inSuite, FD_ISSET(lContext.mWakeEvent.GetNotifFD(), &lContext.mReadSet));
97
98     // Check that Confirm() clears state of the event
99     lContext.mWakeEvent.Confirm();
100     NL_TEST_ASSERT(inSuite, lContext.SelectWakeEvent() == 0);
101 }
102
103 #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING
104 void * WaitForEvent(void * aContext)
105 {
106     TestContext & lContext = *static_cast<TestContext *>(aContext);
107     // wait 5 seconds
108     return reinterpret_cast<void *>(lContext.SelectWakeEvent(timeval{ 5, 0 }));
109 }
110
111 void TestBlockingSelect(nlTestSuite * inSuite, void * aContext)
112 {
113     TestContext & lContext = *static_cast<TestContext *>(aContext);
114
115     // Spawn a thread waiting for the event
116     pthread_t tid = 0;
117     NL_TEST_ASSERT(inSuite, 0 == pthread_create(&tid, nullptr, WaitForEvent, aContext));
118
119     lContext.mWakeEvent.Notify();
120     void * selectResult = nullptr;
121     NL_TEST_ASSERT(inSuite, 0 == pthread_join(tid, &selectResult));
122     NL_TEST_ASSERT(inSuite, selectResult == reinterpret_cast<void *>(1));
123 }
124 #else  // CHIP_SYSTEM_CONFIG_POSIX_LOCKING
125 void TestBlockingSelect(nlTestSuite *, void *) {}
126 #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING
127
128 void TestClose(nlTestSuite * inSuite, void * aContext)
129 {
130     TestContext & lContext = *static_cast<TestContext *>(aContext);
131     lContext.mWakeEvent.Close();
132
133     const auto notifFD = lContext.mWakeEvent.GetNotifFD();
134
135     // Check that Close() has cleaned up itself and reopen is possible
136     NL_TEST_ASSERT(inSuite, lContext.mWakeEvent.Open() == CHIP_SYSTEM_NO_ERROR);
137     NL_TEST_ASSERT(inSuite, notifFD < 0);
138 }
139 } // namespace
140
141 // Test Suite
142
143 /**
144  *   Test Suite. It lists all the test functions.
145  */
146 // clang-format off
147 static const nlTest sTests[] =
148 {
149     NL_TEST_DEF("WakeEvent::TestOpen",              TestOpen),
150     NL_TEST_DEF("WakeEvent::TestNotify",            TestNotify),
151     NL_TEST_DEF("WakeEvent::TestConfirm",           TestConfirm),
152     NL_TEST_DEF("WakeEvent::TestBlockingSelect",    TestBlockingSelect),
153     NL_TEST_DEF("WakeEvent::TestClose",             TestClose),
154     NL_TEST_SENTINEL()
155 };
156 // clang-format on
157
158 // clang-format off
159 static nlTestSuite kTheSuite =
160 {
161     "chip-system-wake-event",
162     sTests
163 };
164 // clang-format on
165
166 int TestSystemWakeEvent(void)
167 {
168     TestContext context;
169
170     // Run test suit againt one lContext.
171     nlTestRunner(&kTheSuite, &context);
172
173     return nlTestRunnerStats(&kTheSuite);
174 }
175
176 CHIP_REGISTER_TEST_SUITE(TestSystemWakeEvent)
177 #else  // CHIP_SYSTEM_CONFIG_USE_SOCKETS
178 int TestSystemWakeEvent(void)
179 {
180     return SUCCESS;
181 }
182 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS