test_clienthelpers.py 9.7 KB

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