1 /*
2 * lws-api-test-lws_tokenize
3 *
4 * Written in 2010-2021 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
16 #include <libwebsockets.h>
17 #include <string.h>
18 #include <stdio.h>
19
20 struct expected {
21 lws_tokenize_elem e;
22 const char *value;
23 size_t len;
24 };
25
26 struct tests {
27 const char *string;
28 struct expected *exp;
29 int count;
30 int flags;
31 };
32
33 struct expected expected1[] = {
34 { LWS_TOKZE_TOKEN, "protocol-1", 10 },
35 { LWS_TOKZE_DELIMITER, ",", 1},
36 { LWS_TOKZE_TOKEN, "protocol_2", 10 },
37 { LWS_TOKZE_DELIMITER, ",", 1},
38 { LWS_TOKZE_TOKEN, "protocol3", 9 },
39 { LWS_TOKZE_ENDED, NULL, 0 },
40 },
41 expected2[] = {
42 { LWS_TOKZE_TOKEN_NAME_COLON, "Accept-Language", 15 },
43 { LWS_TOKZE_TOKEN, "fr-CH", 5 },
44 { LWS_TOKZE_DELIMITER, ",", 1 },
45 { LWS_TOKZE_TOKEN, "fr", 2 },
46 { LWS_TOKZE_DELIMITER, ";", 1},
47 { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
48 { LWS_TOKZE_FLOAT, "0.9", 3 },
49 { LWS_TOKZE_DELIMITER, ",", 1 },
50 { LWS_TOKZE_TOKEN, "en", 2 },
51 { LWS_TOKZE_DELIMITER, ";", 1},
52 { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
53 { LWS_TOKZE_FLOAT, "0.8", 3 },
54 { LWS_TOKZE_DELIMITER, ",", 1 },
55 { LWS_TOKZE_TOKEN, "de", 2 },
56 { LWS_TOKZE_DELIMITER, ";", 1},
57 { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
58 { LWS_TOKZE_FLOAT, "0.7", 3 },
59 { LWS_TOKZE_DELIMITER, ",", 1 },
60 { LWS_TOKZE_DELIMITER, "*", 1 },
61 { LWS_TOKZE_DELIMITER, ";", 1 },
62 { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
63 { LWS_TOKZE_FLOAT, "0.5", 3 },
64 { LWS_TOKZE_ENDED, NULL, 0 },
65 },
66 expected3[] = {
67 { LWS_TOKZE_TOKEN_NAME_EQUALS, "quoted", 6 },
68 { LWS_TOKZE_QUOTED_STRING, "things:", 7 },
69 { LWS_TOKZE_DELIMITER, ",", 1 },
70 { LWS_TOKZE_INTEGER, "1234", 4 },
71 { LWS_TOKZE_ENDED, NULL, 0 },
72 },
73 expected4[] = {
74 { LWS_TOKZE_ERR_COMMA_LIST, ",", 1 },
75 },
76 expected5[] = {
77 { LWS_TOKZE_TOKEN, "brokenlist2", 11 },
78 { LWS_TOKZE_DELIMITER, ",", 1 },
79 { LWS_TOKZE_ERR_COMMA_LIST, ",", 1 },
80 },
81 expected6[] = {
82 { LWS_TOKZE_TOKEN, "brokenlist3", 11 },
83 { LWS_TOKZE_DELIMITER, ",", 1 },
84 { LWS_TOKZE_ERR_COMMA_LIST, ",", 1 },
85
86 },
87 expected7[] = {
88 { LWS_TOKZE_TOKEN, "fr", 2 },
89 { LWS_TOKZE_DELIMITER, "-", 1 },
90 { LWS_TOKZE_TOKEN, "CH", 2 },
91 { LWS_TOKZE_DELIMITER, ",", 1 },
92 { LWS_TOKZE_TOKEN, "fr", 2 },
93 { LWS_TOKZE_DELIMITER, ";", 1 },
94 { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
95 { LWS_TOKZE_FLOAT, "0.9", 3 },
96 { LWS_TOKZE_DELIMITER, ",", 1 },
97 { LWS_TOKZE_TOKEN, "en", 2 },
98 { LWS_TOKZE_DELIMITER, ";", 1 },
99 { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
100 { LWS_TOKZE_FLOAT, "0.8", 3 },
101 { LWS_TOKZE_DELIMITER, ",", 1 },
102 { LWS_TOKZE_TOKEN, "de", 2 },
103 { LWS_TOKZE_DELIMITER, ";", 1 },
104 { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
105 { LWS_TOKZE_FLOAT, "0.7", 3 },
106 { LWS_TOKZE_DELIMITER, ",", 1 },
107 { LWS_TOKZE_TOKEN, "*", 1 },
108 { LWS_TOKZE_DELIMITER, ";", 1 },
109 { LWS_TOKZE_TOKEN_NAME_EQUALS, "q", 1 },
110 { LWS_TOKZE_FLOAT, "0.5", 3 },
111 { LWS_TOKZE_ENDED, "", 0 },
112 },
113 expected8[] = {
114 { LWS_TOKZE_TOKEN, "Οὐχὶ", 10 },
115 { LWS_TOKZE_TOKEN, "ταὐτὰ", 12 },
116 { LWS_TOKZE_TOKEN, "παρίσταταί", 22 },
117 { LWS_TOKZE_TOKEN, "μοι", 6 },
118 { LWS_TOKZE_TOKEN, "γιγνώσκειν", 21 },
119 { LWS_TOKZE_DELIMITER, ",", 1 },
120 { LWS_TOKZE_TOKEN, "ὦ", 3 },
121 { LWS_TOKZE_TOKEN, "ἄνδρες", 13 },
122 { LWS_TOKZE_TOKEN, "᾿Αθηναῖοι", 20 },
123 { LWS_TOKZE_DELIMITER, ",", 1 },
124 { LWS_TOKZE_TOKEN, "greek", 5 },
125 { LWS_TOKZE_ENDED, "", 0 },
126 },
127 expected9[] = {
128 /*
129 * because the tokenizer scans ahead for = aggregation,
130 * it finds the broken utf8 before reporting the token
131 */
132 { LWS_TOKZE_ERR_BROKEN_UTF8, "", 0 },
133 },
134 expected10[] = {
135 { LWS_TOKZE_TOKEN, "badutf8-2", 9 },
136 { LWS_TOKZE_TOKEN, "", 3 },
137 { LWS_TOKZE_DELIMITER, ",", 1 },
138 { LWS_TOKZE_ERR_BROKEN_UTF8, "", 0 },
139 },
140 expected11[] = {
141 { LWS_TOKZE_TOKEN, "1.myserver", 10 },
142 { LWS_TOKZE_DELIMITER, ".", 1 },
143 { LWS_TOKZE_TOKEN, "com", 3 },
144 { LWS_TOKZE_ENDED, "", 0 },
145 },
146 expected12[] = {
147 { LWS_TOKZE_TOKEN, "1.myserver.com", 14 },
148 { LWS_TOKZE_ENDED, "", 0 },
149 },
150 expected13[] = {
151 { LWS_TOKZE_TOKEN, "1.myserver.com", 14 },
152 { LWS_TOKZE_ENDED, "", 0 },
153 },
154 expected14[] = {
155 { LWS_TOKZE_INTEGER, "1", 1 },
156 { LWS_TOKZE_DELIMITER, ".", 1 },
157 { LWS_TOKZE_TOKEN, "myserver", 8 },
158 { LWS_TOKZE_DELIMITER, ".", 1 },
159 { LWS_TOKZE_TOKEN, "com", 3 },
160 { LWS_TOKZE_ENDED, "", 0 },
161 },
162 expected15[] = {
163 { LWS_TOKZE_TOKEN, "close", 5 },
164 { LWS_TOKZE_DELIMITER, ",", 1 },
165 { LWS_TOKZE_TOKEN, "Upgrade", 7 },
166 { LWS_TOKZE_ENDED, "", 0 },
167 },
168 expected16[] = {
169 { LWS_TOKZE_TOKEN_NAME_EQUALS, "a", 1 },
170 { LWS_TOKZE_TOKEN, "5", 1 },
171 { LWS_TOKZE_ENDED, "", 0 },
172 },
173 expected17[] = {
174 { LWS_TOKZE_TOKEN, "hello", 5 },
175 { LWS_TOKZE_ENDED, "", 0 },
176 },
177 expected18[] = {
178 { LWS_TOKZE_TOKEN, "x=y", 3 },
179 { LWS_TOKZE_ENDED, "", 0 },
180 }
181 ;
182
183 struct tests tests[] = {
184 {
185 " protocol-1, protocol_2\t,\tprotocol3\n",
186 expected1, LWS_ARRAY_SIZE(expected1),
187 LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_AGG_COLON
188 }, {
189 "Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5",
190 expected2, LWS_ARRAY_SIZE(expected2),
191 LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_AGG_COLON
192 }, {
193 "quoted = \"things:\", 1234",
194 expected3, LWS_ARRAY_SIZE(expected3),
195 LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_AGG_COLON
196 }, {
197 ", brokenlist1",
198 expected4, LWS_ARRAY_SIZE(expected4),
199 LWS_TOKENIZE_F_COMMA_SEP_LIST
200 }, {
201 "brokenlist2,,",
202 expected5, LWS_ARRAY_SIZE(expected5),
203 LWS_TOKENIZE_F_COMMA_SEP_LIST
204 }, {
205 "brokenlist3,",
206 expected6, LWS_ARRAY_SIZE(expected6),
207 LWS_TOKENIZE_F_COMMA_SEP_LIST
208 }, {
209 "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5",
210 expected7, LWS_ARRAY_SIZE(expected7),
211 LWS_TOKENIZE_F_ASTERISK_NONTERM | LWS_TOKENIZE_F_RFC7230_DELIMS
212 },
213 {
214 " Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι, greek",
215 expected8, LWS_ARRAY_SIZE(expected8),
216 LWS_TOKENIZE_F_RFC7230_DELIMS
217 },
218 {
219 "badutf8-1 \x80...",
220 expected9, LWS_ARRAY_SIZE(expected9),
221 LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_RFC7230_DELIMS
222 },
223 {
224 "badutf8-2 \xed\x9f\xbf,\x80...",
225 expected10, LWS_ARRAY_SIZE(expected10),
226 LWS_TOKENIZE_F_MINUS_NONTERM | LWS_TOKENIZE_F_RFC7230_DELIMS
227 },
228 {
229 "1.myserver.com",
230 expected11, LWS_ARRAY_SIZE(expected11),
231 0
232 },
233 {
234 "1.myserver.com",
235 expected12, LWS_ARRAY_SIZE(expected12),
236 LWS_TOKENIZE_F_DOT_NONTERM
237 },
238 {
239 "1.myserver.com",
240 expected13, LWS_ARRAY_SIZE(expected13),
241 LWS_TOKENIZE_F_DOT_NONTERM | LWS_TOKENIZE_F_NO_FLOATS
242 },
243 {
244 "1.myserver.com",
245 expected14, LWS_ARRAY_SIZE(expected14),
246 LWS_TOKENIZE_F_NO_FLOATS
247 },
248 {
249 "close, Upgrade",
250 expected15, LWS_ARRAY_SIZE(expected15),
251 LWS_TOKENIZE_F_COMMA_SEP_LIST
252 },
253 {
254 "a=5", expected16, LWS_ARRAY_SIZE(expected16),
255 LWS_TOKENIZE_F_NO_INTEGERS
256 },
257 {
258 "# comment1\r\nhello #comment2\r\n#comment3", expected17,
259 LWS_ARRAY_SIZE(expected17), LWS_TOKENIZE_F_HASH_COMMENT
260 },
261 {
262 "x=y", expected18,
263 LWS_ARRAY_SIZE(expected18), LWS_TOKENIZE_F_EQUALS_NONTERM
264 }
265 };
266
267 /*
268 * add LWS_TOKZE_ERRS to the element index (which may be negative by that
269 * amount) to index this array
270 */
271
272 static const char *element_names[] = {
273 "LWS_TOKZE_ERR_BROKEN_UTF8",
274 "LWS_TOKZE_ERR_UNTERM_STRING",
275 "LWS_TOKZE_ERR_MALFORMED_FLOAT",
276 "LWS_TOKZE_ERR_NUM_ON_LHS",
277 "LWS_TOKZE_ERR_COMMA_LIST",
278 "LWS_TOKZE_ENDED",
279 "LWS_TOKZE_DELIMITER",
280 "LWS_TOKZE_TOKEN",
281 "LWS_TOKZE_INTEGER",
282 "LWS_TOKZE_FLOAT",
283 "LWS_TOKZE_TOKEN_NAME_EQUALS",
284 "LWS_TOKZE_TOKEN_NAME_COLON",
285 "LWS_TOKZE_QUOTED_STRING",
286 };
287
288
289 int
exp_cb1(void * priv,const char * name,char * out,size_t * pos,size_t olen,size_t * exp_ofs)290 exp_cb1(void *priv, const char *name, char *out, size_t *pos, size_t olen,
291 size_t *exp_ofs)
292 {
293 const char *replace = NULL;
294 size_t total, budget;
295
296 if (!strcmp(name, "test")) {
297 replace = "replacement_string";
298 total = strlen(replace);
299 goto expand;
300 }
301
302 return LSTRX_FATAL_NAME_UNKNOWN;
303
304 expand:
305 budget = olen - *pos;
306 total -= *exp_ofs;
307 if (total < budget)
308 budget = total;
309
310 if (out)
311 memcpy(out + *pos, replace + (*exp_ofs), budget);
312 *exp_ofs += budget;
313 *pos += budget;
314
315 if (budget == total)
316 return LSTRX_DONE;
317
318 return LSTRX_FILLED_OUT;
319 }
320
321 static const char *exp_inp1 = "this-is-a-${test}-for-strexp";
322
main(int argc,const char ** argv)323 int main(int argc, const char **argv)
324 {
325 struct lws_context_creation_info info;
326 struct lws_context *cx;
327 struct lws_tokenize ts;
328 lws_tokenize_elem e;
329 const char *p;
330 int n, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
331 /* for LLL_ verbosity above NOTICE to be built into lws,
332 * lws must have been configured and built with
333 * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
334 /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
335 /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
336 /* | LLL_DEBUG */;
337 int fail = 0, ok = 0, flags = 0;
338 char dotstar[512];
339
340 if ((p = lws_cmdline_option(argc, argv, "-d")))
341 logs = atoi(p);
342
343 lws_set_log_level(logs, NULL);
344 lwsl_user("LWS API selftest: lws_tokenize\n");
345
346 if ((p = lws_cmdline_option(argc, argv, "-f")))
347 flags = atoi(p);
348
349
350 memset(&info, 0, sizeof info);
351 info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
352 LWS_SERVER_OPTION_H2_JUST_FIX_WINDOW_UPDATE_OVERFLOW;
353
354 /*
355 * since we know this lws context is only ever going to be used with
356 * one client wsis / fds / sockets at a time, let lws know it doesn't
357 * have to use the default allocations for fd tables up to ulimit -n.
358 * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we
359 * will use.
360 */
361 info.fd_limit_per_thread = 1 + 1 + 1;
362
363 #if 0
364 #if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL)
365 /*
366 * OpenSSL uses the system trust store. mbedTLS has to be told which
367 * CA to trust explicitly.
368 */
369 info.client_ssl_ca_filepath = "./warmcat.com.cer";
370 #endif
371 #endif
372 #if 0
373 n = open("./warmcat.com.cer", O_RDONLY);
374 if (n >= 0) {
375 info.client_ssl_ca_mem_len = read(n, memcert, sizeof(memcert));
376 info.client_ssl_ca_mem = memcert;
377 close(n);
378 n = 0;
379 memcert[info.client_ssl_ca_mem_len++] = '\0';
380 }
381 #endif
382 cx = lws_create_context(&info);
383
384 /* lws_strexp */
385
386 {
387 size_t in_len, used_in, used_out;
388 lws_strexp_t exp;
389 char obuf[128];
390 const char *p;
391
392 obuf[0] = '\0';
393 lws_strexp_init(&exp, NULL, exp_cb1, obuf, sizeof(obuf));
394 n = lws_strexp_expand(&exp, exp_inp1, 28, &used_in, &used_out);
395 if (n != LSTRX_DONE || used_in != 28 ||
396 strcmp(obuf, "this-is-a-replacement_string-for-strexp")) {
397 lwsl_notice("%s: obuf %s\n", __func__, obuf);
398 lwsl_err("%s: lws_strexp test 1 failed: %d\n", __func__, n);
399
400 return 1;
401 }
402
403 /* as above, but don't generate output, just find the length */
404
405 lws_strexp_init(&exp, NULL, exp_cb1, NULL, (size_t)-1);
406 n = lws_strexp_expand(&exp, exp_inp1, 28, &used_in, &used_out);
407 if (n != LSTRX_DONE || used_in != 28 || used_out != 39) {
408 lwsl_err("%s: lws_strexp test 2 failed: %d, used_out: %d\n",
409 __func__, n, (int)used_out);
410
411 return 1;
412 }
413
414 p = exp_inp1;
415 in_len = strlen(p);
416 memset(obuf, 0, sizeof(obuf));
417 lws_strexp_init(&exp, NULL, exp_cb1, obuf, 16);
418 n = lws_strexp_expand(&exp, p, in_len, &used_in, &used_out);
419 if (n != LSTRX_FILLED_OUT || used_in != 16 || used_out != 16) {
420 lwsl_err("a\n");
421 return 1;
422 }
423
424 p += used_in;
425 in_len -= used_in;
426
427 memset(obuf, 0, sizeof(obuf));
428 lws_strexp_reset_out(&exp, obuf, 16);
429
430 n = lws_strexp_expand(&exp, p, in_len, &used_in, &used_out);
431 if (n != LSTRX_FILLED_OUT || used_in != 5 || used_out != 16) {
432 lwsl_err("b: n %d, used_in %d, used_out %d\n", n,
433 (int)used_in, (int)used_out);
434 return 2;
435 }
436
437 p += used_in;
438 in_len -= used_in;
439
440 memset(obuf, 0, sizeof(obuf));
441 lws_strexp_reset_out(&exp, obuf, 16);
442
443 n = lws_strexp_expand(&exp, p, in_len, &used_in, &used_out);
444 if (n != LSTRX_DONE || used_in != 7 || used_out != 7) {
445 lwsl_err("c: n %d, used_in %d, used_out %d\n", n, (int)used_in, (int)used_out);
446 return 2;
447 }
448 }
449
450 /* sanity check lws_strnncpy() */
451
452 lws_strnncpy(dotstar, "12345678", 4, sizeof(dotstar));
453 if (strcmp(dotstar, "1234")) {
454 lwsl_err("%s: lws_strnncpy check failed\n", __func__);
455
456 return 1;
457 }
458 lws_strnncpy(dotstar, "12345678", 8, 6);
459 if (strcmp(dotstar, "12345")) {
460 lwsl_err("%s: lws_strnncpy check failed\n", __func__);
461
462 return 1;
463 }
464
465 /* sanity check lws_nstrstr() */
466
467 {
468 static const char *t1 = "abc123456";
469 const char *mcp;
470
471 mcp = lws_nstrstr(t1, strlen(t1), "abc", 3);
472 if (mcp != t1) {
473 lwsl_err("%s: lws_nstrstr 1 failed\n", __func__);
474 return 1;
475 }
476 mcp = lws_nstrstr(t1, strlen(t1), "def", 3);
477 if (mcp != NULL) {
478 lwsl_err("%s: lws_nstrstr 2 failed\n", __func__);
479 return 1;
480 }
481 mcp = lws_nstrstr(t1, strlen(t1), "456", 3);
482 if (mcp != t1 + 6) {
483 lwsl_err("%s: lws_nstrstr 3 failed: %p\n", __func__, mcp);
484 return 1;
485 }
486 mcp = lws_nstrstr(t1, strlen(t1), "1", 1);
487 if (mcp != t1 + 3) {
488 lwsl_err("%s: lws_nstrstr 4 failed\n", __func__);
489 return 1;
490 }
491 mcp = lws_nstrstr(t1, strlen(t1), "abc1234567", 10);
492 if (mcp != NULL) {
493 lwsl_err("%s: lws_nstrstr 5 failed\n", __func__);
494 return 1;
495 }
496 }
497
498 /* sanity check lws_json_simple_find() */
499
500 {
501 static const char *t1 = "{\"myname1\":true,"
502 "\"myname2\":\"string\", "
503 "\"myname3\": 123}";
504 size_t alen;
505 const char *mcp;
506
507 mcp = lws_json_simple_find(t1, strlen(t1), "\"myname1\":", &alen);
508 if (mcp != t1 + 11 || alen != 4) {
509 lwsl_err("%s: lws_json_simple_find 1 failed: (%d) %s\n",
510 __func__, (int)alen, mcp);
511 return 1;
512 }
513
514 mcp = lws_json_simple_find(t1, strlen(t1), "\"myname2\":", &alen);
515 if (mcp != t1 + 27 || alen != 6) {
516 lwsl_err("%s: lws_json_simple_find 2 failed\n", __func__);
517 return 1;
518 }
519
520 mcp = lws_json_simple_find(t1, strlen(t1), "\"myname3\":", &alen);
521 if (mcp != t1 + 47 || alen != 3) {
522 lwsl_err("%s: lws_json_simple_find 3 failed\n", __func__);
523 return 1;
524 }
525
526 mcp = lws_json_simple_find(t1, strlen(t1), "\"nope\":", &alen);
527 if (mcp != NULL) {
528 lwsl_err("%s: lws_json_simple_find 4 failed\n", __func__);
529 return 1;
530 }
531 }
532
533 p = lws_cmdline_option(argc, argv, "-s");
534
535 for (n = 0; n < (int)LWS_ARRAY_SIZE(tests); n++) {
536 int m = 0, in_fail = fail;
537 struct expected *exp = tests[n].exp;
538
539 memset(&ts, 0, sizeof(ts));
540 ts.start = tests[n].string;
541 ts.len = strlen(ts.start);
542 ts.flags = (uint16_t)tests[n].flags;
543
544 do {
545 e = lws_tokenize(&ts);
546
547 lws_strnncpy(dotstar, ts.token, ts.token_len,
548 sizeof(dotstar));
549 lwsl_info("{ %s, \"%s\", %d }\n",
550 element_names[e + LWS_TOKZE_ERRS], dotstar,
551 (int)ts.token_len);
552
553 if (m == (int)tests[n].count) {
554 lwsl_notice("fail: expected end earlier\n");
555 fail++;
556 break;
557 }
558
559 if (e != exp->e) {
560 lwsl_notice("fail... tok %s vs expected %s\n",
561 element_names[e + LWS_TOKZE_ERRS],
562 element_names[exp->e + LWS_TOKZE_ERRS]);
563 fail++;
564 break;
565 }
566
567 if (e > 0 &&
568 (ts.token_len != exp->len ||
569 memcmp(exp->value, ts.token, exp->len))) {
570 lws_strnncpy(dotstar, ts.token, ts.token_len,
571 sizeof(dotstar));
572 lwsl_notice("fail token mismatch %d %d %s\n",
573 (int)ts.token_len, (int)exp->len,
574 dotstar);
575 fail++;
576 break;
577 }
578
579 m++;
580 exp++;
581
582 } while (e > 0);
583
584 if (fail == in_fail)
585 ok++;
586 }
587
588 if (p) {
589 ts.start = p;
590 ts.len = strlen(p);
591 ts.flags = (uint16_t)flags;
592
593 printf("\t{\n\t\t\"%s\",\n"
594 "\t\texpected%d, LWS_ARRAY_SIZE(expected%d),\n\t\t",
595 p, (int)LWS_ARRAY_SIZE(tests) + 1,
596 (int)LWS_ARRAY_SIZE(tests) + 1);
597
598 if (!flags)
599 printf("0\n\t},\n");
600 else {
601 if (flags & LWS_TOKENIZE_F_MINUS_NONTERM)
602 printf("LWS_TOKENIZE_F_MINUS_NONTERM");
603 if (flags & LWS_TOKENIZE_F_AGG_COLON) {
604 if (flags & 1)
605 printf(" | ");
606 printf("LWS_TOKENIZE_F_AGG_COLON");
607 }
608 if (flags & LWS_TOKENIZE_F_COMMA_SEP_LIST) {
609 if (flags & 3)
610 printf(" | ");
611 printf("LWS_TOKENIZE_F_COMMA_SEP_LIST");
612 }
613 if (flags & LWS_TOKENIZE_F_RFC7230_DELIMS) {
614 if (flags & 7)
615 printf(" | ");
616 printf("LWS_TOKENIZE_F_RFC7230_DELIMS");
617 }
618 if (flags & LWS_TOKENIZE_F_DOT_NONTERM) {
619 if (flags & 15)
620 printf(" | ");
621 printf("LWS_TOKENIZE_F_DOT_NONTERM");
622 }
623 if (flags & LWS_TOKENIZE_F_NO_FLOATS) {
624 if (flags & 31)
625 printf(" | ");
626 printf("LWS_TOKENIZE_F_NO_FLOATS");
627 }
628 printf("\n\t},\n");
629 }
630
631 printf("\texpected%d[] = {\n", (int)LWS_ARRAY_SIZE(tests) + 1);
632
633 do {
634 e = lws_tokenize(&ts);
635
636 lws_strnncpy(dotstar, ts.token, ts.token_len,
637 sizeof(dotstar));
638
639 printf("\t\t{ %s, \"%s\", %d },\n",
640 element_names[e + LWS_TOKZE_ERRS],
641 dotstar, (int)ts.token_len);
642
643 } while (e > 0);
644
645 printf("\t}\n");
646 }
647
648 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
649 {
650 time_t t;
651
652 if (lws_http_date_parse_unix("Tue, 15 Nov 1994 08:12:31 GMT", 29, &t)) {
653 lwsl_err("%s: date parse failed\n", __func__);
654 fail++;
655 } else {
656 /* lwsl_notice("%s: %llu\n", __func__, (unsigned long long)t); */
657 if (t != (time_t)784887151) {
658 lwsl_err("%s: date parse wrong\n", __func__);
659 fail++;
660 } else {
661 char s[30];
662
663 if (lws_http_date_render_from_unix(s, sizeof(s), &t)) {
664 lwsl_err("%s: failed date render\n", __func__);
665 fail++;
666 } else {
667 if (!strcmp(s, "Tue, 15 Nov 1994 08:12:31 GMT")) {
668 lwsl_err("%s: date render wrong\n", __func__);
669 fail++;
670 }
671 }
672 }
673 }
674 }
675 #endif
676
677 {
678 char buf[24];
679 int m;
680
681 m = lws_humanize(buf, sizeof(buf), 0, humanize_schema_si);
682 if (m != 1 || strcmp(buf, "0")) {
683 lwsl_user("%s: humanize 1 fail '%s' (%d)\n", __func__, buf, m);
684 fail++;
685 }
686 m = lws_humanize(buf, sizeof(buf), 2, humanize_schema_si);
687 if (m != 1 || strcmp(buf, "2")) {
688 lwsl_user("%s: humanize 2 fail '%s' (%d)\n", __func__, buf, m);
689 fail++;
690 }
691 m = lws_humanize(buf, sizeof(buf), 999, humanize_schema_si);
692 if (m != 3 || strcmp(buf, "999")) {
693 lwsl_user("%s: humanize 3 fail '%s' (%d)\n", __func__, buf, m);
694 fail++;
695 }
696 m = lws_humanize(buf, sizeof(buf), 1000, humanize_schema_si);
697 if (m != 4 || strcmp(buf, "1000")) {
698 lwsl_user("%s: humanize 4 fail '%s' (%d)\n", __func__, buf, m);
699 fail++;
700 }
701 m = lws_humanize(buf, sizeof(buf), 1024, humanize_schema_si);
702 if (m != 7 || strcmp(buf, "1.000Ki")) {
703 lwsl_user("%s: humanize 5 fail '%s' (%d)\n", __func__, buf, m);
704 fail++;
705 }
706 }
707
708 if (lws_strcmp_wildcard("allied", 6, "allied", 6)) {
709 lwsl_user("%s: wc 1 fail\n", __func__);
710 fail++;
711 }
712 if (lws_strcmp_wildcard("a*", 2, "allied", 6)) {
713 lwsl_user("%s: wc 2 fail\n", __func__);
714 fail++;
715 }
716 if (lws_strcmp_wildcard("all*", 4, "allied", 6)) {
717 lwsl_user("%s: wc 3 fail\n", __func__);
718 fail++;
719 }
720 if (lws_strcmp_wildcard("all*d", 5, "allied", 6)) {
721 lwsl_user("%s: wc 4 fail\n", __func__);
722 fail++;
723 }
724 if (!lws_strcmp_wildcard("b*", 2, "allied", 6)) {
725 lwsl_user("%s: wc 5 fail\n", __func__);
726 fail++;
727 }
728 if (!lws_strcmp_wildcard("b*ed", 4, "allied", 6)) {
729 lwsl_user("%s: wc 6 fail\n", __func__);
730 fail++;
731 }
732 if (!lws_strcmp_wildcard("allie", 5, "allied", 6)) {
733 lwsl_user("%s: wc 7 fail\n", __func__);
734 fail++;
735 }
736 if (lws_strcmp_wildcard("allie*", 6, "allied", 6)) {
737 lwsl_user("%s: wc 8 fail\n", __func__);
738 fail++;
739 }
740 if (lws_strcmp_wildcard("*llie*", 6, "allied", 6)) {
741 lwsl_user("%s: wc 9 fail\n", __func__);
742 fail++;
743 }
744 if (lws_strcmp_wildcard("*llied", 6, "allied", 6)) {
745 lwsl_user("%s: wc 10 fail\n", __func__);
746 fail++;
747 }
748 if (!lws_strcmp_wildcard("*llie", 5, "allied", 6)) {
749 lwsl_user("%s: wc 11 fail\n", __func__);
750 fail++;
751 }
752 if (!lws_strcmp_wildcard("*nope", 5, "allied", 6)) {
753 lwsl_user("%s: wc 12 fail\n", __func__);
754 fail++;
755 }
756 if (lws_strcmp_wildcard("*li*", 4, "allied", 6)) {
757 lwsl_user("%s: wc 13 fail\n", __func__);
758 fail++;
759 }
760 if (lws_strcmp_wildcard("*", 1, "allied", 6)) {
761 lwsl_user("%s: wc 14 fail\n", __func__);
762 fail++;
763 }
764 if (lws_strcmp_wildcard("*abc*d", 6, "xxabyyabcdd", 11)) {
765 lwsl_user("%s: wc 15 fail\n", __func__);
766 fail++;
767 }
768 if (lws_strcmp_wildcard("ssproxy.n.cn.*", 14,
769 "ssproxy.n.cn.failures", 21)) {
770 lwsl_user("%s: wc 16 fail\n", __func__);
771 fail++;
772 }
773
774 lwsl_user("Completed: PASS: %d, FAIL: %d\n", ok, fail);
775
776 lws_context_destroy(cx);
777
778 return !(ok && !fail);
779 }
780