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