test_json.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. /* json.c - unit test for JSON parsing into fixed-extent structures
  2. *
  3. * This file is Copyright 2010 by the GPSD project
  4. * SPDX-License-Identifier: BSD-2-clause
  5. */
  6. #include "../include/gpsd_config.h"
  7. #include <getopt.h>
  8. #include <stddef.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <time.h> // for struct timespec
  13. #include "../include/gpsd.h"
  14. #include "../include/gps_json.h"
  15. // Note: JSON_MINIMAL no longer exists
  16. static int debug = 0;
  17. static int current_test = 0;
  18. static void assert_case(int status)
  19. {
  20. if (status != 0) {
  21. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  22. (void)fprintf(stderr, "status %d (%s).\n",
  23. status, json_error_string(status));
  24. exit(EXIT_FAILURE);
  25. }
  26. }
  27. static void assert_string(char *attr, char *fld, char *val)
  28. {
  29. if (strcmp(fld, val)) {
  30. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  31. (void)fprintf(stderr,
  32. "'%s' string attribute eval failed, value = %s.\n",
  33. attr, fld);
  34. exit(EXIT_FAILURE);
  35. }
  36. }
  37. static void assert_string1(char *desc, char *got, char *sb)
  38. {
  39. if (2 < debug) {
  40. (void)fprintf(stderr, "test string: >%s<\n", sb);
  41. }
  42. if (strcmp(got, sb)) {
  43. (void)fprintf(stderr, "case %d/%s FAILED\n", current_test, desc);
  44. (void)fprintf(stderr, "got = >%s<, s/b >%s<\n", got, sb);
  45. exit(EXIT_FAILURE);
  46. }
  47. }
  48. static void assert_int(const char *attr, const char *type, long fld, long val)
  49. {
  50. if (fld != val) {
  51. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  52. (void)fprintf(stderr,
  53. "'%s' %s eval failed, value = %ld s/b %ld.\n",
  54. attr, type, fld, val);
  55. exit(EXIT_FAILURE);
  56. }
  57. }
  58. static void assert_uint(const char *attr, const char *type, unsigned long fld,
  59. unsigned long val)
  60. {
  61. if (fld != val) {
  62. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  63. (void)fprintf(stderr,
  64. "'%s' %s eval failed, value = %lu s/b %lu.\n",
  65. attr, type, fld, val);
  66. exit(EXIT_FAILURE);
  67. }
  68. }
  69. static void assert_boolean(char *attr, bool fld, bool val)
  70. {
  71. if (fld != val) {
  72. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  73. (void)fprintf(stderr,
  74. "'%s' boolean attribute eval failed, value = %s.\n",
  75. attr, fld ? "true" : "false");
  76. exit(EXIT_FAILURE);
  77. }
  78. }
  79. static void assert_ts(const char *attr, struct timespec fld,
  80. struct timespec val)
  81. {
  82. if (fld.tv_sec != val.tv_sec ||
  83. fld.tv_nsec != val.tv_nsec) {
  84. (void)fprintf(stderr,"case %d FAILED\n"
  85. " '%s' timespec eval failed, value = %lld %ld s/b "
  86. "%lld %ld.\n",
  87. current_test, attr,
  88. (long long)fld.tv_sec, fld.tv_nsec,
  89. (long long)val.tv_sec, val.tv_nsec);
  90. exit(EXIT_FAILURE);
  91. }
  92. }
  93. static void assert_other(char *desc, int val, int val1)
  94. {
  95. if (val != val1) {
  96. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  97. (void)fprintf(stderr, "'%s' was %d, s/b %d\n", desc, val, val1);
  98. exit(EXIT_FAILURE);
  99. }
  100. }
  101. /*
  102. * Floating point comparisons are iffy, but at least if any of these fail
  103. * the output will make it clear whether it was a precision issue
  104. */
  105. static void assert_real(char *attr, double fld, double val)
  106. {
  107. if (fld != val) {
  108. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  109. (void)fprintf(stderr,
  110. "'%s' real attribute eval failed, value = %f.\n", attr,
  111. fld);
  112. exit(EXIT_FAILURE);
  113. }
  114. }
  115. static struct gps_data_t gpsdata;
  116. /* Case 1: TPV report */
  117. /* *INDENT-OFF* */
  118. static const char json_str1[] =
  119. "{\"class\":\"TPV\","
  120. "\"device\":\"GPS#1\",\"time\":\"2005-06-19T08:12:41.89Z\","
  121. "\"lon\":46.498203637,\"lat\":7.568074350,\"altHAE\":1327.780,"
  122. "\"epx\":21.000,\"epy\":23.000,\"epv\":124.484,\"mode\":3}";
  123. /*
  124. * Case 2: SKY report
  125. *
  126. * The fields of the last satellite entry are arranged in the reverse order
  127. * of the structure fields, in order to test for field overflow.
  128. */
  129. static const char *json_str2 = "{\"class\":\"SKY\",\
  130. \"time\":\"2005-06-19T12:12:42.03Z\",\"nSat\":6, \
  131. \"satellites\":[\
  132. {\"PRN\":10,\"el\":45,\"az\":196,\"ss\":34,\"used\":true},\
  133. {\"PRN\":29,\"el\":67,\"az\":310,\"ss\":40,\"used\":true},\
  134. {\"PRN\":28,\"el\":59,\"az\":108,\"ss\":42,\"used\":true},\
  135. {\"PRN\":26,\"el\":51,\"az\":304,\"ss\":43,\"used\":true},\
  136. {\"PRN\":8,\"el\":44,\"az\":58,\"ss\":41,\"used\":true},\
  137. {\"PRN\":27,\"el\":16,\"az\":66,\"ss\":39,\"used\":true},\
  138. {\"az\":301,\"el\":10,\"PRN\":21,\"used\":false,\"ss\":0}]}";
  139. /* Case 3: String list syntax */
  140. static const char *json_str3 = "[\"foo\",\"bar\",\"baz\"]";
  141. static char *stringptrs[3];
  142. static char stringstore[256];
  143. static int stringcount;
  144. static const struct json_array_t json_array_3 = {
  145. .element_type = t_string,
  146. .arr.strings.ptrs = stringptrs,
  147. .arr.strings.store = stringstore,
  148. .arr.strings.storelen = sizeof(stringstore),
  149. .count = &stringcount,
  150. .maxlen = sizeof(stringptrs)/sizeof(stringptrs[0]),
  151. };
  152. /* Case 4: test defaulting of unspecified attributes */
  153. static const char *json_str4 = "{\"flag1\":true,\"flag2\":false}";
  154. static bool flag1, flag2;
  155. static double dftreal;
  156. // char can be signed or unsigned! We can only use range 0 to 127
  157. static char dftbyte;
  158. static char maxbyte;
  159. static char minbyte;
  160. static unsigned char dftubyte;
  161. static int dftinteger;
  162. static int maxint;
  163. static int minint;
  164. static unsigned int maxuint;
  165. static unsigned int dftuinteger;
  166. static long dftlongint;
  167. static unsigned long dftulongint;
  168. static struct timespec ts;
  169. static struct timespec maxts;
  170. static const struct json_attr_t json_attrs_4[] = {
  171. // t_byte can be signed, or unsigned, so can only use range 0 - 127
  172. {"dftbyte", t_byte, .addr.byte = &dftbyte, .dflt.byte = 1},
  173. {"dftubyte", t_ubyte, .addr.ubyte = &dftubyte, .dflt.ubyte = 9},
  174. {"dftint", t_integer, .addr.integer = &dftinteger, .dflt.integer = -5},
  175. {"dftuint", t_uinteger, .addr.uinteger = &dftuinteger, .dflt.uinteger = 10},
  176. {"dftlongint", t_longint, .addr.longint = &dftlongint, .dflt.longint = -6},
  177. {"dftulongint", t_ulongint, .addr.ulongint = &dftulongint,
  178. .dflt.ulongint = 11},
  179. {"dftreal", t_real, .addr.real = &dftreal, .dflt.real = 23.17},
  180. {"maxbyte", t_byte, .addr.byte = &maxbyte, .dflt.byte = 127},
  181. {"minbyte", t_byte, .addr.byte = &minbyte, .dflt.byte = 0},
  182. {"maxint", t_integer, .addr.integer = &maxint, .dflt.integer = 32767},
  183. {"minint", t_integer, .addr.integer = &minint, .dflt.integer = -32767},
  184. {"maxuint", t_uinteger, .addr.uinteger = &maxuint, .dflt.uinteger = 65535},
  185. {"flag1", t_boolean, .addr.boolean = &flag1,},
  186. {"flag2", t_boolean, .addr.boolean = &flag2,},
  187. {"dftts", t_timespec, .addr.ts = &ts, .dflt.ts = {0,0}},
  188. {"maxts", t_timespec, .addr.ts = &maxts, .dflt.ts = {0x0ffff,9}},
  189. {NULL},
  190. };
  191. /* Case 5: test DEVICE parsing */
  192. static const char *json_str5 = "{\"class\":\"DEVICE\",\
  193. \"path\":\"/dev/ttyUSB0\",\
  194. \"flags\":5,\
  195. \"driver\":\"Foonly\",\"subtype\":\"Foonly Frob\",\
  196. \"cycle\":1.1,\"mincycle\":0.002\
  197. }";
  198. /* Case 6: test parsing of subobject list into array of structures */
  199. static const char *json_str6 = "{\"parts\":[\
  200. {\"name\":\"Urgle\", \"flag\":true, \"count\":3},\
  201. {\"name\":\"Burgle\",\"flag\":false,\"count\":1},\
  202. {\"name\":\"Witter\",\"flag\":true, \"count\":4},\
  203. {\"name\":\"Thud\", \"flag\":false,\"count\":1}]}";
  204. struct dumbstruct_t {
  205. char name[64];
  206. bool flag;
  207. int count;
  208. };
  209. static struct dumbstruct_t dumbstruck[5];
  210. static int dumbcount;
  211. static const struct json_attr_t json_attrs_6_subtype[] = {
  212. {"name", t_string, .addr.offset = offsetof(struct dumbstruct_t, name),
  213. .len = 64},
  214. {"flag", t_boolean, .addr.offset = offsetof(struct dumbstruct_t, flag),},
  215. {"count", t_integer, .addr.offset = offsetof(struct dumbstruct_t, count),},
  216. {NULL},
  217. };
  218. static const struct json_attr_t json_attrs_6[] = {
  219. {"parts", t_array,
  220. .addr.array.element_type = t_structobject,
  221. .addr.array.arr.objects.base = (char*)&dumbstruck,
  222. .addr.array.arr.objects.stride = sizeof(struct dumbstruct_t),
  223. .addr.array.arr.objects.subtype = json_attrs_6_subtype,
  224. .addr.array.count = &dumbcount,
  225. .addr.array.maxlen = sizeof(dumbstruck)/sizeof(dumbstruck[0])},
  226. {NULL},
  227. };
  228. /* Case 7: test parsing of version response */
  229. static const char *json_str7 = "{\"class\":\"VERSION\",\
  230. \"release\":\"" VERSION "\",\"rev\":\"dummy-revision\",\
  231. \"proto_major\":3,\"proto_minor\":1}";
  232. /* Case 8: test parsing arrays of enumerated types */
  233. static const char *json_str8 =
  234. "{\"fee\":\"FOO\",\"fie\":\"BAR\",\"foe\":\"BAZ\"}";
  235. static const struct json_enum_t enum_table[] = {
  236. {"BAR", 6}, {"FOO", 3}, {"BAZ", 14}, {NULL}
  237. };
  238. static int fee, fie, foe;
  239. static const struct json_attr_t json_attrs_8[] = {
  240. {"fee", t_integer, .addr.integer = &fee, .map=enum_table},
  241. {"fie", t_integer, .addr.integer = &fie, .map=enum_table},
  242. {"foe", t_integer, .addr.integer = &foe, .map=enum_table},
  243. {NULL},
  244. };
  245. /* Case 9: Like case 6 but w/ an empty array */
  246. static const char *json_str9 = "{\"parts\":[]}";
  247. /* Case 10: test parsing of PPS message */
  248. static const char *json_strPPS = "{\"class\":\"PPS\",\"device\":\"GPS#1\"," \
  249. "\"real_sec\":1428001514, \"real_nsec\":1000000," \
  250. "\"clock_sec\":1428001513,\"clock_nsec\":999999999," \
  251. "\"precision\":-20,\"qErr\":-123456}";
  252. /* Case 11: test parsing of TOFF message */
  253. static const char *json_strTOFF = "{\"class\":\"TOFF\",\"device\":\"GPS#1\"," \
  254. "\"real_sec\":1428001514, \"real_nsec\":1000000," \
  255. "\"clock_sec\":1428001513,\"clock_nsec\":999999999}";
  256. /* Case 12: test parsing of OSC message */
  257. static const char *json_strOSC = "{\"class\":\"OSC\",\"device\":\"GPS#1\"," \
  258. "\"running\":true,\"reference\":true,\"disciplined\":false," \
  259. "\"delta\":67}";
  260. /* Case 13: test parsing of ERROR message, and some escape sequences */
  261. static char *json_strErr = "{\"class\":\"ERROR\",\"message\":" \
  262. "\"Hello\b\f\n\r\t\"}";
  263. /* Case 14: test parsing of ERROR message and \u escape */
  264. /* per ECMA-404, \u must be followed by 4 hex digits */
  265. static char *json_strErr1 = "{\"class\":\"ERROR\",\"message\":\"0\\u00334\"}";
  266. /* Case 15: test buffer overflow of short string destination */
  267. static char *json_strOver = "{\"name\":\"\\u0033\\u0034\\u0035\\u0036\"}";
  268. char json_short_string_dst[2];
  269. int json_short_string_cnt = 5;
  270. static const struct json_attr_t json_short_string[] = {
  271. {"name", t_string,
  272. .addr.string = json_short_string_dst,
  273. .len = sizeof(json_short_string_dst)},
  274. {"count", t_integer, .addr.integer = &json_short_string_cnt},
  275. {NULL},
  276. };
  277. /* Case 16: test buffer overflow of short string destination */
  278. static char json_strOver2[7 * JSON_VAL_MAX]; /* dynamically built */
  279. /* Case 18: Ignore part of VERSION sentence */
  280. static char *json_str18 =
  281. "{\"class\":\"VERSION\",\"release\":\"" VERSION "\","
  282. "\"rev\":\"release-dummy\",\"proto_major\":3,\"proto_minor\":14}";
  283. char release[50];
  284. int pvhi, pvlo;
  285. static const struct json_attr_t json_attrs_18[] = {
  286. {"class", t_check, .dflt.check = "VERSION"},
  287. {"release", t_string, .addr.string = (char *)&release, .len = 50},
  288. {"proto_major", t_integer, .addr.integer = &pvhi},
  289. {"proto_minor", t_integer, .addr.integer = &pvlo},
  290. {"", t_ignore},
  291. {NULL},
  292. };
  293. /* Case 19: Ignore part of WATCH sentence */
  294. static char *json_str19 =
  295. "{\"class\":\"WATCH\",\"enable\":true,\"json\":true,\"nmea\":false,\"raw\":"
  296. "0,\"scaled\":false,\"timing\":false,\"split24\":false,\"pps\":false,"
  297. "\"device\":\"/dev/ttyUSB0\"}";
  298. bool enable, json;
  299. static const struct json_attr_t json_attrs_19[] = {
  300. {"class", t_check, .dflt.check = "WATCH"},
  301. {"device", t_check, .dflt.check = "/dev/ttyUSB0"},
  302. {"enable", t_boolean, .addr.boolean = &enable},
  303. {"json", t_boolean, .addr.boolean = &json},
  304. {"", t_ignore},
  305. {NULL},
  306. };
  307. /* Case 20: Ignore part of TPV sentence */
  308. static char *json_str20 =
  309. "{\"class\":\"TPV\",\"device\":\"/dev/"
  310. "ttyUSB0\",\"mode\":3,\"time\":\"2019-10-04T08:51:34.000Z\",\"ept\":0.005,"
  311. "\"lat\":46.367303831,\"lon\":-116.963791235,\"altHAE\":460.834,\"altMSL\":"
  312. "476.140,\"epx\":7.842,\"epy\":12.231,\"epv\":30.607,\"track\":57.1020,"
  313. "\"magtrack\":70.9299,\"magvar\":13.8,\"speed\":0.065,\"climb\":-0.206,"
  314. "\"eps\":24.46,\"epc\":61.21,\"ecefx\":-1999242.00,\"ecefy\":-3929871.00,"
  315. "\"ecefz\":4593848.00,\"ecefvx\":0.12,\"ecefvy\":0.12,\"ecefvz\":-0.12,"
  316. "\"velN\":0.035,\"velE\":0.055,\"velD\":0.206,\"geoidSep\":-15.307,\"eph\":"
  317. "15.200,\"sep\":31.273}";
  318. int gps_mode;
  319. double ept;
  320. char gps_time[50];
  321. static const struct json_attr_t json_attrs_20[] = {
  322. {"class", t_check, .dflt.check = "TPV"},
  323. {"device", t_check, .dflt.check = "/dev/ttyUSB0"},
  324. {"mode", t_integer, .addr.integer = &gps_mode, .dflt.integer = -1},
  325. {"time", t_string, .addr.string = (char *)&gps_time, .len = 50},
  326. {"ept", t_real, .addr.real = &ept, .dflt.real = NAN},
  327. {"", t_ignore},
  328. {NULL},
  329. };
  330. /* Case 21: Read array of integers */
  331. static const char *json_strInt = "[23,-17,5]";
  332. static int intstore[4], intcount;
  333. static const struct json_array_t json_array_Int = {
  334. .element_type = t_integer,
  335. .arr.integers.store = intstore,
  336. .count = &intcount,
  337. .maxlen = sizeof(intstore)/sizeof(intstore[0]),
  338. };
  339. /* Case 22: Read array of booleans */
  340. static const char *json_strBool = "[true,false,true]";
  341. static bool boolstore[4];
  342. static int boolcount;
  343. static const struct json_array_t json_array_Bool = {
  344. .element_type = t_boolean,
  345. .arr.booleans.store = boolstore,
  346. .count = &boolcount,
  347. .maxlen = sizeof(boolstore)/sizeof(boolstore[0]),
  348. };
  349. /* Case 23: Read array of reals */
  350. static const char *json_strReal = "[23.1,-17.2,5.3]";
  351. static double realstore[4];
  352. static int realcount;
  353. static const struct json_array_t json_array_Real = {
  354. .element_type = t_real,
  355. .arr.reals.store = realstore,
  356. .count = &realcount,
  357. .maxlen = sizeof(realstore)/sizeof(realstore[0]),
  358. };
  359. // Case 24: ascii, bfnrt, lows unicode string encoding
  360. char ee24a[] = "This, that, the other thing.",
  361. ee24b[] = "\b\f\n\r\t\'\"\\/",
  362. // test for NUL
  363. ee24c[] = "This, that, the other thing.\0Not This",
  364. // test for good trailing unicode
  365. ee24d[] = "Hello\xc2\xb0",
  366. // test for bad trailing unicode
  367. ee24e[] = "Hello\xc2",
  368. // test for short output buffer
  369. ee24f[] = "Hello\xc2",
  370. ee24l[] = "\x01\x07\x15",
  371. /* Note the char after the "13" is a "double prime", U+2033
  372. * not a double quote! */
  373. ee24u[] = "±176°42′13″ 𠜎 𠜱 𠝹 𠱓";
  374. char ed24a[] = "This, that, the other thing.",
  375. ed24b[] = "\\b\\f\\n\\r\\t\\'\\\"\\\\\\/",
  376. ed24c[] = "This, that, the other thing.",
  377. ed24d[] = "Hello\xc2\xb0",
  378. ed24e[] = "Hello\\u00c2",
  379. ed24f[] = "Hello",
  380. ed24l[] = "\\u0001\\u0007\\u0015",
  381. ed24u[] = "±176°42′13″ 𠜎 𠜱 𠝹 𠱓";
  382. static char *json_str25a = "{\"class\":\"\",\"mode\":-1}";
  383. static char *json_str25b = "{\"class\":\"f\",\"mode\":-2}";
  384. static char *json_str25c = "{\"class\":\"fo\",\"mode\":-3}";
  385. static char *json_str25d = "{\"class\":\"foo\",\"mode\":-4}";
  386. static char *json_str25e = "{\"class\":\"foob\",\"mode\":-5}";
  387. static char *json_str25f = "{\"class\":\"fooba\",\"mode\":-6}";
  388. static char *json_str25t = "{\"class\":\"TPV\",\"mode\":3}";
  389. int i25 = 25;
  390. static const struct json_attr_t json_attrs_25[] = {
  391. {"class", t_check, .dflt.check = "TPV"},
  392. {"mode", t_integer, .addr.integer = &i25, .dflt.integer = -9},
  393. {NULL},
  394. };
  395. char str32[] = "\f\n\r\t\v";
  396. /* *INDENT-ON* */
  397. static void jsontest(int i)
  398. {
  399. int status = 0; /* libgps_json_unpack() returned status */
  400. int n; /* generic index */
  401. char buffer[500];
  402. char *pbuf;
  403. struct timespec expected_ts;
  404. if (0 < debug) {
  405. (void)fprintf(stderr, "Running test #%d.\n", i);
  406. }
  407. current_test = i;
  408. /* do not keep old data! */
  409. memset((void *)&gpsdata, 0, sizeof(gpsdata));
  410. switch (i)
  411. {
  412. case 1:
  413. status = libgps_json_unpack(json_str1, &gpsdata, NULL);
  414. assert_case(status);
  415. assert_string("device", gpsdata.dev.path, "GPS#1");
  416. assert_int("mode", "t_integer", gpsdata.fix.mode, 3);
  417. assert_int("time.tv_sec", "t_integer", gpsdata.fix.time.tv_sec,
  418. 1119168761);
  419. assert_int("time.tv_nsec", "t_integer",
  420. gpsdata.fix.time.tv_nsec / 10000000, 89);
  421. assert_real("lon", gpsdata.fix.longitude, 46.498203637);
  422. assert_real("lat", gpsdata.fix.latitude, 7.568074350);
  423. break;
  424. case 2:
  425. status = libgps_json_unpack(json_str2, &gpsdata, NULL);
  426. assert_case(status);
  427. assert_int("used", "t_integer", gpsdata.satellites_used, 6);
  428. assert_int("PRN[0]", "t_integer", gpsdata.skyview[0].PRN, 10);
  429. assert_int("el[0]", "t_integer", gpsdata.skyview[0].elevation, 45);
  430. assert_int("az[0]", "t_integer", gpsdata.skyview[0].azimuth, 196);
  431. assert_real("ss[0]", gpsdata.skyview[0].ss, 34);
  432. assert_boolean("used[0]", gpsdata.skyview[0].used, true);
  433. assert_int("PRN[6]", "t_integer", gpsdata.skyview[6].PRN, 21);
  434. assert_int("el[6]", "t_integer", gpsdata.skyview[6].elevation, 10);
  435. assert_int("az[6]", "t_integer", gpsdata.skyview[6].azimuth, 301);
  436. assert_real("ss[6]", gpsdata.skyview[6].ss, 0);
  437. assert_boolean("used[6]", gpsdata.skyview[6].used, false);
  438. break;
  439. case 3:
  440. status = json_read_array(json_str3, &json_array_3, NULL);
  441. assert_case(status);
  442. assert_other("stringcount", stringcount, 3);
  443. assert_other("stringptrs[0] == foo", strcmp(stringptrs[0], "foo"), 0);
  444. assert_other("stringptrs[1] == bar", strcmp(stringptrs[1], "bar"), 0);
  445. assert_other("stringptrs[2] == baz", strcmp(stringptrs[2], "baz"), 0);
  446. break;
  447. case 4:
  448. status = json_read_object(json_str4, json_attrs_4, NULL);
  449. assert_case(status);
  450. // did the defaults work?
  451. assert_int("dftbyte", "t_byte", dftbyte, 1);
  452. assert_uint("dftubyte", "t_ubyte", dftubyte, 9);
  453. assert_int("dftint", "t_integer", dftinteger, -5);
  454. assert_uint("dftuint", "t_uinteger", dftuinteger, 10);
  455. assert_int("dftlongint", "t_longint", dftlongint, -6);
  456. assert_uint("dftulongint", "t_ulongint", dftulongint, 11);
  457. assert_real("dftreal", dftreal, 23.17);
  458. assert_int("maxbyte", "t_byte", maxbyte, 127);
  459. assert_int("minbyte", "t_byte", minbyte, 0);
  460. assert_int("maxint", "t_integer", maxint, 32767);
  461. assert_int("minint", "t_integer", minint, -32767);
  462. assert_int("maxuint", "t_uinteger", maxuint, 65535);
  463. assert_boolean("flag1", flag1, true);
  464. assert_boolean("flag2", flag2, false);
  465. expected_ts.tv_sec = 0;
  466. expected_ts.tv_nsec = 0;
  467. assert_ts("dflts", ts, expected_ts);
  468. expected_ts.tv_sec = 0x0ffff;
  469. expected_ts.tv_nsec = 9;
  470. assert_ts("maxts", maxts, expected_ts);
  471. break;
  472. case 5:
  473. status = libgps_json_unpack(json_str5, &gpsdata, NULL);
  474. assert_case(status);
  475. assert_string("path", gpsdata.dev.path, "/dev/ttyUSB0");
  476. assert_int("flags", "t_integer", gpsdata.dev.flags, 5);
  477. assert_string("driver", gpsdata.dev.driver, "Foonly");
  478. expected_ts.tv_sec = 1;
  479. expected_ts.tv_nsec = 100000000;
  480. assert_ts("cycle", gpsdata.dev.cycle, expected_ts);
  481. expected_ts.tv_sec = 0;
  482. expected_ts.tv_nsec = 2000000;
  483. assert_ts("mincycle", gpsdata.dev.mincycle, expected_ts);
  484. break;
  485. case 6:
  486. status = json_read_object(json_str6, json_attrs_6, NULL);
  487. assert_case(status);
  488. assert_int("dumbcount", "t_integer", dumbcount, 4);
  489. assert_string("dumbstruck[0].name", dumbstruck[0].name, "Urgle");
  490. assert_string("dumbstruck[1].name", dumbstruck[1].name, "Burgle");
  491. assert_string("dumbstruck[2].name", dumbstruck[2].name, "Witter");
  492. assert_string("dumbstruck[3].name", dumbstruck[3].name, "Thud");
  493. assert_boolean("dumbstruck[0].flag", dumbstruck[0].flag, true);
  494. assert_boolean("dumbstruck[1].flag", dumbstruck[1].flag, false);
  495. assert_boolean("dumbstruck[2].flag", dumbstruck[2].flag, true);
  496. assert_boolean("dumbstruck[3].flag", dumbstruck[3].flag, false);
  497. assert_int("dumbstruck[0].count", "t_integer", dumbstruck[0].count, 3);
  498. assert_int("dumbstruck[1].count", "t_integer", dumbstruck[1].count, 1);
  499. assert_int("dumbstruck[2].count", "t_integer", dumbstruck[2].count, 4);
  500. assert_int("dumbstruck[3].count", "t_integer", dumbstruck[3].count, 1);
  501. break;
  502. case 7:
  503. status = libgps_json_unpack(json_str7, &gpsdata, NULL);
  504. assert_case(status);
  505. assert_string("release", gpsdata.version.release, VERSION);
  506. assert_string("rev", gpsdata.version.rev, "dummy-revision");
  507. assert_int("proto_major", "t_integer", gpsdata.version.proto_major, 3);
  508. assert_int("proto_minor", "t_integer", gpsdata.version.proto_minor, 1);
  509. break;
  510. case 8:
  511. status = json_read_object(json_str8, json_attrs_8, NULL);
  512. assert_case(status);
  513. assert_int("fee", "t_integer", fee, 3);
  514. assert_int("fie", "t_integer", fie, 6);
  515. assert_int("foe", "t_integer", foe, 14);
  516. break;
  517. case 9:
  518. /* yes, the '6' in the next line is correct */
  519. status = json_read_object(json_str9, json_attrs_6, NULL);
  520. assert_case(status);
  521. assert_int("dumbcount", "t_integer", dumbcount, 0);
  522. break;
  523. case 10:
  524. status = json_pps_read(json_strPPS, &gpsdata, NULL);
  525. assert_case(status);
  526. assert_string("device", gpsdata.dev.path, "GPS#1");
  527. assert_int("real_sec", "t_integer", gpsdata.pps.real.tv_sec, 1428001514);
  528. assert_int("real_nsec", "t_integer", gpsdata.pps.real.tv_nsec, 1000000);
  529. assert_int("clock_sec", "t_integer", gpsdata.pps.clock.tv_sec,
  530. 1428001513);
  531. assert_int("clock_nsec", "t_integer", gpsdata.pps.clock.tv_nsec,
  532. 999999999);
  533. assert_int("qErr", "t_integer", gpsdata.qErr, -123456);
  534. break;
  535. case 11:
  536. status = json_toff_read(json_strTOFF, &gpsdata, NULL);
  537. assert_case(status);
  538. assert_string("device", gpsdata.dev.path, "GPS#1");
  539. assert_int("real_sec", "t_integer", gpsdata.toff.real.tv_sec,
  540. 1428001514);
  541. assert_int("real_nsec", "t_integer", gpsdata.toff.real.tv_nsec,
  542. 1000000);
  543. assert_int("clock_sec", "t_integer", gpsdata.toff.clock.tv_sec,
  544. 1428001513);
  545. assert_int("clock_nsec", "t_integer", gpsdata.toff.clock.tv_nsec,
  546. 999999999);
  547. break;
  548. case 12:
  549. status = json_oscillator_read(json_strOSC, &gpsdata, NULL);
  550. assert_case(status);
  551. assert_string("device", gpsdata.dev.path, "GPS#1");
  552. assert_boolean("running", gpsdata.osc.running, true);
  553. assert_boolean("reference", gpsdata.osc.reference, true);
  554. assert_boolean("disciplined", gpsdata.osc.disciplined, false);
  555. assert_int("delta", "t_integer", gpsdata.osc.delta, 67);
  556. break;
  557. case 13:
  558. if (2 < debug) {
  559. (void)fprintf(stderr, "test string: %s.\n", json_strErr);
  560. }
  561. status = libgps_json_unpack(json_strErr, &gpsdata, NULL);
  562. assert_case(status);
  563. assert_string("message", gpsdata.error, "Hello\b\f\n\r\t");
  564. break;
  565. case 14:
  566. if (2 < debug) {
  567. (void)fprintf(stderr, "test string: %s.\n", json_strErr1);
  568. }
  569. status = libgps_json_unpack(json_strErr1, &gpsdata, NULL);
  570. assert_case(status);
  571. assert_string("message", gpsdata.error, "034");
  572. break;
  573. case 15:
  574. /* check for string overrun caught */
  575. if (2 < debug) {
  576. (void)fprintf(stderr, "test string: %s.\n", json_strOver);
  577. }
  578. json_short_string_cnt = 7;
  579. status = json_read_object(json_strOver, json_short_string, NULL);
  580. assert_case(JSON_ERR_STRLONG != status);
  581. assert_string("name", json_short_string_dst, "");
  582. assert_int("count", "t_integer", json_short_string_cnt, 0);
  583. break;
  584. case 16:
  585. /* check for string overrun caught */
  586. json_strOver2[0] = '\0';
  587. /* build a LONG test string */
  588. strlcat(json_strOver2, "{\"name\":\"", sizeof(json_strOver2));
  589. for (n = 0; n < (2 * JSON_VAL_MAX); n++) {
  590. strlcat(json_strOver2, "\\u0033", sizeof(json_strOver2));
  591. }
  592. strlcat(json_strOver2, "\"}", sizeof(json_strOver2));
  593. if (2 < debug) {
  594. (void)fprintf(stderr, "test string: %s.\n", json_strOver2);
  595. }
  596. json_short_string_cnt = 7;
  597. status = json_read_object(json_strOver2, json_short_string, NULL);
  598. assert_case(JSON_ERR_STRLONG != status);
  599. assert_string("name", json_short_string_dst, "");
  600. assert_int("count", "t_integer", json_short_string_cnt, 0);
  601. break;
  602. case 17:
  603. /* check for a different string overrun caught */
  604. json_strOver2[0] = '\0';
  605. /* build a LONG test string */
  606. strlcat(json_strOver2, "{\"name\":\"", sizeof(json_strOver2));
  607. for (n = 0; n < (2 * JSON_VAL_MAX); n++) {
  608. strlcat(json_strOver2, "\\A", sizeof(json_strOver2));
  609. }
  610. strlcat(json_strOver2, "\"}", sizeof(json_strOver2));
  611. if (2 < debug) {
  612. (void)fprintf(stderr, "test string: %s.\n", json_strOver2);
  613. }
  614. json_short_string_cnt = 7;
  615. status = json_read_object(json_strOver2, json_short_string, NULL);
  616. assert_case(JSON_ERR_STRLONG != status);
  617. assert_string("name", json_short_string_dst, "");
  618. assert_int("count", "t_integer", json_short_string_cnt, 0);
  619. break;
  620. case 18:
  621. status = json_read_object(json_str18, json_attrs_18, NULL);
  622. assert_int("proto_major", "t_integer", pvhi, 3);
  623. assert_int("proto_minor", "t_integer", pvlo, 14);
  624. assert_string("release", release, VERSION);
  625. assert_int("return", "t_integer", status, 0);
  626. break;
  627. case 19:
  628. status = json_read_object(json_str19, json_attrs_19, NULL);
  629. assert_boolean("enable", enable, true);
  630. assert_boolean("json", json, true);
  631. assert_int("return", "t_integer", status, 0);
  632. break;
  633. case 20:
  634. status = json_read_object(json_str20, json_attrs_20, NULL);
  635. assert_int("mode", "t_integer", gps_mode, 3);
  636. assert_string("time", gps_time, "2019-10-04T08:51:34.000Z");
  637. assert_real("ept", ept, 0.005);
  638. assert_int("return", "t_integer", status, 0);
  639. break;
  640. case 21:
  641. status = json_read_array(json_strInt, &json_array_Int, NULL);
  642. assert_case(status);
  643. assert_int("count", "t_integer", intcount, 3);
  644. assert_int("intstore[0]", "t_integer", intstore[0], 23);
  645. assert_int("intstore[1]", "t_integer", intstore[1], -17);
  646. assert_int("intstore[2]", "t_integer", intstore[2], 5);
  647. assert_int("intstore[3]", "t_integer", intstore[3], 0);
  648. break;
  649. case 22:
  650. status = json_read_array(json_strBool, &json_array_Bool, NULL);
  651. assert_case(status);
  652. assert_int("count", "t_integer", boolcount, 3);
  653. assert_boolean("boolstore[0]", boolstore[0], true);
  654. assert_boolean("boolstore[1]", boolstore[1], false);
  655. assert_boolean("boolstore[2]", boolstore[2], true);
  656. assert_boolean("boolstore[3]", boolstore[3], false);
  657. break;
  658. case 23:
  659. status = json_read_array(json_strReal, &json_array_Real, NULL);
  660. assert_case(status);
  661. assert_int("count", "t_integer", realcount, 3);
  662. assert_real("realstore[0]", realstore[0], 23.1);
  663. assert_real("realstore[1]", realstore[1], -17.2);
  664. assert_real("realstore[2]", realstore[2], 5.3);
  665. assert_real("realstore[3]", realstore[3], 0);
  666. break;
  667. case 24:
  668. // test w/o the trailing NUL
  669. pbuf = json_quote(ee24a, buffer, sizeof(ee24a) - 1, sizeof(buffer));
  670. assert_string1("Ascii", pbuf, ed24a);
  671. pbuf = json_quote(ee24b, buffer, sizeof(ee24b), sizeof(buffer));
  672. assert_string1("bfnrt", pbuf, ed24b);
  673. pbuf = json_quote(ee24c, buffer, sizeof(ee24c), sizeof(buffer));
  674. assert_string1("NUL", pbuf, ed24c);
  675. pbuf = json_quote(ee24d, buffer, sizeof(ee24d), sizeof(buffer));
  676. assert_string1("trailing utf", pbuf, ed24d);
  677. pbuf = json_quote(ee24e, buffer, sizeof(ee24e), sizeof(buffer));
  678. assert_string1("Bad trailing utf", pbuf, ed24e);
  679. // test for short output buffer
  680. pbuf = json_quote(ee24f, buffer, sizeof(ee24f), (size_t)6);
  681. assert_string1("Bad trailing utf", pbuf, ed24f);
  682. pbuf = json_quote(ee24l, buffer, sizeof(ee24l), sizeof(buffer));
  683. assert_string1("low", pbuf, ed24l);
  684. pbuf = json_quote(ee24u, buffer, sizeof(ee24u), sizeof(buffer));
  685. assert_string1("unicode", pbuf, ed24u);
  686. break;
  687. // Check for strings from (25) "" to (28) "foo" --
  688. // should return JSON_ERR_CHECKFAIL (16)
  689. case 25:
  690. status = json_read_object(json_str25a, json_attrs_25, NULL);
  691. assert_int("mode", "t_integer", i25, -9);
  692. assert_int("status", "t_integer", status, JSON_ERR_CHECKFAIL);
  693. break;
  694. case 26:
  695. status = json_read_object(json_str25b, json_attrs_25, NULL);
  696. assert_int("mode", "t_integer", i25, -9);
  697. assert_int("status", "t_integer", status, JSON_ERR_CHECKFAIL);
  698. break;
  699. case 27:
  700. status = json_read_object(json_str25c, json_attrs_25, NULL);
  701. assert_int("mode", "t_integer", i25, -9);
  702. assert_int("status", "t_integer", status, JSON_ERR_CHECKFAIL);
  703. break;
  704. case 28:
  705. status = json_read_object(json_str25d, json_attrs_25, NULL);
  706. assert_int("mode", "t_integer", i25, -9);
  707. assert_int("status", "t_integer", status, JSON_ERR_CHECKFAIL);
  708. break;
  709. // check strings "foob" and "fooba" -- should return JSON_ERR_STRLONG (7)
  710. case 29:
  711. status = json_read_object(json_str25e, json_attrs_25, NULL);
  712. assert_int("mode", "t_integer", i25, -9);
  713. assert_int("status", "t_integer", status, JSON_ERR_STRLONG);
  714. break;
  715. case 30:
  716. status = json_read_object(json_str25f, json_attrs_25, NULL);
  717. assert_int("mode", "t_integer", i25, -9);
  718. assert_int("status", "t_integer", status, JSON_ERR_STRLONG);
  719. break;
  720. case 31: // Check string "TPV" -- should return success (0)
  721. status = json_read_object(json_str25t, json_attrs_25, NULL);
  722. assert_int("mode", "t_integer", i25, 3);
  723. assert_int("status", "t_integer", status, 0);
  724. break;
  725. case 32: // Check that whitespace-only JSON returns JSON_ERR_EMPTY (25)
  726. status = json_read_object(str32, json_attrs_25, NULL);
  727. assert_int("status", "t_integer", status, JSON_ERR_EMPTY);
  728. break;
  729. #define MAXTEST 32
  730. default:
  731. (void)fputs("Unknown test number\n", stderr);
  732. exit(EXIT_FAILURE);
  733. }
  734. }
  735. int main(int argc UNUSED, char *argv[]UNUSED)
  736. {
  737. int option;
  738. int individual = 0;
  739. while ((option = getopt(argc, argv, "D:hn:V?")) != -1) {
  740. switch (option) {
  741. case 'D':
  742. debug = atoi(optarg);
  743. gps_enable_debug(debug, stdout);
  744. break;
  745. case 'n':
  746. individual = atoi(optarg);
  747. break;
  748. case '?':
  749. case 'h':
  750. default:
  751. (void)fprintf(stderr,
  752. "usage: %s [-D lvl] [-n tst] [-V]\n"
  753. " -D lvl set debug level\n"
  754. " -n tst run only test tst\n"
  755. " -V Print version and exit\n",
  756. argv[0]);
  757. exit(EXIT_FAILURE);
  758. case 'V':
  759. (void)fprintf(stderr, "%s: %s (revision %s)\n",
  760. argv[0], VERSION, REVISION);
  761. exit(EXIT_SUCCESS);
  762. }
  763. }
  764. (void)fprintf(stderr, "JSON unit tests\n");
  765. if (individual)
  766. jsontest(individual);
  767. else {
  768. int i;
  769. for (i = 1; i <= MAXTEST; i++) {
  770. jsontest(i);
  771. }
  772. }
  773. (void)fprintf(stderr, "succeeded.\n");
  774. exit(EXIT_SUCCESS);
  775. }
  776. /* end */
  777. // vim: set expandtab shiftwidth=4