Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / tests / TestPlatformTime.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 file implements a unit test suite for the Platform Time
21  *      code functionality.
22  *
23  */
24
25 #include <inttypes.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <nlunit-test.h>
32 #include <support/CodeUtils.h>
33 #include <support/UnitTestRegistration.h>
34 #include <system/SystemClock.h>
35
36 #include <platform/internal/CHIPDeviceLayerInternal.h>
37
38 #define TEST_TIME_MARGIN_MS 2
39 #define TEST_TIME_MARGIN_US 500
40
41 using namespace chip;
42 using namespace chip::Logging;
43 using namespace chip::System::Platform::Layer;
44
45 // =================================
46 //      Test Vectors
47 // =================================
48
49 struct time_test_vector
50 {
51     uint64_t delay;
52 };
53
54 static const struct time_test_vector test_vector_system_time_ms[] = {
55     { .delay = 10 },
56     { .delay = 100 },
57     { .delay = 250 },
58 };
59
60 static const struct time_test_vector test_vector_system_time_us[] = {
61     { .delay = 600 },
62     { .delay = 900 },
63     { .delay = 1500 },
64 };
65
66 // =================================
67 //      OS-specific utils
68 // =================================
69 // TODO: Make tests OS agnostic
70
71 #include <unistd.h>
72
73 void test_os_sleep_ms(uint64_t millisecs)
74 {
75     struct timespec sleep_time;
76     int s = millisecs / 1000;
77
78     millisecs -= s * 1000;
79     sleep_time.tv_sec  = s;
80     sleep_time.tv_nsec = millisecs * 1000000;
81
82     nanosleep(&sleep_time, nullptr);
83 }
84
85 void test_os_sleep_us(uint64_t microsecs)
86 {
87     struct timespec sleep_time;
88     int s = microsecs / 1000000;
89
90     microsecs -= s * 1000000;
91     sleep_time.tv_sec  = s;
92     sleep_time.tv_nsec = microsecs * 1000;
93
94     nanosleep(&sleep_time, nullptr);
95 }
96
97 // =================================
98 //      Unit tests
99 // =================================
100
101 static void TestDevice_GetClock_Monotonic(nlTestSuite * inSuite, void * inContext)
102 {
103     int numOfTestVectors = ArraySize(test_vector_system_time_us);
104     int numOfTestsRan    = 0;
105     const struct time_test_vector * test_params;
106
107     uint64_t margin = TEST_TIME_MARGIN_US;
108     uint64_t Tstart, Tend, Tdelta, Tdelay;
109
110     for (int vectorIndex = 0; vectorIndex < numOfTestVectors; vectorIndex++)
111     {
112         test_params = &test_vector_system_time_us[vectorIndex];
113         Tdelay      = test_params->delay;
114         Tstart      = GetClock_Monotonic();
115
116         test_os_sleep_us(test_params->delay);
117
118         Tend   = GetClock_Monotonic();
119         Tdelta = Tend - Tstart;
120
121         ChipLogProgress(DeviceLayer, "Start=%" PRIu64 " End=%" PRIu64 " Delta=%" PRIu64 " Expected=%" PRIu64, Tstart, Tend, Tdelta,
122                         Tdelay);
123         // verify that timers don't fire early
124         NL_TEST_ASSERT(inSuite, Tdelta > (Tdelay - margin));
125         // verify they're not too late
126         //        NL_TEST_ASSERT(inSuite, Tdelta < (Tdelay + margin));
127         numOfTestsRan++;
128     }
129     NL_TEST_ASSERT(inSuite, numOfTestsRan > 0);
130 }
131
132 static void TestDevice_GetClock_MonotonicMS(nlTestSuite * inSuite, void * inContext)
133 {
134     int numOfTestVectors = ArraySize(test_vector_system_time_ms);
135     int numOfTestsRan    = 0;
136     const struct time_test_vector * test_params;
137
138     uint64_t margin = TEST_TIME_MARGIN_MS;
139     uint64_t Tstart, Tend, Tdelta, Tdelay;
140
141     for (int vectorIndex = 0; vectorIndex < numOfTestVectors; vectorIndex++)
142     {
143         test_params = &test_vector_system_time_ms[vectorIndex];
144         Tdelay      = test_params->delay;
145         Tstart      = GetClock_MonotonicMS();
146
147         test_os_sleep_ms(test_params->delay);
148
149         Tend   = GetClock_MonotonicMS();
150         Tdelta = Tend - Tstart;
151
152         ChipLogProgress(DeviceLayer, "Start=%" PRIu64 " End=%" PRIu64 " Delta=%" PRIu64 " Expected=%" PRIu64, Tstart, Tend, Tdelta,
153                         Tdelay);
154         // verify that timers don't fire early
155         NL_TEST_ASSERT(inSuite, Tdelta > (Tdelay - margin));
156         // verify they're not too late
157         //        NL_TEST_ASSERT(inSuite, Tdelta < (Tdelay + margin));
158         numOfTestsRan++;
159     }
160     NL_TEST_ASSERT(inSuite, numOfTestsRan > 0);
161 }
162
163 static void TestDevice_GetClock_MonotonicHiRes(nlTestSuite * inSuite, void * inContext)
164 {
165     int numOfTestVectors = ArraySize(test_vector_system_time_us);
166     int numOfTestsRan    = 0;
167     const struct time_test_vector * test_params;
168
169     uint64_t margin = TEST_TIME_MARGIN_US;
170     uint64_t Tstart, Tend, Tdelta, Tdelay;
171
172     for (int vectorIndex = 0; vectorIndex < numOfTestVectors; vectorIndex++)
173     {
174         test_params = &test_vector_system_time_us[vectorIndex];
175         Tdelay      = test_params->delay;
176         Tstart      = GetClock_MonotonicHiRes();
177
178         test_os_sleep_us(test_params->delay);
179
180         Tend   = GetClock_MonotonicHiRes();
181         Tdelta = Tend - Tstart;
182
183         ChipLogProgress(DeviceLayer, "Start=%" PRIu64 " End=%" PRIu64 " Delta=%" PRIu64 " Expected=%" PRIu64, Tstart, Tend, Tdelta,
184                         Tdelay);
185         NL_TEST_ASSERT(inSuite, Tdelta > (Tdelay - margin));
186         numOfTestsRan++;
187     }
188     NL_TEST_ASSERT(inSuite, numOfTestsRan > 0);
189 }
190
191 /**
192  *   Test Suite. It lists all the test functions.
193  */
194 static const nlTest sTests[] = {
195
196     NL_TEST_DEF("Test DeviceLayer::GetClock_Monotonic", TestDevice_GetClock_Monotonic),
197     NL_TEST_DEF("Test DeviceLayer::GetClock_MonotonicMS", TestDevice_GetClock_MonotonicMS),
198     NL_TEST_DEF("Test DeviceLayer::GetClock_MonotonicHiRes", TestDevice_GetClock_MonotonicHiRes),
199
200     NL_TEST_SENTINEL()
201 };
202
203 int TestPlatformTime()
204 {
205     nlTestSuite theSuite = { "PlatformTime tests", &sTests[0], nullptr, nullptr };
206
207     // Run test suit againt one context.
208     nlTestRunner(&theSuite, nullptr);
209     return nlTestRunnerStats(&theSuite);
210 }
211
212 CHIP_REGISTER_TEST_SUITE(TestPlatformTime)