test_clienthelpers.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #!/usr/bin/env python
  2. #
  3. # Test gps/clienthelpers.py
  4. #
  5. # This code runs compatibly under Python 2 and 3.x for x >= 2.
  6. # Preserve this property!
  7. """Partial test suite for gps.clienthelpers module."""
  8. from __future__ import absolute_import, print_function, division
  9. import math # for math.fabs()
  10. import os # for os.environ()
  11. import sys # for stderr, etc.
  12. import gps.clienthelpers
  13. import gps.misc
  14. debug = 0
  15. test1 = [(0, 0, " 0.00000000"), # deg_dd
  16. (0, 89.999, " 89.99900000"),
  17. (0, 90.1, " 90.10000000"),
  18. (0, 180.21, "180.21000000"),
  19. (0, 359.321, "359.32100000"),
  20. (0, 360.0, " 0.00000000"),
  21. (1, 0, " 0 00.000000'"), # deg_ddmm
  22. (1, 89.999, " 89 59.940000'"),
  23. (1, 90.1, " 90 06.000000'"),
  24. (1, 180.21, "180 12.600000'"),
  25. (1, 359.321, "359 19.260000'"),
  26. (1, 360.0, " 0 00.000000'"),
  27. (2, 0, " 0 00' 00.00000\""), # deg_ddmmss
  28. (2, 89.999, " 89 59' 56.40000\""),
  29. (2, 90.1, " 90 06' 00.00000\""),
  30. (2, 180.21, "180 12' 36.00000\""),
  31. (2, 359.321, "359 19' 15.60000\""),
  32. (2, 360.0, " 0 00' 00.00000\""),
  33. ]
  34. # maidenhead
  35. # keep in sync with tests/test_gpsdclient.c
  36. test2 = [(48.86471, 2.37305, "JN18eu", "Paris"),
  37. (41.93498, 12.43652, "JN61fw", "Rome"),
  38. (39.9771, -75.1685, "FM29jx", "Philadelphia"),
  39. (-23.4028, -50.9766, "GG46mo", "Sao Paulo"),
  40. (90, 180, "RR99xx", "North Pole"),
  41. (-90, -180, "AA00aa", "South Pole"),
  42. ]
  43. test3 = [
  44. # wgs84 separation, cm precision
  45. # online calculator:
  46. # https://geographiclib.sourceforge.io/cgi-bin/GeoidEval
  47. #
  48. # magnetic variation, hundredths of a degree precision.
  49. #
  50. # same tests as tests/test_geoid.c. Keep them in sync.
  51. #
  52. # Easter Island: EGM2008 -3.8178, EGM96 -4.9979, EGM84 -5.1408
  53. # wmm2015 2.90
  54. (27.1127, -109.3497, -31.29, 8.45, "Easter Island"),
  55. # Kalahari: EGM2008, 20.6560, EGM96, 20.8419, EGM84 23.4496
  56. # wmm2015 6.73
  57. (25.5920, 21.0937, 21.80, 3.35, "Kalahari Desert"),
  58. # Greenland: EGM2008 40.3981, EGM96 40.5912, EGM84 41.7056
  59. # wmm2015 28.26 AWEFUL!
  60. (71.7069, -42.6043, 40.11, -28.25, "Greenland"),
  61. # Kuk Swamp: EGM2008 62.8837, EGM96, 62.8002, EGM84, 64.5655
  62. # wmm2015 9.11
  63. # seems to be over a gravitational anomaly
  64. (5.7837, 144.3317, 62.34, 2.42, "Kuk Swamp PG"),
  65. # KBDN: EGM2008 -20.3509, EGM96 -19.8008, EGM84 -18.5562
  66. # wmm2015 14.61
  67. (44.094556, -121.200222, -21.95, 14.40, "Bend Airport, OR (KBDN)"),
  68. # PANC: EGM2008 7.6508, EGM96 7.8563, EGM84 8.0838
  69. # wmm2015 15.78
  70. (61.171333, -149.991164, 13.54, 15.52, "Anchorage Airport, AK (PANC)"),
  71. # KDEN: EGM2008 -18.1941, EGM96 -18.4209, EGM84 -15.9555
  72. # wmm2015 7.95
  73. (39.861666, -104.673166, -18.15, 7.84, "Denver Airport, CO (KDEN)"),
  74. # LHR: EGM2008 46.4499, EGM96 46.3061, EGM84 47.7620
  75. # wmm2015 0.17
  76. (51.46970, -0.45943, 46.26, -0.28, "London Heathrow Airport, UK (LHR)"),
  77. # SCPE: EGM2008 37.9592, EGM96 39.3400, EGM84 46.6604
  78. # wmm2015 -6.17
  79. (-22.92170, -68.158401, 35.46, -6.11,
  80. "San Pedro de Atacama Airport, CL (SCPE)"),
  81. # SIN: EGM2008 8.6453, EGM96 8.3503, EGM84 8.2509
  82. # wmm2015 0.22
  83. (1.350190, 103.994003, 7.51, 0.17, "Singapore Changi Airport, SG (SIN)"),
  84. # UURB: EGM2008 13.6322, EGM96 13.6448, EGM84 13.1280
  85. # wmm2015 11.41
  86. (55.617199, 38.06000, 13.22, 11.42, "Moscow Bykovo Airport, RU (UUBB)"),
  87. # SYD: EGM2008 13.0311, EGM96 13.3736, EGM84 13.3147
  88. # wmm2015 -4.28
  89. (33.946098, 151.177002, 13.59, -4.26, "Sydney Airport, AU (SYD)"),
  90. # Doyle: EGM2008 -23.3366, EGM96 -23.3278, EGM84 -21.1672
  91. # wmm2015 13.35
  92. (40, -120, -23.34, 13.35, "Near Doyle, CA"),
  93. # test calc at delta lat == 0
  94. # North Poll: EGM2008 14.8980, EGM96 13.6050, EGM84 13.0980
  95. # wmm2015 1.75
  96. (90, 0, 14.90, 1.75, "North Poll 0"),
  97. # wmm2015 3.75
  98. (90, 2, 14.90, 3.75, "North Poll 2"),
  99. # wmm2015 4.25
  100. (90, 2.5, 14.90, 4.25, "North Poll 2.5"),
  101. # wmm2015 1.75
  102. (90, 3, 14.90, 4.75, "North Poll 3"),
  103. # wmm2015 1.75
  104. (90, 5, 14.90, 6.75, "North Poll 5"),
  105. # wmm2015 -178.25
  106. (90, 180, 14.90, -178.25, "North Poll"),
  107. # Equator 0, EGM2008 17.2260, EGM96 17.1630, EGM84 18.3296
  108. # wmm2015 -4.84
  109. (0, 0, 17.23, -4.84, "Equator 0W"),
  110. # South Poll: EGM2008 -30.1500, EGM96 -29.5350, EGM84 -29.7120
  111. # wmm2015 -30.80
  112. (-90, 0, -30.15, -30.80, "South Poll"),
  113. # test calc at delta lon == 0
  114. # 2 0: EGM2008 17.1724, EGM96 16.8962, EGM84 17.3676
  115. # wmm2015 -4.17
  116. (2, 0, 18.42, -4.23, "2N 0W"),
  117. # 2.5 0: EGM2008 16.5384, EGM96 16.5991, EGM84 17.0643
  118. # wmm2015 -4.02
  119. (2.5, 0, 18.71, -4.08, "2.5N 0W"),
  120. # 3 0: EGM2008 16.7998, EGM96 16.6161, EGM84 16.7857
  121. # wmm2015 -3.87
  122. (3, 0, 19.01, -3.92, "3N 0W"),
  123. # 3.5 0: EGM2008 17.0646, EGM96 17.0821, EGM84 16.7220
  124. # wmm2015 -3.72
  125. (3.5, 0, 19.31, -3.77, "3.5N 0W"),
  126. # 5 0: EGM2008 20.1991, EGM96 20.4536, EGM84 20.3181
  127. # wmm2015 -3.31
  128. (5, 0, 20.20, -3.31, "5N 0W"),
  129. # test calc on diagonal
  130. # Equator 0, EGM2008 17.2260, EGM96 17.1630, EGM84 18.3296
  131. # wmm2015 -4.84
  132. # 2 2: EGM2008 16.2839, EGM96 16.1579, EGM84 17.5354
  133. # wmm2015 -3.53
  134. (2, 2, 18.39, -3.60, "2N 2E"),
  135. # 2.5 2.5: EGM2008 15.7918, EGM96 15.5314, EGM84 16.3230
  136. # wmm2015 -3.24
  137. (2.5, 2.5, 18.78, -3.30, "2.5N 2.5E"),
  138. # 3 3: EGM2008 15.2097, EGM96 15.0751, EGM84 14.6542
  139. # wmm2015 -2.95
  140. (3, 3, 19.20, -3.01, "3N 3E"),
  141. # 3.5 3.5: EGM2008 14.8706, EGM96 14.6668, EGM84 13.9592
  142. # wmm2015 -3.72
  143. (3.5, 3.5, 19.66, -2.73, "3.5N 3.5E"),
  144. # some 5x5 points, s/b exact EGM2008, +/- rounding
  145. # 5, 5: EGM2008 21.2609, EGM96 20.8917, EGM84 20.3509
  146. # wmm2015 -1.91
  147. (5, 5, 21.26, -1.91, "5, 5"),
  148. # -5, -5: EGM2008 17.1068, EGM96 16.8362, EGM84 17.5916
  149. # wmm2015 -9.03
  150. (-5, -5, 17.11, -9.03, "-5, -5"),
  151. # -5, 5: EGM2008 9.3988, EGM96 9.2399, EGM84 9.7948
  152. # wmm2015 -4.80
  153. (-5, 5, 9.40, -4.80, "-5, 5"),
  154. # 5, -5: EGM2008 25.7668, EGM96 25.6144, EGM84 25.1224
  155. # wmm2015 -4.90
  156. (5, -5, 25.77, -4.90, "5, 5"),
  157. # test data for some former corners in the code
  158. # 0, -78.452222: EGM2008 26.8978, EGM96 25.3457, EGM84 26.1507
  159. # wmm2015 -3.87
  160. (0, -78.452222, 15.98, -3.89, "Equatorial Sign Bolivia"),
  161. # 51.4778067, 0: EGM2008 45.8961, EGM96 45.7976, EGM84 47.2468
  162. # wmm2015 -0.10
  163. (51.4778067, 0, 45.46, -0.11, "Lawn Greenwich Observatory UK"),
  164. # 0, 180: EGM2008 21.2813, EGM96 21.1534, EGM84 21.7089
  165. # wmm2015 9.75
  166. (0, 180, 21.28, 9.75, "Far away from Google default"),
  167. (0, -180, 21.28, 9.75, "Away far from Google default"),
  168. ]
  169. # gpsd gpsd_units
  170. test4 = [('GPSD_UNITS', 'imperial', gps.clienthelpers.imperial),
  171. ('GPSD_UNITS', 'nautical', gps.clienthelpers.nautical),
  172. ('GPSD_UNITS', 'metric', gps.clienthelpers.metric),
  173. ('LC_MEASUREMENT', 'en_US', gps.clienthelpers.imperial),
  174. ('LC_MEASUREMENT', 'C', gps.clienthelpers.imperial),
  175. ('LC_MEASUREMENT', 'POSIX', gps.clienthelpers.imperial),
  176. ('LC_MEASUREMENT', 'ru_RU', gps.clienthelpers.metric),
  177. ('LANG', 'en_US', gps.clienthelpers.imperial),
  178. ('LANG', 'C', gps.clienthelpers.imperial),
  179. ('LANG', 'POSIX', gps.clienthelpers.imperial),
  180. ('LANG', 'ru_RU', gps.clienthelpers.metric),
  181. ]
  182. errors = 0
  183. for test in test1:
  184. (deg_type, deg, expected) = test
  185. result = gps.clienthelpers.deg_to_str(deg_type, deg)
  186. if result != expected:
  187. print("fail: deg_to_str(%d, %.3f) got %s expected %s" %
  188. (deg_type, deg, result, expected))
  189. errors += 1
  190. for (lat, lon, maidenhead, location) in test2:
  191. converted = gps.clienthelpers.maidenhead(lat, lon)
  192. if converted != maidenhead:
  193. sys.stderr.write(
  194. "fail: maidenhead test%s, %s (%s)) expected %s got %s\n" %
  195. (lat, lon, maidenhead, location, converted))
  196. errors += 1
  197. # check wgs84_separation()
  198. for (lat, lon, wgs84, var, desc) in test3:
  199. separation = gps.clienthelpers.wgs84_separation(lat, lon)
  200. # check to 1 millimeter
  201. diff = separation - wgs84
  202. if debug:
  203. print("diff %f sep %f wgs84 %f" % (diff, separation, wgs84))
  204. if 0.009 < math.fabs(diff):
  205. sys.stderr.write(
  206. "fail: wgs84_separation(%s, %s) (%s) expected %.2f got %.2f\n" %
  207. (lat, lon, desc, wgs84, separation))
  208. errors += 1
  209. # check mag_var()
  210. for (lat, lon, wgs84, var, desc) in test3:
  211. magvar = gps.clienthelpers.mag_var(lat, lon)
  212. # check to 0.1 degree
  213. diff = magvar - var
  214. if debug:
  215. print("diff %f magvar %f s/b %f" % (diff, magvar, var))
  216. if 0.09 < math.fabs(diff):
  217. sys.stderr.write(
  218. "fail: mag_var(%s, %s) (%s) expected %.2f got %.2f\n" %
  219. (lat, lon, desc, var, magvar))
  220. errors += 1
  221. savedenv = os.environ
  222. # from the python doc:
  223. # calls to unsetenv() don't update os.environ, so it is actually
  224. # preferable to delete items of os.environ.
  225. for key in ['GPSD_UNITS', 'LC_MEASUREMENT', 'LANG']:
  226. if key in os.environ:
  227. del os.environ[key]
  228. for (key, val, expected) in test4:
  229. os.environ[key] = val
  230. result = gps.clienthelpers.gpsd_units()
  231. del os.environ[key]
  232. if result != expected:
  233. print("fail: gpsd_units() %s=%s got %s expected %d" %
  234. (key, val, str(result), expected))
  235. errors += 1
  236. # restore environment
  237. os.environ = savedenv
  238. if errors:
  239. print("test_clienthelpers.py: %d tests failed" % errors)
  240. sys.exit(1)
  241. else:
  242. print("test_clienthelpers.py: OK")
  243. sys.exit(0)