test_gpsdclient.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /* test for gpsdclient.c: function deg_to_str
  2. *
  3. * Consider rounding off also:
  4. * dsec = (int)(fdsec * 10000.0 + 0.5);
  5. *
  6. * This file is Copyright (c) 2010 by the GPSD project
  7. * SPDX-License-Identifier: BSD-2-clause
  8. */
  9. /* first so the #defs work */
  10. #include "../gpsd_config.h"
  11. #include <math.h> /* for nan() */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <unistd.h> /* for getopt() */
  16. #include "../gpsdclient.h"
  17. #include "../revision.h"
  18. struct test {
  19. double deg;
  20. char dd[20];
  21. char dd2[20];
  22. char ddmm[20];
  23. char ddmm2[20];
  24. char ddmmss[20];
  25. char ddmmss2[20];
  26. };
  27. #define NANFLAG 9999
  28. struct test tests[] = {
  29. /* 1.999999995 sec */
  30. {(1.999999995),
  31. " 2.00000000", /* rounded up */
  32. " 2.00000000 E", /* rounded up */
  33. " 2 00.000000'", /* rounded up */
  34. " 2 00.000000' E", /* rounded up */
  35. " 1 59' 59.99998\"",
  36. " 1 59' 59.99998\" N"},
  37. /* 3.999999999 sec */
  38. {(3.999999994),
  39. " 3.99999999", /* not rounded up */
  40. " 3.99999999 E", /* not rounded up */
  41. " 4 00.000000'", /* rounded up */
  42. " 4 00.000000' E", /* rounded up */
  43. " 3 59' 59.99998\"",
  44. " 3 59' 59.99998\" N"},
  45. /* 5 degree, 1.99999960 arcmin */
  46. {(5.0 + 1.999999600/60.0),
  47. " 5.03333333",
  48. " 5.03333333 E",
  49. " 5 02.000000'", /* rounded up */
  50. " 5 02.000000' E", /* rounded up */
  51. " 5 01' 59.99998\"",
  52. " 5 01' 59.99998\" N"},
  53. /* 6 degree, 1.99999940 arcmin */
  54. {(6.0 + 1.999999400/60.0),
  55. " 6.03333332",
  56. " 6.03333332 E",
  57. " 6 01.999999'", /* not rounded up */
  58. " 6 01.999999' E", /* not rounded up */
  59. " 6 01' 59.99996\"",
  60. " 6 01' 59.99996\" N"},
  61. /* 7 degree, 59.99999960 arcmin */
  62. {(7.0 + 59.999999600/60.0),
  63. " 7.99999999",
  64. " 7.99999999 E",
  65. " 8 00.000000'", /* rounded up */
  66. " 8 00.000000' E", /* rounded up */
  67. " 7 59' 59.99998\"",
  68. " 7 59' 59.99998\" N"},
  69. /* 9 degree, 59.99999940 arcmin */
  70. {(9.0 + 59.999999400/60.0),
  71. " 9.99999999",
  72. " 9.99999999 E",
  73. " 9 59.999999'", /* not rounded up */
  74. " 9 59.999999' E", /* not rounded up */
  75. " 9 59' 59.99996\"",
  76. " 9 59' 59.99996\" N"},
  77. /* 11 degree, 1 arcminute, 1.99999600 arcsec */
  78. {(11.0 + 1.0/60.0 + 1.99999600/3600.0),
  79. " 11.01722222",
  80. " 11.01722222 E",
  81. " 11 01.033333'",
  82. " 11 01.033333' E",
  83. " 11 01' 02.00000\"", /* rounded up */
  84. " 11 01' 02.00000\" N"}, /* rounded up */
  85. /* 12 deg, 2 min, 2.99999400 sec */
  86. {(12.0 + 2.0/60.0 + 2.99999400/3600.0),
  87. " 12.03416667",
  88. " 12.03416667 E",
  89. " 12 02.050000'",
  90. " 12 02.050000' E",
  91. " 12 02' 02.99999\"", /* not rounded up */
  92. " 12 02' 02.99999\" N"}, /* not rounded up */
  93. /* 13.00000001 sec, LSB of dd */
  94. {-13.00000001,
  95. " 13.00000001",
  96. " 13.00000001 W",
  97. " 13 00.000001'",
  98. " 13 00.000001' W",
  99. " 13 00' 00.00004\"",
  100. " 13 00' 00.00004\" S"},
  101. /* 14 deg, 0.000001 min, LSB of ddmm */
  102. {(14.0 + 0.000001/60.0),
  103. " 14.00000002",
  104. " 14.00000002 E",
  105. " 14 00.000001'",
  106. " 14 00.000001' E",
  107. " 14 00' 00.00006\"",
  108. " 14 00' 00.00006\" N"},
  109. /* 15 deg, 2 min, 2.00001 sec, LSB of ddmmss */
  110. {(15.0 + 2.0/60.0 + 2.00001/3600.0),
  111. " 15.03388889",
  112. " 15.03388889 E",
  113. " 15 02.033334'",
  114. " 15 02.033334' E",
  115. " 15 02' 02.00001\"",
  116. " 15 02' 02.00001\" N"},
  117. /* -44.99999999999 */
  118. /* fabs() */
  119. {-44.0,
  120. " 44.00000000",
  121. " 44.00000000 W",
  122. " 44 00.000000'",
  123. " 44 00.000000' W",
  124. " 44 00' 00.00000\"",
  125. " 44 00' 00.00000\" S"},
  126. /* 359.99999999999 */
  127. {359.99999999999,
  128. " 0.00000000", /* rounded up, and rolled over */
  129. " 0.00000000 E", /* rounded up, and rolled over */
  130. " 0 00.000000'",
  131. " 0 00.000000' E",
  132. " 0 00' 00.00000\"",
  133. " 0 00' 00.00000\" N"},
  134. /* 361 */
  135. /* nan because out of range */
  136. {361,
  137. "n/a",
  138. "n/a",
  139. "n/a",
  140. "n/a",
  141. "n/a",
  142. "n/a"},
  143. /* -361 */
  144. /* nan, just because */
  145. {NANFLAG,
  146. "n/a",
  147. "n/a",
  148. "n/a",
  149. "n/a",
  150. "n/a",
  151. "n/a"},
  152. /* FP_INFINITE */
  153. /* gcc too 'smart' to let us put a Nan here */
  154. {9999,
  155. "n/a",
  156. "n/a",
  157. "n/a",
  158. "n/a",
  159. "n/a",
  160. "n/a"},
  161. };
  162. struct test2 {
  163. double lat;
  164. double lon;
  165. char *maidenhead;
  166. char *name;
  167. };
  168. struct test2 tests2[] = {
  169. /* maidenhead
  170. * keep in sync with test_clienthelpers.py */
  171. {48.86471, 2.37305, "JN18eu", "Paris"},
  172. {41.93498, 12.43652, "JN61fw", "Rome"},
  173. {39.9771, -75.1685, "FM29jx", "Philadelphia"},
  174. {-23.4028, -50.9766, "GG46mo", "Sao Paulo"},
  175. {90, 180, "RR99xx", "North Pole"},
  176. {-90, -180, "AA00aa", "South Pole"},
  177. };
  178. int main(int argc, char **argv)
  179. {
  180. char buf[20];
  181. char *s;
  182. unsigned int i;
  183. int verbose = 0;
  184. int fail_count = 0;
  185. int option;
  186. while ((option = getopt(argc, argv, "h?vV")) != -1) {
  187. switch (option) {
  188. default:
  189. fail_count = 1;
  190. /* FALLTHROUGH */
  191. case '?':
  192. /* FALLTHROUGH */
  193. case 'h':
  194. (void)fputs("usage: test_gpsdclient [-v] [-V]\n", stderr);
  195. exit(fail_count);
  196. case 'V':
  197. (void)fprintf( stderr, "test_gpsdclient %s\n",
  198. VERSION);
  199. exit(EXIT_SUCCESS);
  200. case 'v':
  201. verbose = 1;
  202. break;
  203. }
  204. }
  205. for (i = 0; i < (sizeof(tests)/sizeof(struct test)); i++) {
  206. if (NANFLAG == tests[i].deg) {
  207. /* make it a NaN */
  208. tests[i].deg = nan("a");
  209. }
  210. s = deg_to_str(deg_dd, tests[i].deg);
  211. if (0 != strcmp(s, tests[i].dd)) {
  212. printf("ERROR: %s s/b %s\n", s, tests[i].dd);
  213. fail_count++;
  214. } else if (0 < verbose) {
  215. printf("%s s/b %s\n", s, tests[i].dd);
  216. }
  217. s = deg_to_str2(deg_dd, tests[i].deg, buf,
  218. sizeof(buf), " E", " W");
  219. if (0 != strcmp(s, tests[i].dd2)) {
  220. printf("ERROR: %s s/b %s\n", s, tests[i].dd2);
  221. fail_count++;
  222. } else if (0 < verbose) {
  223. printf("%s s/b %s\n", s, tests[i].dd2);
  224. }
  225. s = deg_to_str(deg_ddmm, tests[i].deg);
  226. if (0 != strcmp(s, tests[i].ddmm)) {
  227. printf("ERROR: %s s/b %s\n", s, tests[i].ddmm);
  228. fail_count++;
  229. } else if (0 < verbose) {
  230. printf("%s s/b %s\n", s, tests[i].ddmm);
  231. }
  232. s = deg_to_str2(deg_ddmm, tests[i].deg, buf,
  233. sizeof(buf), " E", " W");
  234. if (0 != strcmp(s, tests[i].ddmm2)) {
  235. printf("ERROR: %s s/b %s\n", s, tests[i].ddmm2);
  236. fail_count++;
  237. } else if (0 < verbose) {
  238. printf("%s s/b %s\n", s, tests[i].ddmm2);
  239. }
  240. s = deg_to_str(deg_ddmmss, tests[i].deg);
  241. if (0 != strcmp(s, tests[i].ddmmss)) {
  242. printf("ERROR: %s s/b %s\n", s, tests[i].ddmmss);
  243. fail_count++;
  244. } else if (0 < verbose) {
  245. printf("%s s/b %s\n", s, tests[i].ddmmss);
  246. }
  247. s = deg_to_str2(deg_ddmmss, tests[i].deg, buf,
  248. sizeof(buf), " N", " S");
  249. if (0 != strcmp(s, tests[i].ddmmss2)) {
  250. printf("ERROR: %s s/b %s\n", s, tests[i].ddmmss2);
  251. fail_count++;
  252. } else if (0 < verbose) {
  253. printf("%s s/b %s\n", s, tests[i].ddmmss2);
  254. }
  255. }
  256. for (i = 0; i < (sizeof(tests2)/sizeof(struct test2)); i++) {
  257. s = maidenhead(tests2[i].lat, tests2[i].lon);
  258. if (0 != strcmp(s, tests2[i].maidenhead)) {
  259. printf("ERROR: %s s/b %s\n", s, tests2[i].maidenhead);
  260. fail_count++;
  261. } else if (0 < verbose) {
  262. printf("%s s/b %s\n", s, tests2[i].maidenhead);
  263. }
  264. }
  265. exit(fail_count);
  266. }