Devuan fork of gpsd
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

709 lines
23 KiB

  1. /* json.c - unit test for JSON parsing into fixed-extent structures
  2. *
  3. * This file is Copyright (c) 2010 by the GPSD project
  4. * SPDX-License-Identifier: BSD-2-clause
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stddef.h>
  10. #include <getopt.h>
  11. #include "../gpsd.h"
  12. #include "../gps_json.h"
  13. #include "../revision.h"
  14. /* GPSD is built with JSON_MINIMAL. Any !JSON_MINIMAL tests,
  15. * like 18, 19 and 20 will thus fail.
  16. * So this define removes them, they never execute.
  17. */
  18. #define JSON_MINIMAL
  19. static int debug = 0;
  20. static int current_test = 0;
  21. static void assert_case(int status)
  22. {
  23. if (status != 0) {
  24. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  25. (void)fprintf(stderr, "status %d (%s).\n",
  26. status, json_error_string(status));
  27. exit(EXIT_FAILURE);
  28. }
  29. }
  30. static void assert_string(char *attr, char *fld, char *val)
  31. {
  32. if (strcmp(fld, val)) {
  33. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  34. (void)fprintf(stderr,
  35. "'%s' string attribute eval failed, value = %s.\n",
  36. attr, fld);
  37. exit(EXIT_FAILURE);
  38. }
  39. }
  40. static void assert_integer(char *attr, int fld, int val)
  41. {
  42. if (fld != val) {
  43. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  44. (void)fprintf(stderr,
  45. "'%s' integer attribute eval failed, value = %d s/b %d.\n",
  46. attr, fld, val);
  47. exit(EXIT_FAILURE);
  48. }
  49. }
  50. static void assert_uinteger(char *attr, unsigned int fld, unsigned int val)
  51. {
  52. if (fld != val) {
  53. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  54. (void)fprintf(stderr,
  55. "'%s' integer attribute eval failed, value = %u.\n",
  56. attr, fld);
  57. exit(EXIT_FAILURE);
  58. }
  59. }
  60. static void assert_boolean(char *attr, bool fld, bool val)
  61. {
  62. if (fld != val) {
  63. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  64. (void)fprintf(stderr,
  65. "'%s' boolean attribute eval failed, value = %s.\n",
  66. attr, fld ? "true" : "false");
  67. exit(EXIT_FAILURE);
  68. }
  69. }
  70. static void assert_other(char *desc, int val, int val1)
  71. {
  72. if (val != val1) {
  73. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  74. (void)fprintf(stderr, "'%s' was %d, s/b %d\n", desc, val, val1);
  75. exit(EXIT_FAILURE);
  76. }
  77. }
  78. /*
  79. * Floating point comparisons are iffy, but at least if any of these fail
  80. * the output will make it clear whether it was a precision issue
  81. */
  82. static void assert_real(char *attr, double fld, double val)
  83. {
  84. if (fld != val) {
  85. (void)fprintf(stderr, "case %d FAILED\n", current_test);
  86. (void)fprintf(stderr,
  87. "'%s' real attribute eval failed, value = %f.\n", attr,
  88. fld);
  89. exit(EXIT_FAILURE);
  90. }
  91. }
  92. static struct gps_data_t gpsdata;
  93. /* Case 1: TPV report */
  94. /* *INDENT-OFF* */
  95. static const char json_str1[] =
  96. "{\"class\":\"TPV\","
  97. "\"device\":\"GPS#1\",\"time\":\"2005-06-19T08:12:41.89Z\","
  98. "\"lon\":46.498203637,\"lat\":7.568074350,\"altHAE\":1327.780,"
  99. "\"epx\":21.000,\"epy\":23.000,\"epv\":124.484,\"mode\":3}";
  100. /*
  101. * Case 2: SKY report
  102. *
  103. * The fields of the last satellite entry are arranged in the reverse order
  104. * of the structure fields, in order to test for field overflow.
  105. */
  106. static const char *json_str2 = "{\"class\":\"SKY\",\
  107. \"time\":\"2005-06-19T12:12:42.03Z\", \
  108. \"satellites\":[\
  109. {\"PRN\":10,\"el\":45,\"az\":196,\"ss\":34,\"used\":true},\
  110. {\"PRN\":29,\"el\":67,\"az\":310,\"ss\":40,\"used\":true},\
  111. {\"PRN\":28,\"el\":59,\"az\":108,\"ss\":42,\"used\":true},\
  112. {\"PRN\":26,\"el\":51,\"az\":304,\"ss\":43,\"used\":true},\
  113. {\"PRN\":8,\"el\":44,\"az\":58,\"ss\":41,\"used\":true},\
  114. {\"PRN\":27,\"el\":16,\"az\":66,\"ss\":39,\"used\":true},\
  115. {\"az\":301,\"el\":10,\"PRN\":21,\"used\":false,\"ss\":0}]}";
  116. /* Case 3: String list syntax */
  117. static const char *json_str3 = "[\"foo\",\"bar\",\"baz\"]";
  118. static char *stringptrs[3];
  119. static char stringstore[256];
  120. static int stringcount;
  121. static const struct json_array_t json_array_3 = {
  122. .element_type = t_string,
  123. .arr.strings.ptrs = stringptrs,
  124. .arr.strings.store = stringstore,
  125. .arr.strings.storelen = sizeof(stringstore),
  126. .count = &stringcount,
  127. .maxlen = sizeof(stringptrs)/sizeof(stringptrs[0]),
  128. };
  129. /* Case 4: test defaulting of unspecified attributes */
  130. static const char *json_str4 = "{\"flag1\":true,\"flag2\":false}";
  131. static bool flag1, flag2;
  132. static double dftreal;
  133. static int dftinteger;
  134. static unsigned int dftuinteger;
  135. static const struct json_attr_t json_attrs_4[] = {
  136. {"dftint", t_integer, .addr.integer = &dftinteger, .dflt.integer = -5},
  137. {"dftuint", t_integer, .addr.uinteger = &dftuinteger, .dflt.uinteger = 10},
  138. {"dftreal", t_real, .addr.real = &dftreal, .dflt.real = 23.17},
  139. {"flag1", t_boolean, .addr.boolean = &flag1,},
  140. {"flag2", t_boolean, .addr.boolean = &flag2,},
  141. {NULL},
  142. };
  143. /* Case 5: test DEVICE parsing */
  144. static const char *json_str5 = "{\"class\":\"DEVICE\",\
  145. \"path\":\"/dev/ttyUSB0\",\
  146. \"flags\":5,\
  147. \"driver\":\"Foonly\",\"subtype\":\"Foonly Frob\"\
  148. }";
  149. /* Case 6: test parsing of subobject list into array of structures */
  150. static const char *json_str6 = "{\"parts\":[\
  151. {\"name\":\"Urgle\", \"flag\":true, \"count\":3},\
  152. {\"name\":\"Burgle\",\"flag\":false,\"count\":1},\
  153. {\"name\":\"Witter\",\"flag\":true, \"count\":4},\
  154. {\"name\":\"Thud\", \"flag\":false,\"count\":1}]}";
  155. struct dumbstruct_t {
  156. char name[64];
  157. bool flag;
  158. int count;
  159. };
  160. static struct dumbstruct_t dumbstruck[5];
  161. static int dumbcount;
  162. static const struct json_attr_t json_attrs_6_subtype[] = {
  163. {"name", t_string, .addr.offset = offsetof(struct dumbstruct_t, name),
  164. .len = 64},
  165. {"flag", t_boolean, .addr.offset = offsetof(struct dumbstruct_t, flag),},
  166. {"count", t_integer, .addr.offset = offsetof(struct dumbstruct_t, count),},
  167. {NULL},
  168. };
  169. static const struct json_attr_t json_attrs_6[] = {
  170. {"parts", t_array, .addr.array.element_type = t_structobject,
  171. .addr.array.arr.objects.base = (char*)&dumbstruck,
  172. .addr.array.arr.objects.stride = sizeof(struct dumbstruct_t),
  173. .addr.array.arr.objects.subtype = json_attrs_6_subtype,
  174. .addr.array.count = &dumbcount,
  175. .addr.array.maxlen = sizeof(dumbstruck)/sizeof(dumbstruck[0])},
  176. {NULL},
  177. };
  178. /* Case 7: test parsing of version response */
  179. static const char *json_str7 = "{\"class\":\"VERSION\",\
  180. \"release\":\"2.40dev\",\"rev\":\"dummy-revision\",\
  181. \"proto_major\":3,\"proto_minor\":1}";
  182. /* Case 8: test parsing arrays of enumerated types */
  183. static const char *json_str8 = "{\"fee\":\"FOO\",\"fie\":\"BAR\",\"foe\":\"BAZ\"}";
  184. static const struct json_enum_t enum_table[] = {
  185. {"BAR", 6}, {"FOO", 3}, {"BAZ", 14}, {NULL}
  186. };
  187. static int fee, fie, foe;
  188. static const struct json_attr_t json_attrs_8[] = {
  189. {"fee", t_integer, .addr.integer = &fee, .map=enum_table},
  190. {"fie", t_integer, .addr.integer = &fie, .map=enum_table},
  191. {"foe", t_integer, .addr.integer = &foe, .map=enum_table},
  192. {NULL},
  193. };
  194. /* Case 9: Like case 6 but w/ an empty array */
  195. static const char *json_str9 = "{\"parts\":[]}";
  196. /* Case 10: test parsing of PPS message */
  197. static const char *json_strPPS = "{\"class\":\"PPS\",\"device\":\"GPS#1\"," \
  198. "\"real_sec\":1428001514, \"real_nsec\":1000000," \
  199. "\"clock_sec\":1428001513,\"clock_nsec\":999999999," \
  200. "\"precision\":-20,\"qErr\":-123456}";
  201. /* Case 11: test parsing of TOFF message */
  202. static const char *json_strTOFF = "{\"class\":\"TOFF\",\"device\":\"GPS#1\"," \
  203. "\"real_sec\":1428001514, \"real_nsec\":1000000," \
  204. "\"clock_sec\":1428001513,\"clock_nsec\":999999999}";
  205. /* Case 12: test parsing of OSC message */
  206. static const char *json_strOSC = "{\"class\":\"OSC\",\"device\":\"GPS#1\"," \
  207. "\"running\":true,\"reference\":true,\"disciplined\":false," \
  208. "\"delta\":67}";
  209. /* Case 13: test parsing of ERROR message, and some escape sequences */
  210. static char *json_strErr = "{\"class\":\"ERROR\",\"message\":" \
  211. "\"Hello\b\f\n\r\t\"}";
  212. /* Case 14: test parsing of ERROR message and \u escape */
  213. /* per ECMA-404, \u must be followed by 4 hex digits */
  214. static char *json_strErr1 = "{\"class\":\"ERROR\",\"message\":\"0\\u00334\"}";
  215. /* Case 15: test buffer overflow of short string destination */
  216. static char *json_strOver = "{\"name\":\"\\u0033\\u0034\\u0035\\u0036\"}";
  217. char json_short_string_dst[2];
  218. int json_short_string_cnt = 5;
  219. static const struct json_attr_t json_short_string[] = {
  220. {"name", t_string,
  221. .addr.string = json_short_string_dst,
  222. .len = sizeof(json_short_string_dst)},
  223. {"count", t_integer, .addr.integer = &json_short_string_cnt},
  224. {NULL},
  225. };
  226. /* Case 16: test buffer overflow of short string destination */
  227. static char json_strOver2[7 * JSON_VAL_MAX]; /* dynamically built */
  228. /* Case 18: Ignore part of VERSION sentence */
  229. static char *json_str18 =
  230. "{\"class\":\"VERSION\",\"release\":\"3.20\",\"rev\":\"release-3.20"
  231. "\",\"proto_major\":3,\"proto_minor\":14}";
  232. char revision[50];
  233. int pvhi, pvlo;
  234. static const struct json_attr_t json_attrs_18[] = {
  235. {"class", t_check, .dflt.check = "VERSION"},
  236. {"rev", t_string, .addr.string = (char *)&revision, .len = 50},
  237. {"proto_major", t_integer, .addr.integer = &pvhi},
  238. {"proto_minor", t_integer, .addr.integer = &pvlo},
  239. {"", t_ignore},
  240. {NULL},
  241. };
  242. /* Case 19: Ignore part of WATCH sentence */
  243. static char *json_str19 =
  244. "{\"class\":\"WATCH\",\"enable\":true,\"json\":true,\"nmea\":false,\"raw\":"
  245. "0,\"scaled\":false,\"timing\":false,\"split24\":false,\"pps\":false,"
  246. "\"device\":\"/dev/ttyUSB0\"}";
  247. bool enable, json;
  248. static const struct json_attr_t json_attrs_19[] = {
  249. {"class", t_check, .dflt.check = "WATCH"},
  250. {"device", t_check, .dflt.check = "/dev/ttyUSB0"},
  251. {"enable", t_boolean, .addr.boolean = &enable},
  252. {"json", t_boolean, .addr.boolean = &json},
  253. {"", t_ignore},
  254. {NULL},
  255. };
  256. /* Case 20: Ignore part of TPV sentence */
  257. static char *json_str20 =
  258. "{\"class\":\"TPV\",\"device\":\"/dev/"
  259. "ttyUSB0\",\"mode\":3,\"time\":\"2019-10-04T08:51:34.000Z\",\"ept\":0.005,"
  260. "\"lat\":46.367303831,\"lon\":-116.963791235,\"altHAE\":460.834,\"altMSL\":"
  261. "476.140,\"epx\":7.842,\"epy\":12.231,\"epv\":30.607,\"track\":57.1020,"
  262. "\"magtrack\":70.9299,\"magvar\":13.8,\"speed\":0.065,\"climb\":-0.206,"
  263. "\"eps\":24.46,\"epc\":61.21,\"ecefx\":-1999242.00,\"ecefy\":-3929871.00,"
  264. "\"ecefz\":4593848.00,\"ecefvx\":0.12,\"ecefvy\":0.12,\"ecefvz\":-0.12,"
  265. "\"velN\":0.035,\"velE\":0.055,\"velD\":0.206,\"geoidSep\":-15.307,\"eph\":"
  266. "15.200,\"sep\":31.273}";
  267. int gps_mode;
  268. double ept;
  269. char gps_time[50];
  270. static const struct json_attr_t json_attrs_20[] = {
  271. {"class", t_check, .dflt.check = "TPV"},
  272. {"device", t_check, .dflt.check = "/dev/ttyUSB0"},
  273. {"mode", t_integer, .addr.integer = &gps_mode, .dflt.integer = -1},
  274. {"time", t_string, .addr.string = (char *)&gps_time, .len = 50},
  275. {"ept", t_real, .addr.real = &ept, .dflt.real = NAN},
  276. {"", t_ignore},
  277. {NULL},
  278. };
  279. #ifndef JSON_MINIMAL
  280. /* Case 21: Read array of integers */
  281. static const char *json_strInt = "[23,-17,5]";
  282. static int intstore[4], intcount;
  283. static const struct json_array_t json_array_Int = {
  284. .element_type = t_integer,
  285. .arr.integers.store = intstore,
  286. .count = &intcount,
  287. .maxlen = sizeof(intstore)/sizeof(intstore[0]),
  288. };
  289. /* Case 22: Read array of booleans */
  290. static const char *json_strBool = "[true,false,true]";
  291. static bool boolstore[4];
  292. static int boolcount;
  293. static const struct json_array_t json_array_Bool = {
  294. .element_type = t_boolean,
  295. .arr.booleans.store = boolstore,
  296. .count = &boolcount,
  297. .maxlen = sizeof(boolstore)/sizeof(boolstore[0]),
  298. };
  299. /* Case 23: Read array of reals */
  300. static const char *json_strReal = "[23.1,-17.2,5.3]";
  301. static double realstore[4];
  302. static int realcount;
  303. static const struct json_array_t json_array_Real = {
  304. .element_type = t_real,
  305. .arr.reals.store = realstore,
  306. .count = &realcount,
  307. .maxlen = sizeof(realstore)/sizeof(realstore[0]),
  308. };
  309. #endif /* JSON_MINIMAL */
  310. /* *INDENT-ON* */
  311. static void jsontest(int i)
  312. {
  313. int status = 0; /* libgps_json_unpack() returned status */
  314. int n; /* generic index */
  315. if (0 < debug) {
  316. (void)fprintf(stderr, "Running test #%d.\n", i);
  317. }
  318. current_test = i;
  319. /* do not keep old data! */
  320. memset((void *)&gpsdata, 0, sizeof(gpsdata));
  321. switch (i)
  322. {
  323. case 1:
  324. status = libgps_json_unpack(json_str1, &gpsdata, NULL);
  325. assert_case(status);
  326. assert_string("device", gpsdata.dev.path, "GPS#1");
  327. assert_integer("mode", gpsdata.fix.mode, 3);
  328. assert_integer("time.tv_sec", gpsdata.fix.time.tv_sec, 1119168761);
  329. assert_integer("time.tv_nsec", gpsdata.fix.time.tv_nsec / 10000000, 89);
  330. assert_real("lon", gpsdata.fix.longitude, 46.498203637);
  331. assert_real("lat", gpsdata.fix.latitude, 7.568074350);
  332. break;
  333. case 2:
  334. status = libgps_json_unpack(json_str2, &gpsdata, NULL);
  335. assert_case(status);
  336. assert_integer("used", gpsdata.satellites_used, 6);
  337. assert_integer("PRN[0]", gpsdata.skyview[0].PRN, 10);
  338. assert_integer("el[0]", gpsdata.skyview[0].elevation, 45);
  339. assert_integer("az[0]", gpsdata.skyview[0].azimuth, 196);
  340. assert_real("ss[0]", gpsdata.skyview[0].ss, 34);
  341. assert_boolean("used[0]", gpsdata.skyview[0].used, true);
  342. assert_integer("PRN[6]", gpsdata.skyview[6].PRN, 21);
  343. assert_integer("el[6]", gpsdata.skyview[6].elevation, 10);
  344. assert_integer("az[6]", gpsdata.skyview[6].azimuth, 301);
  345. assert_real("ss[6]", gpsdata.skyview[6].ss, 0);
  346. assert_boolean("used[6]", gpsdata.skyview[6].used, false);
  347. break;
  348. case 3:
  349. status = json_read_array(json_str3, &json_array_3, NULL);
  350. assert_case(status);
  351. assert_other("stringcount", stringcount, 3);
  352. assert_other("stringptrs[0] == foo", strcmp(stringptrs[0], "foo"), 0);
  353. assert_other("stringptrs[1] == bar", strcmp(stringptrs[1], "bar"), 0);
  354. assert_other("stringptrs[2] == baz", strcmp(stringptrs[2], "baz"), 0);
  355. break;
  356. case 4:
  357. status = json_read_object(json_str4, json_attrs_4, NULL);
  358. assert_case(status);
  359. assert_integer("dftint", dftinteger, -5); /* did the default work? */
  360. assert_uinteger("dftuint", dftuinteger, 10); /* did the default work? */
  361. assert_real("dftreal", dftreal, 23.17); /* did the default work? */
  362. assert_boolean("flag1", flag1, true);
  363. assert_boolean("flag2", flag2, false);
  364. break;
  365. case 5:
  366. status = libgps_json_unpack(json_str5, &gpsdata, NULL);
  367. assert_case(status);
  368. assert_string("path", gpsdata.dev.path, "/dev/ttyUSB0");
  369. assert_integer("flags", gpsdata.dev.flags, 5);
  370. assert_string("driver", gpsdata.dev.driver, "Foonly");
  371. break;
  372. case 6:
  373. status = json_read_object(json_str6, json_attrs_6, NULL);
  374. assert_case(status);
  375. assert_integer("dumbcount", dumbcount, 4);
  376. assert_string("dumbstruck[0].name", dumbstruck[0].name, "Urgle");
  377. assert_string("dumbstruck[1].name", dumbstruck[1].name, "Burgle");
  378. assert_string("dumbstruck[2].name", dumbstruck[2].name, "Witter");
  379. assert_string("dumbstruck[3].name", dumbstruck[3].name, "Thud");
  380. assert_boolean("dumbstruck[0].flag", dumbstruck[0].flag, true);
  381. assert_boolean("dumbstruck[1].flag", dumbstruck[1].flag, false);
  382. assert_boolean("dumbstruck[2].flag", dumbstruck[2].flag, true);
  383. assert_boolean("dumbstruck[3].flag", dumbstruck[3].flag, false);
  384. assert_integer("dumbstruck[0].count", dumbstruck[0].count, 3);
  385. assert_integer("dumbstruck[1].count", dumbstruck[1].count, 1);
  386. assert_integer("dumbstruck[2].count", dumbstruck[2].count, 4);
  387. assert_integer("dumbstruck[3].count", dumbstruck[3].count, 1);
  388. break;
  389. case 7:
  390. status = libgps_json_unpack(json_str7, &gpsdata, NULL);
  391. assert_case(status);
  392. assert_string("release", gpsdata.version.release, "2.40dev");
  393. assert_string("rev", gpsdata.version.rev, "dummy-revision");
  394. assert_integer("proto_major", gpsdata.version.proto_major, 3);
  395. assert_integer("proto_minor", gpsdata.version.proto_minor, 1);
  396. break;
  397. case 8:
  398. status = json_read_object(json_str8, json_attrs_8, NULL);
  399. assert_case(status);
  400. assert_integer("fee", fee, 3);
  401. assert_integer("fie", fie, 6);
  402. assert_integer("foe", foe, 14);
  403. break;
  404. case 9:
  405. /* yes, the '6' in the next line is correct */
  406. status = json_read_object(json_str9, json_attrs_6, NULL);
  407. assert_case(status);
  408. assert_integer("dumbcount", dumbcount, 0);
  409. break;
  410. case 10:
  411. status = json_pps_read(json_strPPS, &gpsdata, NULL);
  412. assert_case(status);
  413. assert_string("device", gpsdata.dev.path, "GPS#1");
  414. assert_integer("real_sec", gpsdata.pps.real.tv_sec, 1428001514);
  415. assert_integer("real_nsec", gpsdata.pps.real.tv_nsec, 1000000);
  416. assert_integer("clock_sec", gpsdata.pps.clock.tv_sec, 1428001513);
  417. assert_integer("clock_nsec", gpsdata.pps.clock.tv_nsec, 999999999);
  418. assert_integer("qErr", gpsdata.qErr, -123456);
  419. break;
  420. case 11:
  421. status = json_toff_read(json_strTOFF, &gpsdata, NULL);
  422. assert_case(status);
  423. assert_string("device", gpsdata.dev.path, "GPS#1");
  424. assert_integer("real_sec", gpsdata.toff.real.tv_sec, 1428001514);
  425. assert_integer("real_nsec", gpsdata.toff.real.tv_nsec, 1000000);
  426. assert_integer("clock_sec", gpsdata.toff.clock.tv_sec, 1428001513);
  427. assert_integer("clock_nsec", gpsdata.toff.clock.tv_nsec, 999999999);
  428. break;
  429. case 12:
  430. status = json_oscillator_read(json_strOSC, &gpsdata, NULL);
  431. assert_case(status);
  432. assert_string("device", gpsdata.dev.path, "GPS#1");
  433. assert_boolean("running", gpsdata.osc.running, true);
  434. assert_boolean("reference", gpsdata.osc.reference, true);
  435. assert_boolean("disciplined", gpsdata.osc.disciplined, false);
  436. assert_integer("delta", gpsdata.osc.delta, 67);
  437. break;
  438. case 13:
  439. if (2 < debug) {
  440. (void)fprintf(stderr, "test string: %s.\n", json_strErr);
  441. }
  442. status = libgps_json_unpack(json_strErr, &gpsdata, NULL);
  443. assert_case(status);
  444. assert_string("message", gpsdata.error, "Hello\b\f\n\r\t");
  445. break;
  446. case 14:
  447. if (2 < debug) {
  448. (void)fprintf(stderr, "test string: %s.\n", json_strErr1);
  449. }
  450. status = libgps_json_unpack(json_strErr1, &gpsdata, NULL);
  451. assert_case(status);
  452. assert_string("message", gpsdata.error, "034");
  453. break;
  454. case 15:
  455. /* check for string overrun caught */
  456. if (2 < debug) {
  457. (void)fprintf(stderr, "test string: %s.\n", json_strOver);
  458. }
  459. json_short_string_cnt = 7;
  460. status = json_read_object(json_strOver, json_short_string, NULL);
  461. assert_case(JSON_ERR_STRLONG != status);
  462. assert_string("name", json_short_string_dst, "");
  463. assert_integer("count", json_short_string_cnt, 0);
  464. break;
  465. case 16:
  466. /* check for string overrun caught */
  467. json_strOver2[0] = '\0';
  468. /* build a LONG test string */
  469. strlcat(json_strOver2, "{\"name\":\"", sizeof(json_strOver2));
  470. for (n = 0; n < (2 * JSON_VAL_MAX); n++) {
  471. strlcat(json_strOver2, "\\u0033", sizeof(json_strOver2));
  472. }
  473. strlcat(json_strOver2, "\"}", sizeof(json_strOver2));
  474. if (2 < debug) {
  475. (void)fprintf(stderr, "test string: %s.\n", json_strOver2);
  476. }
  477. json_short_string_cnt = 7;
  478. status = json_read_object(json_strOver2, json_short_string, NULL);
  479. assert_case(JSON_ERR_STRLONG != status);
  480. assert_string("name", json_short_string_dst, "");
  481. assert_integer("count", json_short_string_cnt, 0);
  482. break;
  483. case 17:
  484. /* check for a different string overrun caught */
  485. json_strOver2[0] = '\0';
  486. /* build a LONG test string */
  487. strlcat(json_strOver2, "{\"name\":\"", sizeof(json_strOver2));
  488. for (n = 0; n < (2 * JSON_VAL_MAX); n++) {
  489. strlcat(json_strOver2, "\\A", sizeof(json_strOver2));
  490. }
  491. strlcat(json_strOver2, "\"}", sizeof(json_strOver2));
  492. if (2 < debug) {
  493. (void)fprintf(stderr, "test string: %s.\n", json_strOver2);
  494. }
  495. json_short_string_cnt = 7;
  496. status = json_read_object(json_strOver2, json_short_string, NULL);
  497. assert_case(JSON_ERR_STRLONG != status);
  498. assert_string("name", json_short_string_dst, "");
  499. assert_integer("count", json_short_string_cnt, 0);
  500. break;
  501. case 18:
  502. status = json_read_object(json_str18, json_attrs_18, NULL);
  503. assert_integer("proto_major", pvhi, 3);
  504. assert_integer("proto_minor", pvlo, 14);
  505. assert_string("rev", revision, "release-3.20");
  506. assert_integer("return", status, 0);
  507. break;
  508. case 19:
  509. status = json_read_object(json_str19, json_attrs_19, NULL);
  510. assert_boolean("enable", enable, true);
  511. assert_boolean("json", json, true);
  512. assert_integer("return", status, 0);
  513. break;
  514. case 20:
  515. status = json_read_object(json_str20, json_attrs_20, NULL);
  516. assert_integer("mode", gps_mode, 3);
  517. assert_string("time", gps_time, "2019-10-04T08:51:34.000Z");
  518. assert_real("ept", ept, 0.005);
  519. assert_integer("return", status, 0);
  520. break;
  521. #ifdef JSON_MINIMAL
  522. #define MAXTEST 20
  523. #else
  524. case 21:
  525. status = json_read_array(json_strInt, &json_array_Int, NULL);
  526. assert_integer("count", intcount, 3);
  527. assert_integer("intstore[0]", intstore[0], 23);
  528. assert_integer("intstore[1]", intstore[1], -17);
  529. assert_integer("intstore[2]", intstore[2], 5);
  530. assert_integer("intstore[3]", intstore[3], 0);
  531. break;
  532. case 22:
  533. status = json_read_array(json_strBool, &json_array_Bool, NULL);
  534. assert_integer("count", boolcount, 3);
  535. assert_boolean("boolstore[0]", boolstore[0], true);
  536. assert_boolean("boolstore[1]", boolstore[1], false);
  537. assert_boolean("boolstore[2]", boolstore[2], true);
  538. assert_boolean("boolstore[3]", boolstore[3], false);
  539. break;
  540. case 23:
  541. status = json_read_array(json_strReal, &json_array_Real, NULL);
  542. assert_integer("count", realcount, 3);
  543. assert_real("realstore[0]", realstore[0], 23.1);
  544. assert_real("realstore[1]", realstore[1], -17.2);
  545. assert_real("realstore[2]", realstore[2], 5.3);
  546. assert_real("realstore[3]", realstore[3], 0);
  547. break;
  548. #define MAXTEST 23
  549. #endif /* JSON_MINIMAL */
  550. default:
  551. (void)fputs("Unknown test number\n", stderr);
  552. exit(EXIT_FAILURE);
  553. }
  554. }
  555. int main(int argc UNUSED, char *argv[]UNUSED)
  556. {
  557. int option;
  558. int individual = 0;
  559. while ((option = getopt(argc, argv, "D:hn:V?")) != -1) {
  560. switch (option) {
  561. #ifdef CLIENTDEBUG_ENABLE
  562. case 'D':
  563. debug = atoi(optarg);
  564. gps_enable_debug(debug, stdout);
  565. break;
  566. #endif
  567. case 'n':
  568. individual = atoi(optarg);
  569. break;
  570. case '?':
  571. case 'h':
  572. default:
  573. (void)fprintf(stderr,
  574. "usage: %s [-D lvl] [-n tst] [-V]\n"
  575. " -D lvl set debug level\n"
  576. " -n tst run only test tst\n"
  577. " -V Print version and exit\n",
  578. argv[0]);
  579. exit(EXIT_FAILURE);
  580. case 'V':
  581. (void)fprintf(stderr, "%s: %s (revision %s)\n",
  582. argv[0], VERSION, REVISION);
  583. exit(EXIT_SUCCESS);
  584. }
  585. }
  586. (void)fprintf(stderr, "JSON unit tests\n");
  587. if (individual)
  588. jsontest(individual);
  589. else {
  590. int i;
  591. for (i = 1; i <= MAXTEST; i++) {
  592. jsontest(i);
  593. }
  594. }
  595. (void)fprintf(stderr, "succeeded.\n");
  596. exit(EXIT_SUCCESS);
  597. }
  598. /* end */