main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. * lws-api-test-lws_tokenize
  3. *
  4. * Written in 2010-2019 by Andy Green <[email protected]>
  5. *
  6. * This file is made available under the Creative Commons CC0 1.0
  7. * Universal Public Domain Dedication.
  8. *
  9. * This demonstrates the most minimal http server you can make with lws.
  10. *
  11. * To keep it simple, it serves stuff from the subdirectory
  12. * "./mount-origin" of the directory it was started in.
  13. * You can change that by changing mount.origin below.
  14. */
  15. #include <libwebsockets.h>
  16. #include <string.h>
  17. #include <stdio.h>
  18. struct expected {
  19. lws_tokenize_elem e;
  20. const char *value;
  21. size_t len;
  22. };
  23. struct tests {
  24. const char *string;
  25. struct expected *exp;
  26. int count;
  27. int flags;
  28. };
  29. struct expected expected1[] = {
  30. { LWS_TOKZE_TOKEN, "protocol-1", 10 },
  31. { LWS_TOKZE_DELIMITER, ",", 1},
  32. { LWS_TOKZE_TOKEN, "protocol_2", 10 },
  33. { LWS_TOKZE_DELIMITER, ",", 1},
  34. { LWS_TOKZE_TOKEN, "protocol3", 9 },
  35. { LWS_TOKZE_ENDED, NULL, 0 },
  36. },
  37. expected2[] = {
  38. { LWS_TOKZE_TOKEN_NAME_COLON, "Accept-Language", 15 },
  39. { LWS_TOKZE_TOKEN, "fr-CH", 5 },
  40. { LWS_TOKZE_DELIMITER, ",", 1 },
  41. { LWS_TOKZE_TOKEN, "fr", 2 },
  42. { LWS_TOKZE_DELIMITER, ";", 1},
  43. { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
  44. { LWS_TOKZE_FLOAT, "0.9", 3 },
  45. { LWS_TOKZE_DELIMITER, ",", 1 },
  46. { LWS_TOKZE_TOKEN, "en", 2 },
  47. { LWS_TOKZE_DELIMITER, ";", 1},
  48. { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
  49. { LWS_TOKZE_FLOAT, "0.8", 3 },
  50. { LWS_TOKZE_DELIMITER, ",", 1 },
  51. { LWS_TOKZE_TOKEN, "de", 2 },
  52. { LWS_TOKZE_DELIMITER, ";", 1},
  53. { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
  54. { LWS_TOKZE_FLOAT, "0.7", 3 },
  55. { LWS_TOKZE_DELIMITER, ",", 1 },
  56. { LWS_TOKZE_DELIMITER, "*", 1 },
  57. { LWS_TOKZE_DELIMITER, ";", 1 },
  58. { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
  59. { LWS_TOKZE_FLOAT, "0.5", 3 },
  60. { LWS_TOKZE_ENDED, NULL, 0 },
  61. },
  62. expected3[] = {
  63. { LWS_TOKZE_TOKEN_NAME_EQUALS, "quoted", 6 },
  64. { LWS_TOKZE_QUOTED_STRING, "things:", 7 },
  65. { LWS_TOKZE_DELIMITER, ",", 1 },
  66. { LWS_TOKZE_INTEGER, "1234", 4 },
  67. { LWS_TOKZE_ENDED, NULL, 0 },
  68. },
  69. expected4[] = {
  70. { LWS_TOKZE_ERR_COMMA_LIST, ",", 1 },
  71. },
  72. expected5[] = {
  73. { LWS_TOKZE_TOKEN, "brokenlist2", 11 },
  74. { LWS_TOKZE_DELIMITER, ",", 1 },
  75. { LWS_TOKZE_ERR_COMMA_LIST, ",", 1 },
  76. },
  77. expected6[] = {
  78. { LWS_TOKZE_TOKEN, "brokenlist3", 11 },
  79. { LWS_TOKZE_DELIMITER, ",", 1 },
  80. { LWS_TOKZE_ERR_COMMA_LIST, ",", 1 },
  81. },
  82. expected7[] = {
  83. { LWS_TOKZE_TOKEN, "fr", 2 },
  84. { LWS_TOKZE_DELIMITER, "-", 1 },
  85. { LWS_TOKZE_TOKEN, "CH", 2 },
  86. { LWS_TOKZE_DELIMITER, ",", 1 },
  87. { LWS_TOKZE_TOKEN, "fr", 2 },
  88. { LWS_TOKZE_DELIMITER, ";", 1 },
  89. { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
  90. { LWS_TOKZE_FLOAT, "0.9", 3 },
  91. { LWS_TOKZE_DELIMITER, ",", 1 },
  92. { LWS_TOKZE_TOKEN, "en", 2 },
  93. { LWS_TOKZE_DELIMITER, ";", 1 },
  94. { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
  95. { LWS_TOKZE_FLOAT, "0.8", 3 },
  96. { LWS_TOKZE_DELIMITER, ",", 1 },
  97. { LWS_TOKZE_TOKEN, "de", 2 },
  98. { LWS_TOKZE_DELIMITER, ";", 1 },
  99. { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
  100. { LWS_TOKZE_FLOAT, "0.7", 3 },
  101. { LWS_TOKZE_DELIMITER, ",", 1 },
  102. { LWS_TOKZE_TOKEN, "*", 1 },
  103. { LWS_TOKZE_DELIMITER, ";", 1 },
  104. { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
  105. { LWS_TOKZE_FLOAT, "0.5", 3 },
  106. { LWS_TOKZE_ENDED, "", 0 },
  107. },
  108. expected8[] = {
  109. { LWS_TOKZE_TOKEN, "Οὐχὶ", 10 },
  110. { LWS_TOKZE_TOKEN, "ταὐτὰ", 12 },
  111. { LWS_TOKZE_TOKEN, "παρίσταταί", 22 },
  112. { LWS_TOKZE_TOKEN, "μοι", 6 },
  113. { LWS_TOKZE_TOKEN, "γιγνώσκειν", 21 },
  114. { LWS_TOKZE_DELIMITER, ",", 1 },
  115. { LWS_TOKZE_TOKEN, "ὦ", 3 },
  116. { LWS_TOKZE_TOKEN, "ἄνδρες", 13 },
  117. { LWS_TOKZE_TOKEN, "᾿Αθηναῖοι", 20 },
  118. { LWS_TOKZE_DELIMITER, ",", 1 },
  119. { LWS_TOKZE_TOKEN, "greek", 5 },
  120. { LWS_TOKZE_ENDED, "", 0 },
  121. },
  122. expected9[] = {
  123. /*
  124. * because the tokenizer scans ahead for = aggregation,
  125. * it finds the broken utf8 before reporting the token
  126. */
  127. { LWS_TOKZE_ERR_BROKEN_UTF8, "", 0 },
  128. },
  129. expected10[] = {
  130. { LWS_TOKZE_TOKEN, "badutf8-2", 9 },
  131. { LWS_TOKZE_TOKEN, "퟿", 3 },
  132. { LWS_TOKZE_DELIMITER, ",", 1 },
  133. { LWS_TOKZE_ERR_BROKEN_UTF8, "", 0 },
  134. },
  135. expected11[] = {
  136. { LWS_TOKZE_TOKEN, "1.myserver", 10 },
  137. { LWS_TOKZE_DELIMITER, ".", 1 },
  138. { LWS_TOKZE_TOKEN, "com", 3 },
  139. { LWS_TOKZE_ENDED, "", 0 },
  140. },
  141. expected12[] = {
  142. { LWS_TOKZE_TOKEN, "1.myserver.com", 14 },
  143. { LWS_TOKZE_ENDED, "", 0 },
  144. },
  145. expected13[] = {
  146. { LWS_TOKZE_TOKEN, "1.myserver.com", 14 },
  147. { LWS_TOKZE_ENDED, "", 0 },
  148. },
  149. expected14[] = {
  150. { LWS_TOKZE_INTEGER, "1", 1 },
  151. { LWS_TOKZE_DELIMITER, ".", 1 },
  152. { LWS_TOKZE_TOKEN, "myserver", 8 },
  153. { LWS_TOKZE_DELIMITER, ".", 1 },
  154. { LWS_TOKZE_TOKEN, "com", 3 },
  155. { LWS_TOKZE_ENDED, "", 0 },
  156. },
  157. expected15[] = {
  158. { LWS_TOKZE_TOKEN, "close", 5 },
  159. { LWS_TOKZE_DELIMITER, ",", 1 },
  160. { LWS_TOKZE_TOKEN, "Upgrade", 7 },
  161. { LWS_TOKZE_ENDED, "", 0 },
  162. },
  163. expected16[] = {
  164. { LWS_TOKZE_TOKEN_NAME_EQUALS, "a", 1 },
  165. { LWS_TOKZE_TOKEN, "5", 1 },
  166. { LWS_TOKZE_ENDED, "", 0 },
  167. },
  168. expected17[] = {
  169. { LWS_TOKZE_TOKEN, "hello", 5 },
  170. { LWS_TOKZE_ENDED, "", 0 },
  171. }
  172. ;
  173. struct tests tests[] = {
  174. {
  175. " protocol-1, protocol_2\t,\tprotocol3\n",
  176. expected1, LWS_ARRAY_SIZE(expected1),
  177. LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_AGG_COLON
  178. }, {
  179. "Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5",
  180. expected2, LWS_ARRAY_SIZE(expected2),
  181. LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_AGG_COLON
  182. }, {
  183. "quoted = \"things:\", 1234",
  184. expected3, LWS_ARRAY_SIZE(expected3),
  185. LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_AGG_COLON
  186. }, {
  187. ", brokenlist1",
  188. expected4, LWS_ARRAY_SIZE(expected4),
  189. LWS_TOKENIZE_F_COMMA_SEP_LIST
  190. }, {
  191. "brokenlist2,,",
  192. expected5, LWS_ARRAY_SIZE(expected5),
  193. LWS_TOKENIZE_F_COMMA_SEP_LIST
  194. }, {
  195. "brokenlist3,",
  196. expected6, LWS_ARRAY_SIZE(expected6),
  197. LWS_TOKENIZE_F_COMMA_SEP_LIST
  198. }, {
  199. "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5",
  200. expected7, LWS_ARRAY_SIZE(expected7),
  201. LWS_TOKENIZE_F_RFC7230_DELIMS
  202. },
  203. {
  204. " Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι, greek",
  205. expected8, LWS_ARRAY_SIZE(expected8),
  206. LWS_TOKENIZE_F_RFC7230_DELIMS
  207. },
  208. {
  209. "badutf8-1 \x80...",
  210. expected9, LWS_ARRAY_SIZE(expected9),
  211. LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_RFC7230_DELIMS
  212. },
  213. {
  214. "badutf8-2 \xed\x9f\xbf,\x80...",
  215. expected10, LWS_ARRAY_SIZE(expected10),
  216. LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_RFC7230_DELIMS
  217. },
  218. {
  219. "1.myserver.com",
  220. expected11, LWS_ARRAY_SIZE(expected11),
  221. 0
  222. },
  223. {
  224. "1.myserver.com",
  225. expected12, LWS_ARRAY_SIZE(expected12),
  226. LWS_TOKENIZE_F_DOT_NONTERM
  227. },
  228. {
  229. "1.myserver.com",
  230. expected13, LWS_ARRAY_SIZE(expected13),
  231. LWS_TOKENIZE_F_DOT_NONTERM | LWS_TOKENIZE_F_NO_FLOATS
  232. },
  233. {
  234. "1.myserver.com",
  235. expected14, LWS_ARRAY_SIZE(expected14),
  236. LWS_TOKENIZE_F_NO_FLOATS
  237. },
  238. {
  239. "close, Upgrade",
  240. expected15, LWS_ARRAY_SIZE(expected15),
  241. LWS_TOKENIZE_F_COMMA_SEP_LIST
  242. },
  243. {
  244. "a=5", expected16, LWS_ARRAY_SIZE(expected16),
  245. LWS_TOKENIZE_F_NO_INTEGERS
  246. },
  247. {
  248. "# comment1\r\nhello #comment2\r\n#comment3", expected17,
  249. LWS_ARRAY_SIZE(expected17), LWS_TOKENIZE_F_HASH_COMMENT
  250. }
  251. };
  252. /*
  253. * add LWS_TOKZE_ERRS to the element index (which may be negative by that
  254. * amount) to index this array
  255. */
  256. static const char *element_names[] = {
  257. "LWS_TOKZE_ERR_BROKEN_UTF8",
  258. "LWS_TOKZE_ERR_UNTERM_STRING",
  259. "LWS_TOKZE_ERR_MALFORMED_FLOAT",
  260. "LWS_TOKZE_ERR_NUM_ON_LHS",
  261. "LWS_TOKZE_ERR_COMMA_LIST",
  262. "LWS_TOKZE_ENDED",
  263. "LWS_TOKZE_DELIMITER",
  264. "LWS_TOKZE_TOKEN",
  265. "LWS_TOKZE_INTEGER",
  266. "LWS_TOKZE_FLOAT",
  267. "LWS_TOKZE_TOKEN_NAME_EQUALS",
  268. "LWS_TOKZE_TOKEN_NAME_COLON",
  269. "LWS_TOKZE_QUOTED_STRING",
  270. };
  271. int
  272. exp_cb1(void *priv, const char *name, char *out, size_t *pos, size_t olen,
  273. size_t *exp_ofs)
  274. {
  275. const char *replace = NULL;
  276. size_t total, budget;
  277. if (!strcmp(name, "test")) {
  278. replace = "replacement_string";
  279. total = strlen(replace);
  280. goto expand;
  281. }
  282. return LSTRX_FATAL_NAME_UNKNOWN;
  283. expand:
  284. budget = olen - *pos;
  285. total -= *exp_ofs;
  286. if (total < budget)
  287. budget = total;
  288. if (out)
  289. memcpy(out + *pos, replace + (*exp_ofs), budget);
  290. *exp_ofs += budget;
  291. *pos += budget;
  292. if (budget == total)
  293. return LSTRX_DONE;
  294. return LSTRX_FILLED_OUT;
  295. }
  296. static const char *exp_inp1 = "this-is-a-${test}-for-strexp";
  297. int main(int argc, const char **argv)
  298. {
  299. struct lws_tokenize ts;
  300. lws_tokenize_elem e;
  301. const char *p;
  302. int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
  303. /* for LLL_ verbosity above NOTICE to be built into lws,
  304. * lws must have been configured and built with
  305. * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
  306. /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
  307. /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
  308. /* | LLL_DEBUG */;
  309. int fail = 0, ok = 0, flags = 0;
  310. char dotstar[512];
  311. if ((p = lws_cmdline_option(argc, argv, "-d")))
  312. logs = atoi(p);
  313. lws_set_log_level(logs, NULL);
  314. lwsl_user("LWS API selftest: lws_tokenize\n");
  315. if ((p = lws_cmdline_option(argc, argv, "-f")))
  316. flags = atoi(p);
  317. /* lws_strexp */
  318. {
  319. size_t in_len, used_in, used_out;
  320. lws_strexp_t exp;
  321. char obuf[128];
  322. const char *p;
  323. obuf[0] = '\0';
  324. lws_strexp_init(&exp, NULL, exp_cb1, obuf, sizeof(obuf));
  325. n = lws_strexp_expand(&exp, exp_inp1, 28, &used_in, &used_out);
  326. if (n != LSTRX_DONE || used_in != 28 ||
  327. strcmp(obuf, "this-is-a-replacement_string-for-strexp")) {
  328. lwsl_notice("%s: obuf %s\n", __func__, obuf);
  329. lwsl_err("%s: lws_strexp test 1 failed: %d\n", __func__, n);
  330. return 1;
  331. }
  332. /* as above, but don't generate output, just find the length */
  333. lws_strexp_init(&exp, NULL, exp_cb1, NULL, (size_t)-1);
  334. n = lws_strexp_expand(&exp, exp_inp1, 28, &used_in, &used_out);
  335. if (n != LSTRX_DONE || used_in != 28 || used_out != 39) {
  336. lwsl_err("%s: lws_strexp test 2 failed: %d, used_out: %d\n",
  337. __func__, n, (int)used_out);
  338. return 1;
  339. }
  340. p = exp_inp1;
  341. in_len = strlen(p);
  342. memset(obuf, 0, sizeof(obuf));
  343. lws_strexp_init(&exp, NULL, exp_cb1, obuf, 16);
  344. n = lws_strexp_expand(&exp, p, in_len, &used_in, &used_out);
  345. if (n != LSTRX_FILLED_OUT || used_in != 16 || used_out != 16) {
  346. lwsl_err("a\n");
  347. return 1;
  348. }
  349. p += used_in;
  350. in_len -= used_in;
  351. memset(obuf, 0, sizeof(obuf));
  352. lws_strexp_reset_out(&exp, obuf, 16);
  353. n = lws_strexp_expand(&exp, p, in_len, &used_in, &used_out);
  354. if (n != LSTRX_FILLED_OUT || used_in != 5 || used_out != 16) {
  355. lwsl_err("b: n %d, used_in %d, used_out %d\n", n,
  356. (int)used_in, (int)used_out);
  357. return 2;
  358. }
  359. p += used_in;
  360. in_len -= used_in;
  361. memset(obuf, 0, sizeof(obuf));
  362. lws_strexp_reset_out(&exp, obuf, 16);
  363. n = lws_strexp_expand(&exp, p, in_len, &used_in, &used_out);
  364. if (n != LSTRX_DONE || used_in != 7 || used_out != 7) {
  365. lwsl_err("c: n %d, used_in %d, used_out %d\n", n, (int)used_in, (int)used_out);
  366. return 2;
  367. }
  368. }
  369. /* sanity check lws_strnncpy() */
  370. lws_strnncpy(dotstar, "12345678", 4, sizeof(dotstar));
  371. if (strcmp(dotstar, "1234")) {
  372. lwsl_err("%s: lws_strnncpy check failed\n", __func__);
  373. return 1;
  374. }
  375. lws_strnncpy(dotstar, "12345678", 8, 6);
  376. if (strcmp(dotstar, "12345")) {
  377. lwsl_err("%s: lws_strnncpy check failed\n", __func__);
  378. return 1;
  379. }
  380. /* sanity check lws_nstrstr() */
  381. {
  382. static const char *t1 = "abc123456";
  383. const char *mcp;
  384. mcp = lws_nstrstr(t1, strlen(t1), "abc", 3);
  385. if (mcp != t1) {
  386. lwsl_err("%s: lws_nstrstr 1 failed\n", __func__);
  387. return 1;
  388. }
  389. mcp = lws_nstrstr(t1, strlen(t1), "def", 3);
  390. if (mcp != NULL) {
  391. lwsl_err("%s: lws_nstrstr 2 failed\n", __func__);
  392. return 1;
  393. }
  394. mcp = lws_nstrstr(t1, strlen(t1), "456", 3);
  395. if (mcp != t1 + 6) {
  396. lwsl_err("%s: lws_nstrstr 3 failed: %p\n", __func__, mcp);
  397. return 1;
  398. }
  399. mcp = lws_nstrstr(t1, strlen(t1), "1", 1);
  400. if (mcp != t1 + 3) {
  401. lwsl_err("%s: lws_nstrstr 4 failed\n", __func__);
  402. return 1;
  403. }
  404. mcp = lws_nstrstr(t1, strlen(t1), "abc1234567", 10);
  405. if (mcp != NULL) {
  406. lwsl_err("%s: lws_nstrstr 5 failed\n", __func__);
  407. return 1;
  408. }
  409. }
  410. /* sanity check lws_json_simple_find() */
  411. {
  412. static const char *t1 = "{\"myname1\":true,"
  413. "\"myname2\":\"string\", "
  414. "\"myname3\": 123}";
  415. size_t alen;
  416. const char *mcp;
  417. mcp = lws_json_simple_find(t1, strlen(t1), "\"myname1\":", &alen);
  418. if (mcp != t1 + 11 || alen != 4) {
  419. lwsl_err("%s: lws_json_simple_find 1 failed: (%d) %s\n",
  420. __func__, (int)alen, mcp);
  421. return 1;
  422. }
  423. mcp = lws_json_simple_find(t1, strlen(t1), "\"myname2\":", &alen);
  424. if (mcp != t1 + 27 || alen != 6) {
  425. lwsl_err("%s: lws_json_simple_find 2 failed\n", __func__);
  426. return 1;
  427. }
  428. mcp = lws_json_simple_find(t1, strlen(t1), "\"myname3\":", &alen);
  429. if (mcp != t1 + 47 || alen != 3) {
  430. lwsl_err("%s: lws_json_simple_find 3 failed\n", __func__);
  431. return 1;
  432. }
  433. mcp = lws_json_simple_find(t1, strlen(t1), "\"nope\":", &alen);
  434. if (mcp != NULL) {
  435. lwsl_err("%s: lws_json_simple_find 4 failed\n", __func__);
  436. return 1;
  437. }
  438. }
  439. p = lws_cmdline_option(argc, argv, "-s");
  440. for (n = 0; n < (int)LWS_ARRAY_SIZE(tests); n++) {
  441. int m = 0, in_fail = fail;
  442. struct expected *exp = tests[n].exp;
  443. memset(&ts, 0, sizeof(ts));
  444. ts.start = tests[n].string;
  445. ts.len = strlen(ts.start);
  446. ts.flags = tests[n].flags;
  447. do {
  448. e = lws_tokenize(&ts);
  449. lws_strnncpy(dotstar, ts.token, ts.token_len,
  450. sizeof(dotstar));
  451. lwsl_info("{ %s, \"%s\", %d }\n",
  452. element_names[e + LWS_TOKZE_ERRS], dotstar,
  453. (int)ts.token_len);
  454. if (m == (int)tests[n].count) {
  455. lwsl_notice("fail: expected end earlier\n");
  456. fail++;
  457. break;
  458. }
  459. if (e != exp->e) {
  460. lwsl_notice("fail... tok %s vs expected %s\n",
  461. element_names[e + LWS_TOKZE_ERRS],
  462. element_names[exp->e + LWS_TOKZE_ERRS]);
  463. fail++;
  464. break;
  465. }
  466. if (e > 0 &&
  467. (ts.token_len != exp->len ||
  468. memcmp(exp->value, ts.token, exp->len))) {
  469. lws_strnncpy(dotstar, ts.token, ts.token_len,
  470. sizeof(dotstar));
  471. lwsl_notice("fail token mismatch %d %d %s\n",
  472. (int)ts.token_len, (int)exp->len,
  473. dotstar);
  474. fail++;
  475. break;
  476. }
  477. m++;
  478. exp++;
  479. } while (e > 0);
  480. if (fail == in_fail)
  481. ok++;
  482. }
  483. if (p) {
  484. ts.start = p;
  485. ts.len = strlen(p);
  486. ts.flags = flags;
  487. printf("\t{\n\t\t\"%s\",\n"
  488. "\t\texpected%d, LWS_ARRAY_SIZE(expected%d),\n\t\t",
  489. p, (int)LWS_ARRAY_SIZE(tests) + 1,
  490. (int)LWS_ARRAY_SIZE(tests) + 1);
  491. if (!flags)
  492. printf("0\n\t},\n");
  493. else {
  494. if (flags & LWS_TOKENIZE_F_MINUS_NONTERM)
  495. printf("LWS_TOKENIZE_F_MINUS_NONTERM");
  496. if (flags & LWS_TOKENIZE_F_AGG_COLON) {
  497. if (flags & 1)
  498. printf(" | ");
  499. printf("LWS_TOKENIZE_F_AGG_COLON");
  500. }
  501. if (flags & LWS_TOKENIZE_F_COMMA_SEP_LIST) {
  502. if (flags & 3)
  503. printf(" | ");
  504. printf("LWS_TOKENIZE_F_COMMA_SEP_LIST");
  505. }
  506. if (flags & LWS_TOKENIZE_F_RFC7230_DELIMS) {
  507. if (flags & 7)
  508. printf(" | ");
  509. printf("LWS_TOKENIZE_F_RFC7230_DELIMS");
  510. }
  511. if (flags & LWS_TOKENIZE_F_DOT_NONTERM) {
  512. if (flags & 15)
  513. printf(" | ");
  514. printf("LWS_TOKENIZE_F_DOT_NONTERM");
  515. }
  516. if (flags & LWS_TOKENIZE_F_NO_FLOATS) {
  517. if (flags & 31)
  518. printf(" | ");
  519. printf("LWS_TOKENIZE_F_NO_FLOATS");
  520. }
  521. printf("\n\t},\n");
  522. }
  523. printf("\texpected%d[] = {\n", (int)LWS_ARRAY_SIZE(tests) + 1);
  524. do {
  525. e = lws_tokenize(&ts);
  526. lws_strnncpy(dotstar, ts.token, ts.token_len,
  527. sizeof(dotstar));
  528. printf("\t\t{ %s, \"%s\", %d },\n",
  529. element_names[e + LWS_TOKZE_ERRS],
  530. dotstar, (int)ts.token_len);
  531. } while (e > 0);
  532. printf("\t}\n");
  533. }
  534. #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
  535. {
  536. time_t t;
  537. if (lws_http_date_parse_unix("Tue, 15 Nov 1994 08:12:31 GMT", 29, &t)) {
  538. lwsl_err("%s: date parse failed\n", __func__);
  539. fail++;
  540. } else {
  541. /* lwsl_notice("%s: %llu\n", __func__, (unsigned long long)t); */
  542. if (t != (time_t)784887151) {
  543. lwsl_err("%s: date parse wrong\n", __func__);
  544. fail++;
  545. } else {
  546. char s[30];
  547. if (lws_http_date_render_from_unix(s, sizeof(s), &t)) {
  548. lwsl_err("%s: failed date render\n", __func__);
  549. fail++;
  550. } else {
  551. if (!strcmp(s, "Tue, 15 Nov 1994 08:12:31 GMT")) {
  552. lwsl_err("%s: date render wrong\n", __func__);
  553. fail++;
  554. }
  555. }
  556. }
  557. }
  558. }
  559. #endif
  560. lwsl_user("Completed: PASS: %d, FAIL: %d\n", ok, fail);
  561. return !(ok && !fail);
  562. }