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