Devuan fork of gpsd
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

633 lines
18 KiB

  1. /*
  2. * Unit test for timespec's
  3. *
  4. * This file is Copyright (c) 2010 by the GPSD project
  5. * SPDX-License-Identifier: BSD-2-clause
  6. *
  7. */
  8. /* first so the #defs work */
  9. #include "../gpsd_config.h"
  10. #include <math.h>
  11. #include <stdbool.h>
  12. #include <stdint.h> /* required by C99, for int32_t */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include "../gpsd.h"
  19. #include "../revision.h"
  20. #define TS_ZERO {0,0}
  21. #define TS_ZERO_ONE {0,1}
  22. #define TS_ZERO_TWO {0,2}
  23. #define TS_ZERO_TREES {0,333333333}
  24. #define TS_ZERO_SIXS7 {0,666666667}
  25. #define TS_ZERO_NINES {0,999999999}
  26. #define TS_ONE {1,0}
  27. #define TS_ONE_ONE {1,1}
  28. #define TS_TWO {2,0}
  29. #define TS_N_ZERO_ONE {0,-1}
  30. #define TS_N_ZERO_TWO {0,-2}
  31. #define TS_N_ZERO_TREES {0,-333333333}
  32. #define TS_N_ZERO_NINES {0,-999999999}
  33. #define TS_N_ONE {-1,0}
  34. /* minutes, hours, days */
  35. #define TS_ONEM {60,0} /* one minute */
  36. #define TS_ONEM_TREES {60,333333333} /* one minute, threes */
  37. #define TS_ONEM_NINES {60,999999999} /* one minute, nines */
  38. #define TS_ONEH {3600,0} /* one hour */
  39. #define TS_ONEH_TREES {3600,333333333} /* one hour, threes */
  40. #define TS_ONEH_NINES {3600,999999999} /* one hour, nines */
  41. #define TS_ONED {86400,0} /* one day */
  42. #define TS_ONED_TREES {86400,333333333} /* one day, threes */
  43. #define TS_ONED_NINES {86400,999999999} /* one day, nines */
  44. #define TS_N_ONEM {-60,0} /* negative one minute */
  45. #define TS_N_ONEH {-3600,0} /* negative one hour */
  46. #define TS_N_ONED {-86400,0} /* negative one day */
  47. /* Dec 31, 23:59 2037 GMT */
  48. #define TS_2037 {2145916799, 0}
  49. #define TS_2037_ONE {2145916799, 1}
  50. #define TS_2037_TWO {2145916799, 2}
  51. #define TS_2037_X {2145916799, 123456789}
  52. #define TS_2037_TREES {2145916799, 333333333}
  53. #define TS_2037_SIXS7 {2145916799, 666666667}
  54. #define TS_2037_NINES {2145916799, 999999999}
  55. #define TS_N_2037_TREES {-2145916799, -333333333}
  56. #define TS_N_2037_NINES {-2145916799, -999999999}
  57. /* a 32 bit copy of timespec_diff_ns() to force a 32 bit int */
  58. /* used to demonstrate how 32 bit longs can not work */
  59. #define timespec_diff_ns32(x, y) \
  60. (int32_t)((int32_t)(((x).tv_sec-(y).tv_sec)*NS_IN_SEC)+(x).tv_nsec-(y).tv_nsec)
  61. /* a 64 bit copy of timespec_diff_ns() to force a 64 bit int */
  62. /* used to demonstrate how 64 bit long longs can work */
  63. #define timespec_diff_ns64(x, y) \
  64. (int64_t)((int64_t)(((x).tv_sec-(y).tv_sec)*NS_IN_SEC)+(x).tv_nsec-(y).tv_nsec)
  65. /* convert long long ns to a timespec */
  66. #define ns_to_timespec(ts, ns) \
  67. (ts).tv_sec = ns / NS_IN_SEC; \
  68. (ts).tv_nsec = ns % NS_IN_SEC;
  69. /* convert double to a timespec */
  70. static inline void d_str( const double d, char *buf, size_t buf_size)
  71. {
  72. /* convert to string */
  73. if ( 0 <= d ) {
  74. (void) snprintf( buf, buf_size, " %.9f", d);
  75. } else {
  76. (void) snprintf( buf, buf_size, "%.9f", d);
  77. }
  78. }
  79. /* a - b should be c */
  80. struct subtract_test {
  81. struct timespec a;
  82. struct timespec b;
  83. struct timespec c;
  84. bool last; /* last test marker */
  85. };
  86. struct subtract_test subtract_tests[] = {
  87. { TS_ZERO, TS_ZERO, TS_ZERO, 0},
  88. { TS_ONE, TS_ONE, TS_ZERO, 0},
  89. { TS_ZERO_ONE, TS_ZERO_ONE, TS_ZERO, 0},
  90. { TS_ONE_ONE, TS_ONE_ONE, TS_ZERO, 0},
  91. { TS_N_ONE, TS_N_ONE, TS_ZERO, 0},
  92. { TS_N_ZERO_ONE, TS_N_ZERO_ONE, TS_ZERO, 0},
  93. { TS_ZERO_TREES, TS_ZERO_TREES, TS_ZERO, 0},
  94. { TS_ZERO_NINES, TS_ZERO_NINES, TS_ZERO, 0},
  95. { TS_ZERO_TREES, TS_ZERO, TS_ZERO_TREES, 0},
  96. { TS_ZERO, TS_N_ONE, TS_ONE, 0},
  97. { TS_ONE, TS_ZERO, TS_ONE, 0},
  98. { TS_TWO, TS_ONE, TS_ONE, 0},
  99. { TS_ONE_ONE, TS_ONE, TS_ZERO_ONE, 0},
  100. { TS_ONE, TS_ZERO_TREES, TS_ZERO_SIXS7, 0},
  101. { TS_ONE, TS_ZERO_NINES, TS_ZERO_ONE, 0},
  102. { TS_ZERO_TWO, TS_ZERO_ONE, TS_ZERO_ONE, 0},
  103. { TS_2037_ONE, TS_2037, TS_ZERO_ONE, 0},
  104. { TS_ONE_ONE, TS_ZERO_NINES, TS_ZERO_TWO, 0},
  105. { TS_ONEM, TS_ZERO, TS_ONEM, 0},
  106. { TS_ONEM_TREES, TS_ZERO, TS_ONEM_TREES, 0},
  107. { TS_ONEM_NINES, TS_ZERO, TS_ONEM_NINES, 0},
  108. { TS_ZERO, TS_ONEM, TS_N_ONEM, 0},
  109. { TS_ONEH, TS_ZERO, TS_ONEH, 0},
  110. { TS_ONEH_TREES, TS_ZERO, TS_ONEH_TREES, 0},
  111. { TS_ONEH_NINES, TS_ZERO, TS_ONEH_NINES, 0},
  112. { TS_ZERO, TS_ONEH, TS_N_ONEH, 0},
  113. { TS_ONED, TS_ZERO, TS_ONED, 0},
  114. { TS_ONED_TREES, TS_ZERO, TS_ONED_TREES, 0},
  115. { TS_ONED_NINES, TS_ZERO, TS_ONED_NINES, 0},
  116. { TS_ZERO, TS_ONED, TS_N_ONED, 0},
  117. { TS_2037_NINES, TS_2037, TS_ZERO_NINES, 0},
  118. { TS_2037_TREES, TS_ZERO, TS_2037_TREES, 0},
  119. { TS_2037_SIXS7, TS_2037, TS_ZERO_SIXS7, 0},
  120. { TS_2037_TREES, TS_2037, TS_ZERO_TREES, 0},
  121. { TS_2037_NINES, TS_ZERO, TS_2037_NINES, 0},
  122. { TS_ZERO, TS_ONE, TS_N_ONE, 0},
  123. { TS_ONE, TS_TWO, TS_N_ONE, 0},
  124. { TS_ZERO, TS_ZERO_ONE, TS_N_ZERO_ONE, 0},
  125. { TS_ONE, TS_ONE_ONE, TS_N_ZERO_ONE, 0},
  126. { TS_ZERO_ONE, TS_ZERO_TWO, TS_N_ZERO_ONE, 0},
  127. { TS_2037, TS_2037_ONE, TS_N_ZERO_ONE, 0},
  128. { TS_ZERO_NINES, TS_ONE_ONE, TS_N_ZERO_TWO, 0},
  129. { TS_2037, TS_2037_NINES, TS_N_ZERO_NINES, 0},
  130. { TS_ZERO, TS_2037_NINES, TS_N_2037_NINES, 1},
  131. };
  132. typedef struct format_test {
  133. struct timespec input;
  134. char *expected;
  135. bool last;
  136. } format_test_t;
  137. struct format_test format_tests[] = {
  138. { TS_ZERO, " 0.000000000", 0},
  139. { TS_ZERO_ONE, " 0.000000001", 0},
  140. { TS_ZERO_TWO, " 0.000000002", 0},
  141. { TS_ZERO_NINES, " 0.999999999", 0},
  142. { TS_ONE, " 1.000000000", 0},
  143. { TS_ONE_ONE, " 1.000000001", 0},
  144. { TS_TWO, " 2.000000000", 0},
  145. { TS_N_ZERO_ONE, "-0.000000001", 0},
  146. { TS_N_ZERO_TWO, "-0.000000002", 0},
  147. { TS_N_ZERO_NINES, "-0.999999999", 0},
  148. { TS_N_ONE, "-1.000000000", 0},
  149. { TS_ONEM, " 60.000000000", 0},
  150. { TS_ONEM_TREES, " 60.333333333", 0},
  151. { TS_ONEH, " 3600.000000000", 0},
  152. { TS_ONEH_TREES, " 3600.333333333", 0},
  153. { TS_ONED, " 86400.000000000", 0},
  154. { TS_ONED_TREES, " 86400.333333333", 0},
  155. { TS_N_ONEM, "-60.000000000", 0},
  156. { TS_N_ONEH, "-3600.000000000", 0},
  157. { TS_N_ONED, "-86400.000000000", 0},
  158. { { -1, 1}, "-1.000000001", 0},
  159. { { -1, -1}, "-1.000000001", 0},
  160. { TS_2037, " 2145916799.000000000", 0},
  161. { TS_2037_ONE, " 2145916799.000000001", 0},
  162. { TS_2037_TREES, " 2145916799.333333333", 1},
  163. { TS_2037_NINES, " 2145916799.999999999", 1},
  164. };
  165. /*
  166. * test subtractions using native timespec math: TS_SUB()
  167. *
  168. */
  169. static int test_ts_subtract( int verbose )
  170. {
  171. struct subtract_test *p = subtract_tests;
  172. int fail_count = 0;
  173. while ( 1 ) {
  174. char buf_a[TIMESPEC_LEN];
  175. char buf_b[TIMESPEC_LEN];
  176. char buf_c[TIMESPEC_LEN];
  177. char buf_r[TIMESPEC_LEN];
  178. struct timespec r;
  179. TS_SUB(&r, &p->a, &p->b);
  180. timespec_str( &p->a, buf_a, sizeof(buf_a) );
  181. timespec_str( &p->b, buf_b, sizeof(buf_b) );
  182. timespec_str( &p->c, buf_c, sizeof(buf_c) );
  183. timespec_str( &r, buf_r, sizeof(buf_r) );
  184. if ( (p->c.tv_sec != r.tv_sec) || (p->c.tv_nsec != r.tv_nsec) ) {
  185. printf("%21s - %21s = %21s, FAIL s/b %21s\n",
  186. buf_a, buf_b, buf_r, buf_c);
  187. fail_count++;
  188. } else if ( verbose ) {
  189. printf("%21s - %21s = %21s\n", buf_a, buf_b, buf_r);
  190. }
  191. if ( p->last ) {
  192. break;
  193. }
  194. p++;
  195. };
  196. if ( fail_count ) {
  197. printf("timespec subtract test failed %d tests\n", fail_count );
  198. } else {
  199. puts("timespec subtract test succeeded\n");
  200. }
  201. return fail_count;
  202. }
  203. /*
  204. * test subtractions using timespec_diff_ns()
  205. *
  206. */
  207. static int test_ns_subtract( int verbose )
  208. {
  209. struct subtract_test *p = subtract_tests;
  210. int fail_count = 0;
  211. while ( 1 ) {
  212. char buf_a[TIMESPEC_LEN];
  213. char buf_b[TIMESPEC_LEN];
  214. char buf_c[TIMESPEC_LEN];
  215. char buf_r[TIMESPEC_LEN];
  216. struct timespec r;
  217. long long r_ns;
  218. r_ns = timespec_diff_ns(p->a, p->b);
  219. timespec_str( &p->a, buf_a, sizeof(buf_a) );
  220. timespec_str( &p->b, buf_b, sizeof(buf_b) );
  221. timespec_str( &p->c, buf_c, sizeof(buf_c) );
  222. ns_to_timespec( r, r_ns);
  223. timespec_str( &r, buf_r, sizeof(buf_r) );
  224. if ( (p->c.tv_sec != r.tv_sec) || (p->c.tv_nsec != r.tv_nsec) ) {
  225. printf("%21s - %21s = %21s, FAIL s/b %21s\n",
  226. buf_a, buf_b, buf_r, buf_c);
  227. fail_count++;
  228. } else if ( verbose ) {
  229. printf("%21s - %21s = %21s\n", buf_a, buf_b, buf_r);
  230. }
  231. if ( p->last ) {
  232. break;
  233. }
  234. p++;
  235. };
  236. if ( fail_count ) {
  237. printf("ns subtract test failed %d tests\n", fail_count );
  238. } else {
  239. puts("ns subtract test succeeded\n");
  240. }
  241. return fail_count;
  242. }
  243. static int test_format(int verbose )
  244. {
  245. format_test_t *p = format_tests;
  246. int fail_count = 0;
  247. while ( 1 ) {
  248. char buf[TIMESPEC_LEN];
  249. int fail;
  250. timespec_str( &p->input, buf, sizeof(buf) );
  251. fail = strncmp( buf, p->expected, TIMESPEC_LEN);
  252. if ( fail ) {
  253. printf("%21s, FAIL s/b: %21s\n", buf, p->expected);
  254. fail_count++;
  255. } else if ( verbose ) {
  256. printf("%21s\n", buf);
  257. }
  258. if ( p->last ) {
  259. break;
  260. }
  261. p++;
  262. };
  263. if ( fail_count ) {
  264. printf("timespec_str test failed %d tests\n", fail_count );
  265. } else {
  266. puts("timespec_str test succeeded\n");
  267. }
  268. return fail_count;
  269. }
  270. typedef struct {
  271. unsigned short week;
  272. int leap_seconds;
  273. timespec_t ts_tow;
  274. timespec_t ts_exp; // expected result
  275. char *exp_s; // expected string
  276. bool last;
  277. } gpstime_test_t;
  278. gpstime_test_t gpstime_tests[] = {
  279. // GPS time zero
  280. {0, 0, TS_ZERO, {315964800, 000000000}, "1980-01-06T00:00:00.000Z", 0},
  281. // GPS first roll over
  282. {1024, 7, TS_ZERO, {935279993, 000000000}, "1999-08-21T23:59:53.000Z", 0},
  283. // GPS first roll over
  284. {2048, 18, TS_ZERO, {1554595182, 000000000}, "2019-04-06T23:59:42.000Z", 0},
  285. {2076, 18, {239910, 100000000}, {1571769492, 100000000},
  286. "2019-10-22T18:38:12.100Z", 1},
  287. };
  288. static int test_gpsd_gpstime_resolv(int verbose)
  289. {
  290. char res_s[128];
  291. char buf[20];
  292. int fail_count = 0;
  293. struct gps_device_t session;
  294. struct gps_context_t context;
  295. timespec_t ts_res;
  296. gpstime_test_t *p = gpstime_tests;
  297. memset(&session, 0, sizeof(session));
  298. memset(&context, 0, sizeof(context));
  299. session.context = &context;
  300. context.errout.debug = 0; // a handle to change debug level
  301. while ( 1 ) {
  302. /* setup preconditions */
  303. context.gps_week = p->week;
  304. context.leap_seconds = p->leap_seconds;
  305. ts_res = gpsd_gpstime_resolv(&session, p->week, p->ts_tow);
  306. (void)timespec_to_iso8601(ts_res, res_s, sizeof(res_s));
  307. if (p->ts_exp.tv_sec != ts_res.tv_sec ||
  308. p->ts_exp.tv_nsec != ts_res.tv_nsec ||
  309. strcmp(res_s, p->exp_s) ) {
  310. // long long for 32-bit OS
  311. printf("FAIL %s s/b: %s\n"
  312. " %s s/b %s\n",
  313. timespec_str(&ts_res, buf, sizeof(buf)),
  314. timespec_str(&p->ts_exp, buf, sizeof(buf)),
  315. res_s, p->exp_s);
  316. fail_count++;
  317. } else if ( verbose ) {
  318. printf("%s (%s)\n",
  319. timespec_str(&p->ts_exp, buf, sizeof(buf)),
  320. p->exp_s);
  321. }
  322. if ( p->last ) {
  323. break;
  324. }
  325. p++;
  326. }
  327. if ( fail_count ) {
  328. printf("test_gpsd_gpstime_resolv test failed %d tests\n", fail_count );
  329. } else {
  330. puts("test_gpsd_gpstime_resolv test succeeded\n");
  331. }
  332. return fail_count;
  333. }
  334. static int ex_subtract_float(void)
  335. {
  336. struct subtract_test *p = subtract_tests;
  337. int fail_count = 0;
  338. printf( "\n\nsubtract test examples using doubles,floats,longs:\n"
  339. " ts: TS_SUB()\n"
  340. " l: timespec_to_ns() math\n"
  341. " l32: timespec_to_ns() math with 32 bit long\n"
  342. " l64: timespec_to_ns() math with 64 bit long\n"
  343. " f: float math\n"
  344. " d: double float math\n"
  345. "\n");
  346. while ( 1 ) {
  347. char buf_a[TIMESPEC_LEN];
  348. char buf_b[TIMESPEC_LEN];
  349. char buf_c[TIMESPEC_LEN];
  350. char buf_r[TIMESPEC_LEN];
  351. char buf_l[TIMESPEC_LEN];
  352. char buf_l32[TIMESPEC_LEN];
  353. char buf_l64[TIMESPEC_LEN];
  354. char buf_f[TIMESPEC_LEN];
  355. char buf_d[TIMESPEC_LEN];
  356. struct timespec ts_r;
  357. struct timespec ts_l;
  358. struct timespec ts_l32;
  359. struct timespec ts_l64;
  360. float f_a, f_b, f_r;
  361. double d_a, d_b, d_r;
  362. long long l;
  363. int32_t l32; /* simulate a 32 bit long */
  364. int64_t l64; /* simulate a 64 bit long */
  365. const char *fail_ts = "";
  366. const char *fail_l = "";
  367. const char *fail_l32 = "";
  368. const char *fail_l64 = "";
  369. const char *fail_f = "";
  370. const char *fail_d = "";
  371. /* timespec math */
  372. TS_SUB(&ts_r, &p->a, &p->b);
  373. /* float math */
  374. f_a = TSTONS( &p->a );
  375. f_b = TSTONS( &p->b );
  376. f_r = f_a - f_b;
  377. /* double float math */
  378. d_a = TSTONS( &p->a );
  379. d_b = TSTONS( &p->b );
  380. d_r = d_a - d_b;
  381. /* long math */
  382. l = timespec_diff_ns( p->a, p->b);
  383. l32 = timespec_diff_ns32( p->a, p->b);
  384. l64 = timespec_diff_ns64( p->a, p->b);
  385. /* now convert to strings */
  386. timespec_str( &p->a, buf_a, sizeof(buf_a) );
  387. timespec_str( &p->b, buf_b, sizeof(buf_b) );
  388. timespec_str( &p->c, buf_c, sizeof(buf_c) );
  389. timespec_str( &ts_r, buf_r, sizeof(buf_r) );
  390. ns_to_timespec( ts_l, l );
  391. timespec_str( &ts_l, buf_l, sizeof(buf_l) );
  392. ns_to_timespec( ts_l32, l32 );
  393. timespec_str( &ts_l32, buf_l32, sizeof(buf_l32) );
  394. ns_to_timespec( ts_l64, l64);
  395. timespec_str( &ts_l64, buf_l64, sizeof(buf_l64) );
  396. d_str( f_r, buf_f, sizeof(buf_f) );
  397. d_str( d_r, buf_d, sizeof(buf_d) );
  398. /* test strings */
  399. if ( strcmp( buf_r, buf_c) ) {
  400. fail_ts = "FAIL";
  401. fail_count++;
  402. }
  403. if ( strcmp( buf_l, buf_c) ) {
  404. fail_l = "FAIL";
  405. fail_count++;
  406. }
  407. if ( strcmp( buf_l32, buf_c) ) {
  408. fail_l32 = "FAIL";
  409. fail_count++;
  410. }
  411. if ( strcmp( buf_l64, buf_c) ) {
  412. fail_l64 = "FAIL";
  413. fail_count++;
  414. }
  415. if ( strcmp( buf_f, buf_c) ) {
  416. fail_f = "FAIL";
  417. fail_count++;
  418. }
  419. if ( strcmp( buf_d, buf_c) ) {
  420. fail_d = "FAIL";
  421. fail_count++;
  422. }
  423. printf("ts: %21s - %21s = %21s %s\n"
  424. "l; %21s - %21s = %21lld %s\n"
  425. "l32; %21s - %21s = %21lld %s\n"
  426. "l64; %21s - %21s = %21lld %s\n"
  427. "f; %21.9f - %21.9f = %21.9f %s\n"
  428. "d; %21.9f - %21.9f = %21.9f %s\n"
  429. "\n",
  430. buf_a, buf_b, buf_r, fail_ts,
  431. buf_a, buf_b, l, fail_l,
  432. buf_a, buf_b, (long long)l32, fail_l32,
  433. buf_a, buf_b, (long long)l64, fail_l64,
  434. f_a, f_b, f_r, fail_f,
  435. d_a, d_b, d_r, fail_d);
  436. if ( p->last ) {
  437. break;
  438. }
  439. p++;
  440. };
  441. if ( fail_count ) {
  442. printf("subtract test failed %d tests\n", fail_count );
  443. } else {
  444. puts("subtract test succeeded\n");
  445. }
  446. return fail_count;
  447. }
  448. /*
  449. * show examples of how integers and floats fail
  450. *
  451. */
  452. static void ex_precision(void)
  453. {
  454. format_test_t *p = format_tests;
  455. puts( "\n\n Simple conversion examples\n\n"
  456. "ts: timespec\n"
  457. "l32: 32 bit long\n"
  458. "l64: 64 bit long\n"
  459. "f: float\n"
  460. "d: double\n\n");
  461. while ( 1 ) {
  462. float f;
  463. double d;
  464. int32_t l32;
  465. int64_t l64;
  466. char buf_ts[TIMESPEC_LEN];
  467. char buf_l32[TIMESPEC_LEN];
  468. char buf_l64[TIMESPEC_LEN];
  469. char buf_f[TIMESPEC_LEN];
  470. char buf_d[TIMESPEC_LEN];
  471. const char *fail_ts = "";
  472. const char *fail_l32 = "";
  473. const char *fail_l64 = "";
  474. const char *fail_f = "";
  475. const char *fail_d = "";
  476. struct timespec *v = &(p->input);
  477. struct timespec ts_l32;
  478. struct timespec ts_l64;
  479. /* convert to test size */
  480. l32 = (int32_t)(v->tv_sec * NS_IN_SEC)+(int32_t)v->tv_nsec;
  481. l64 = (int64_t)(v->tv_sec * NS_IN_SEC)+(int64_t)v->tv_nsec;
  482. f = (float)TSTONS( v );
  483. d = TSTONS( v );
  484. /* now convert to strings */
  485. timespec_str( v, buf_ts, sizeof(buf_ts) );
  486. ns_to_timespec( ts_l32, l32);
  487. timespec_str( &ts_l32, buf_l32, sizeof(buf_l32) );
  488. ns_to_timespec( ts_l64, l64);
  489. timespec_str( &ts_l64, buf_l64, sizeof(buf_l64) );
  490. d_str( f, buf_f, sizeof(buf_f) );
  491. d_str( d, buf_d, sizeof(buf_d) );
  492. /* test strings */
  493. if ( strcmp( buf_ts, p->expected) ) {
  494. fail_ts = "FAIL";
  495. }
  496. if ( strcmp( buf_l32, p->expected) ) {
  497. fail_l32 = "FAIL";
  498. }
  499. if ( strcmp( buf_l64, p->expected) ) {
  500. fail_l64 = "FAIL";
  501. }
  502. if ( strcmp( buf_f, p->expected) ) {
  503. fail_f = "FAIL";
  504. }
  505. if ( strcmp( buf_d, p->expected) ) {
  506. fail_d = "FAIL";
  507. }
  508. printf( "ts: %21s %s\n"
  509. "l32: %21lld %s\n"
  510. "l64: %21lld %s\n"
  511. "f: %21.9f %s\n"
  512. "d: %21.9f %s\n\n",
  513. buf_ts, fail_ts,
  514. (long long)l32, fail_l32,
  515. (long long)l64, fail_l64,
  516. f, fail_f,
  517. d, fail_d);
  518. if ( p->last ) {
  519. break;
  520. }
  521. p++;
  522. }
  523. printf( "\n\nSubtraction examples:\n");
  524. ex_subtract_float();
  525. }
  526. int main(int argc, char *argv[])
  527. {
  528. int fail_count = 0;
  529. int verbose = 0;
  530. int option;
  531. while ((option = getopt(argc, argv, "h?vV")) != -1) {
  532. switch (option) {
  533. default:
  534. fail_count = 1;
  535. /* FALL THROUGH! */
  536. case '?':
  537. case 'h':
  538. (void)fputs("usage: test_timespec [-v] [-V]\n", stderr);
  539. exit(fail_count);
  540. case 'V':
  541. (void)fprintf( stderr, "test_timespec %s\n",
  542. VERSION);
  543. exit(EXIT_SUCCESS);
  544. case 'v':
  545. verbose = 1;
  546. break;
  547. }
  548. }
  549. fail_count = test_format(verbose );
  550. fail_count += test_ts_subtract(verbose );
  551. fail_count += test_ns_subtract(verbose );
  552. fail_count += test_gpsd_gpstime_resolv(verbose );
  553. if ( fail_count ) {
  554. printf("timespec tests failed %d tests\n", fail_count );
  555. exit(1);
  556. }
  557. printf("timespec tests succeeded\n");
  558. if ( verbose ) {
  559. ex_precision();
  560. }
  561. exit(0);
  562. }