mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
timeUtils_test.cpp
Go to the documentation of this file.
1/** \file timeUtils_test.cpp
2 */
3#include "../../catch2/catch.hpp"
4
5#include "../../../include/sys/timeUtils.hpp"
6
7/** \test Scenario: Verify operation of get_curr_time.
8 *
9 * This only checks for increasing time on subsequent calls.
10 *
11 * \anchor tests_sys_timeUtils_get_curr_time
12 */
13SCENARIO( "Verify operation of get_curr_time", "[timeutils]" )
14{
15 GIVEN( "getting the time" )
16 {
17 WHEN( "the same timespec is used" )
18 {
19 timespec ts;
20 double t0 = mx::sys::get_curr_time( ts );
21 REQUIRE( t0 > 0 );
22 std::cout << std::endl; // Do something to make sure some time passes.
23 double t1 = mx::sys::get_curr_time( ts );
24
25 REQUIRE( t1 > t0 );
26 }
27
28 WHEN( "no timespec is provided" )
29 {
30 double t0 = mx::sys::get_curr_time();
31 REQUIRE( t0 > 0 );
32 std::cout << std::endl; // Do something to make sure some time passes.
33 double t1 = mx::sys::get_curr_time();
34
35 REQUIRE( t1 > t0 );
36 }
37 }
38}
39
40/** \test Scenario: Verify operation of thread sleep functions
41 *
42 * Uses mx::sys::get_curr_time to verify duration of sleep.
43 *
44 * \anchor tests_sys_timeUtils_sleep
45 */
46SCENARIO( "Verify operation of thread sleep functions", "[timeutils]" )
47{
48 GIVEN( "sleeping for 1 second" )
49 {
50 WHEN( "sleeping in seconds" )
51 {
52 double t0 = mx::sys::get_curr_time();
53 mx::sys::sleep( 1 );
54 double t1 = mx::sys::get_curr_time();
55
56 REQUIRE( t1 >= t0 + 1.0 );
57 }
58 WHEN( "sleeping in milliseconds" )
59 {
60 double t0 = mx::sys::get_curr_time();
61 mx::sys::milliSleep( 1000 );
62 double t1 = mx::sys::get_curr_time();
63
64 REQUIRE( t1 >= t0 + 1.0 );
65 }
66 WHEN( "sleeping in microseconds" )
67 {
68 double t0 = mx::sys::get_curr_time();
69 mx::sys::microSleep( 1000000 );
70 double t1 = mx::sys::get_curr_time();
71
72 REQUIRE( t1 >= t0 + 1.0 );
73 }
74 WHEN( "sleeping in nanoseconds" )
75 {
76 double t0 = mx::sys::get_curr_time();
77 mx::sys::nanoSleep( 1000000000 );
78 double t1 = mx::sys::get_curr_time();
79
80 REQUIRE( t1 >= t0 + 1.0 );
81 }
82 }
83}
84
85/** \test Scenario: Verify operation of timespecAddNsec
86 *
87 * \anchor tests_sys_timeUtils_timespecAddNsec
88 */
89SCENARIO( "Verify operation of timespecAddNsec", "[timeutils]" )
90{
91 GIVEN( "a timespec" )
92 {
93 WHEN( "adding less than 1e9 nanoseconds" )
94 {
95 timespec ts;
96 ts.tv_sec = 1;
97 ts.tv_nsec = 0;
98
100 REQUIRE( ts.tv_sec == 1 );
101 REQUIRE( ts.tv_nsec == 10 );
102
103 mx::sys::timespecAddNsec( ts, 100 );
104 REQUIRE( ts.tv_sec == 1 );
105 REQUIRE( ts.tv_nsec == 110 );
106
107 mx::sys::timespecAddNsec( ts, 1000 );
108 REQUIRE( ts.tv_sec == 1 );
109 REQUIRE( ts.tv_nsec == 1110 );
110
111 mx::sys::timespecAddNsec( ts, 10000 );
112 REQUIRE( ts.tv_sec == 1 );
113 REQUIRE( ts.tv_nsec == 11110 );
114
115 mx::sys::timespecAddNsec( ts, 100000 );
116 REQUIRE( ts.tv_sec == 1 );
117 REQUIRE( ts.tv_nsec == 111110 );
118
119 mx::sys::timespecAddNsec( ts, 1000000 );
120 REQUIRE( ts.tv_sec == 1 );
121 REQUIRE( ts.tv_nsec == 1111110 );
122
123 mx::sys::timespecAddNsec( ts, 10000000 );
124 REQUIRE( ts.tv_sec == 1 );
125 REQUIRE( ts.tv_nsec == 11111110 );
126
127 mx::sys::timespecAddNsec( ts, 100000000 );
128 REQUIRE( ts.tv_sec == 1 );
129 REQUIRE( ts.tv_nsec == 111111110 );
130 }
131
132 WHEN( "adding more than 1e9 nanoseconds but less than 2e9" )
133 {
134 timespec ts;
135 ts.tv_sec = 1;
136 ts.tv_nsec = 0;
137
138 mx::sys::timespecAddNsec( ts, 1000000000 );
139 REQUIRE( ts.tv_sec == 2 );
140 REQUIRE( ts.tv_nsec == 0 );
141
142 mx::sys::timespecAddNsec( ts, 1000000000 + 10 );
143 REQUIRE( ts.tv_sec == 3 );
144 REQUIRE( ts.tv_nsec == 10 );
145
146 mx::sys::timespecAddNsec( ts, 1000000000 + 100 );
147 REQUIRE( ts.tv_sec == 4 );
148 REQUIRE( ts.tv_nsec == 110 );
149
150 mx::sys::timespecAddNsec( ts, 1000000000 + 1000 );
151 REQUIRE( ts.tv_sec == 5 );
152 REQUIRE( ts.tv_nsec == 1110 );
153
154 mx::sys::timespecAddNsec( ts, 1000000000 + 10000 );
155 REQUIRE( ts.tv_sec == 6 );
156 REQUIRE( ts.tv_nsec == 11110 );
157
158 mx::sys::timespecAddNsec( ts, 1000000000 + 100000 );
159 REQUIRE( ts.tv_sec == 7 );
160 REQUIRE( ts.tv_nsec == 111110 );
161
162 mx::sys::timespecAddNsec( ts, 1000000000 + 1000000 );
163 REQUIRE( ts.tv_sec == 8 );
164 REQUIRE( ts.tv_nsec == 1111110 );
165
166 mx::sys::timespecAddNsec( ts, 1000000000 + 10000000 );
167 REQUIRE( ts.tv_sec == 9 );
168 REQUIRE( ts.tv_nsec == 11111110 );
169
170 mx::sys::timespecAddNsec( ts, 1000000000 + 100000000 );
171 REQUIRE( ts.tv_sec == 10 );
172 REQUIRE( ts.tv_nsec == 111111110 );
173 }
174
175 WHEN( "adding more than 2e9" )
176 {
177 timespec ts;
178 ts.tv_sec = 1;
179 ts.tv_nsec = 0;
180
181 mx::sys::timespecAddNsec( ts, 2000000010 );
182 REQUIRE( ts.tv_sec == 3 );
183 REQUIRE( ts.tv_nsec == 10 );
184 }
185 }
186}
187
188/** \test Scenario: Verify parsing of a formatted time string
189 *
190 * Tests parsing of a string of format hh:mm:ss.s
191 *
192 * \anchor tests_sys_timeUtils_parse_hms
193 */
194SCENARIO( "Verify parsing of a formatted time string", "[timeutils]" )
195{
196 GIVEN( "a valid time string" )
197 {
198 WHEN( "integer seconds" )
199 {
200 float hr;
201 float mn;
202 float sec;
203
204 mx::sys::parse_hms( hr, mn, sec, "1:2:3" );
205
206 REQUIRE( hr == 1 );
207 REQUIRE( mn == 2 );
208 REQUIRE( sec == 3 );
209 }
210
211 WHEN( "floating seconds" )
212 {
213 float hr;
214 float mn;
215 float sec;
216
217 mx::sys::parse_hms( hr, mn, sec, "1:2:3.23" );
218
219 REQUIRE( hr == 1 );
220 REQUIRE( mn == 2 );
221 REQUIRE( fabs( sec - 3.23 ) < 1e-7 );
222 }
223
224 WHEN( "negative hour" )
225 {
226 float hr;
227 float mn;
228 float sec;
229
230 mx::sys::parse_hms( hr, mn, sec, "-1:2:3.23" );
231
232 REQUIRE( hr == -1 );
233 REQUIRE( mn == -2 );
234 REQUIRE( fabs( sec - -3.23 ) < 1e-7 );
235 }
236
237 WHEN( "0 pads" )
238 {
239 float hr;
240 float mn;
241 float sec;
242
243 mx::sys::parse_hms( hr, mn, sec, "01:02:03.23" );
244
245 REQUIRE( hr == 1 );
246 REQUIRE( mn == 2 );
247 REQUIRE( fabs( sec - 3.23 ) < 1e-7 );
248 }
249 }
250}
251
252/** \test Scenario: Verify calculation of MJD
253 *
254 * \anchor tests_sys_timeUtils_Cal2mjd
255 */
256SCENARIO( "Verify calculation of MJD", "[timeutils]" )
257{
258 GIVEN( "a valid Gregorian date" )
259 {
260 WHEN( "integer seconds" )
261 {
262 double mjd = mx::sys::Cal2mjd( 2020, 12, 31, 0, 0, 0 );
263 REQUIRE( mjd == 59214.0 );
264 }
265 }
266
267 GIVEN( "a valid Gregorian date" )
268 {
269 WHEN( "floating seconds" )
270 {
271 double mjd = mx::sys::Cal2mjd( 2020, 12, 31, 0, 0, 10.2357 );
272 REQUIRE( fabs( mjd - 59214.00011846875 ) < 1e-14 );
273 }
274 }
275}
276
277/** \test Scenario: Verify parsing of an ISO 8601 time string
278 *
279 * \anchor tests_sys_timeUtils_ISO8601dateBreakdown
280 */
281SCENARIO( "Verify parsing of an ISO 8601 time string", "[timeutils]" )
282{
283 GIVEN( "a valid ISO 8601 time string" )
284 {
285 WHEN( "integer seconds" )
286 {
287 int yr, mon, day, hr, min;
288 double sec;
289
290 int rv = mx::sys::ISO8601dateBreakdown( yr, mon, day, hr, min, sec, "2020-12-31T00:00:00" );
291
292 REQUIRE( rv == 0 );
293 REQUIRE( yr == 2020 );
294 REQUIRE( mon == 12 );
295 REQUIRE( day == 31 );
296 REQUIRE( hr == 0 );
297 REQUIRE( min == 0 );
298 REQUIRE( sec == 0 );
299 }
300
301 WHEN( "fractional seconds" )
302 {
303 int yr, mon, day, hr, min;
304 double sec;
305
306 int rv = mx::sys::ISO8601dateBreakdown( yr, mon, day, hr, min, sec, "2020-12-31T00:00:10.2357" );
307
308 REQUIRE( rv == 0 );
309 REQUIRE( yr == 2020 );
310 REQUIRE( mon == 12 );
311 REQUIRE( day == 31 );
312 REQUIRE( hr == 0 );
313 REQUIRE( min == 0 );
314 REQUIRE( fabs( sec - 10.2357 ) < 1e-14 );
315 }
316 }
317
318 GIVEN( "an invalid ISO 8601 time string" )
319 {
320 WHEN( "string too short" )
321 {
322 int yr, mon, day, hr, min;
323 double sec;
324
325 int rv = mx::sys::ISO8601dateBreakdown( yr, mon, day, hr, min, sec, "2020-12-31" );
326
327 REQUIRE( rv == -4 );
328 }
329 }
330}
331
332/** \test Scenario: Verify conversion of an ISO 8601 time string to MJD
333 *
334 * \anchor tests_sys_timeUtils_ISO8601date2mjd
335 */
336SCENARIO( "Verify conversion of an ISO 8601 time string to MJD", "[timeutils]" )
337{
338 GIVEN( "a valid ISO 8601 time string" )
339 {
340 WHEN( "integer seconds" )
341 {
342 double mjd = mx::sys::ISO8601date2mjd( "2020-12-31T00:00:00" );
343
344 REQUIRE( mjd == 59214.0 );
345 }
346
347 WHEN( "fractional seconds" )
348 {
349 double mjd = mx::sys::ISO8601date2mjd( "2020-12-31T00:00:10.2357" );
350
351 REQUIRE( fabs( mjd - 59214.00011846875 ) < 1e-14 );
352 }
353 }
354}
void nanoSleep(unsigned nsec)
Sleep for a specified period in nanoseconds.
Definition timeUtils.cpp:66
void sleep(unsigned sec)
Sleep for a specified period in seconds.
Definition timeUtils.cpp:51
void milliSleep(unsigned msec)
Sleep for a specified period in milliseconds.
Definition timeUtils.cpp:56
void microSleep(unsigned usec)
Sleep for a specified period in microseconds.
Definition timeUtils.cpp:61
int ISO8601dateBreakdown(int &yr, int &mon, int &day, int &hr, int &min, double &sec, const std::string &fdate)
Parse an ISO8601 date of the form "YYYY-MM-DDTHH:MM:SS.S" into the individual components.
Definition timeUtils.cpp:98
void timespecAddNsec(timespec &ts, unsigned nsec)
Adds a time offset to an existing timespec.
Definition timeUtils.cpp:71
void parse_hms(floatT &h, floatT &m, floatT &s, const std::string &hmsstr)
typeT get_curr_time()
Get the current system time in seconds.
Definition timeUtils.hpp:93
double Cal2mjd(int yr, int mon, int day, int hr, int min, double sec)
Converts a Gregorian calendar date into modified Julian date (MJD).
Definition timeUtils.cpp:83
double ISO8601date2mjd(const std::string &fdate)
Parse an ISO8601 date of the form "YYYY-MM-DDTHH:MM:SS.S" and return the modified Julian date (MJD)
SCENARIO("Verify operation of get_curr_time", "[timeutils]")