1/* 2 * lws-api-test-lws_tokenize 3 * 4 * Written in 2010-2021 by Andy Green <andy@warmcat.com> 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 20struct expected { 21 lws_tokenize_elem e; 22 const char *value; 23 size_t len; 24}; 25 26struct tests { 27 const char *string; 28 struct expected *exp; 29 int count; 30 int flags; 31}; 32 33struct 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 183struct 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 272static 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 289int 290exp_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 304expand: 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 321static const char *exp_inp1 = "this-is-a-${test}-for-strexp"; 322 323int 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