1 /*- 2 * Copyright (c) 2012-2017 Dag-Erling Smørgrav 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifdef HAVE_CONFIG_H 31 # include "config.h" 32 #endif 33 34 #include <err.h> 35 #include <stdint.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include <cryb/test.h> 42 43 #include <security/pam_appl.h> 44 #include <security/openpam.h> 45 46 #define T_FUNC(n, d) \ 47 static const char *t_ ## n ## _desc = d; \ 48 static int t_ ## n ## _func(OPENPAM_UNUSED(char **desc), \ 49 OPENPAM_UNUSED(void *arg)) 50 51 #define T(n) \ 52 t_add_test(&t_ ## n ## _func, NULL, "%s", t_ ## n ## _desc) 53 54 /* 55 * Read a word from the temp file and verify that the result matches our 56 * expectations: whether a word was read at all, how many lines were read 57 * (in case of quoted or escaped newlines), whether we reached the end of 58 * the file and whether we reached the end of the line. 59 */ 60 static int 61 orw_expect(struct t_file *tf, const char *expected, int lines, int eof, int eol) 62 { 63 int ch, lineno = 0; 64 char *got; 65 size_t len; 66 int ret; 67 68 got = openpam_readword(tf->file, &lineno, &len); 69 ret = 1; 70 if (t_ferror(tf)) 71 err(1, "%s(): %s", __func__, tf->name); 72 if (expected != NULL && got == NULL) { 73 t_printv("expected <<%s>>, got nothing\n", expected); 74 ret = 0; 75 } else if (expected == NULL && got != NULL) { 76 t_printv("expected nothing, got <<%s>>\n", got); 77 ret = 0; 78 } else if (expected != NULL && got != NULL && strcmp(expected, got) != 0) { 79 t_printv("expected <<%s>>, got <<%s>>\n", expected, got); 80 ret = 0; 81 } 82 free(got); 83 if (lineno != lines) { 84 t_printv("expected to advance %d lines, advanced %d lines\n", 85 lines, lineno); 86 ret = 0; 87 } 88 if (eof && !t_feof(tf)) { 89 t_printv("expected EOF, but didn't get it\n"); 90 ret = 0; 91 } 92 if (!eof && t_feof(tf)) { 93 t_printv("didn't expect EOF, but got it anyway\n"); 94 ret = 0; 95 } 96 ch = fgetc(tf->file); 97 if (t_ferror(tf)) 98 err(1, "%s(): %s", __func__, tf->name); 99 if (eol && ch != '\n') { 100 t_printv("expected EOL, but didn't get it\n"); 101 ret = 0; 102 } else if (!eol && ch == '\n') { 103 t_printv("didn't expect EOL, but got it anyway\n"); 104 ret = 0; 105 } 106 if (ch != EOF) 107 ungetc(ch, tf->file); 108 return (ret); 109 } 110 111 112 /*************************************************************************** 113 * Lines without words 114 */ 115 116 T_FUNC(empty_input, "empty input") 117 { 118 struct t_file *tf; 119 int ret; 120 121 tf = t_fopen(NULL); 122 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 123 t_fclose(tf); 124 return (ret); 125 } 126 127 T_FUNC(empty_line, "empty line") 128 { 129 struct t_file *tf; 130 int ret; 131 132 tf = t_fopen(NULL); 133 t_fprintf(tf, "\n"); 134 t_frewind(tf); 135 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 136 t_fclose(tf); 137 return (ret); 138 } 139 140 T_FUNC(unterminated_line, "unterminated line") 141 { 142 struct t_file *tf; 143 int ret; 144 145 tf = t_fopen(NULL); 146 t_fprintf(tf, " "); 147 t_frewind(tf); 148 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 149 t_fclose(tf); 150 return (ret); 151 } 152 153 T_FUNC(single_whitespace, "single whitespace") 154 { 155 struct t_file *tf; 156 int ret; 157 158 tf = t_fopen(NULL); 159 t_fprintf(tf, " \n"); 160 t_frewind(tf); 161 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 162 t_fclose(tf); 163 return (ret); 164 } 165 166 T_FUNC(multiple_whitespace, "multiple whitespace") 167 { 168 struct t_file *tf; 169 int ret; 170 171 tf = t_fopen(NULL); 172 t_fprintf(tf, " \t\r\n"); 173 t_frewind(tf); 174 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 175 t_fclose(tf); 176 return (ret); 177 } 178 179 T_FUNC(comment, "comment") 180 { 181 struct t_file *tf; 182 int ret; 183 184 tf = t_fopen(NULL); 185 t_fprintf(tf, "# comment\n"); 186 t_frewind(tf); 187 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 188 t_fclose(tf); 189 return (ret); 190 } 191 192 T_FUNC(whitespace_before_comment, "whitespace before comment") 193 { 194 struct t_file *tf; 195 int ret; 196 197 tf = t_fopen(NULL); 198 t_fprintf(tf, " # comment\n"); 199 t_frewind(tf); 200 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 201 t_fclose(tf); 202 return (ret); 203 } 204 205 T_FUNC(single_quoted_comment, "single-quoted comment") 206 { 207 struct t_file *tf; 208 int ret; 209 210 tf = t_fopen(NULL); 211 t_fprintf(tf, " '# comment'\n"); 212 t_frewind(tf); 213 ret = orw_expect(tf, "# comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 214 t_fclose(tf); 215 return (ret); 216 } 217 218 T_FUNC(double_quoted_comment, "double-quoted comment") 219 { 220 struct t_file *tf; 221 int ret; 222 223 tf = t_fopen(NULL); 224 t_fprintf(tf, " \"# comment\"\n"); 225 t_frewind(tf); 226 ret = orw_expect(tf, "# comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 227 t_fclose(tf); 228 return (ret); 229 } 230 231 T_FUNC(comment_at_eof, "comment at end of file") 232 { 233 struct t_file *tf; 234 int ret; 235 236 tf = t_fopen(NULL); 237 t_fprintf(tf, "# comment"); 238 t_frewind(tf); 239 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 240 t_fclose(tf); 241 return (ret); 242 } 243 244 245 /*************************************************************************** 246 * Simple cases - no quotes or escapes 247 */ 248 249 T_FUNC(single_word, "single word") 250 { 251 const char *word = "hello"; 252 struct t_file *tf; 253 int ret; 254 255 tf = t_fopen(NULL); 256 t_fprintf(tf, "%s\n", word); 257 t_frewind(tf); 258 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 259 t_fclose(tf); 260 return (ret); 261 } 262 263 T_FUNC(single_whitespace_before_word, "single whitespace before word") 264 { 265 const char *word = "hello"; 266 struct t_file *tf; 267 int ret; 268 269 tf = t_fopen(NULL); 270 t_fprintf(tf, " %s\n", word); 271 t_frewind(tf); 272 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 273 t_fclose(tf); 274 return (ret); 275 } 276 277 T_FUNC(double_whitespace_before_word, "double whitespace before word") 278 { 279 const char *word = "hello"; 280 struct t_file *tf; 281 int ret; 282 283 tf = t_fopen(NULL); 284 t_fprintf(tf, " %s\n", word); 285 t_frewind(tf); 286 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 287 t_fclose(tf); 288 return (ret); 289 } 290 291 T_FUNC(single_whitespace_after_word, "single whitespace after word") 292 { 293 const char *word = "hello"; 294 struct t_file *tf; 295 int ret; 296 297 tf = t_fopen(NULL); 298 t_fprintf(tf, "%s \n", word); 299 t_frewind(tf); 300 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 301 t_fclose(tf); 302 return (ret); 303 } 304 305 T_FUNC(double_whitespace_after_word, "double whitespace after word") 306 { 307 const char *word = "hello"; 308 struct t_file *tf; 309 int ret; 310 311 tf = t_fopen(NULL); 312 t_fprintf(tf, "%s \n", word); 313 t_frewind(tf); 314 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 315 t_fclose(tf); 316 return (ret); 317 } 318 319 T_FUNC(comment_after_word, "comment after word") 320 { 321 const char *word = "hello"; 322 struct t_file *tf; 323 int ret; 324 325 tf = t_fopen(NULL); 326 t_fprintf(tf, "%s # comment\n", word); 327 t_frewind(tf); 328 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 329 orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 330 t_fclose(tf); 331 return (ret); 332 } 333 334 T_FUNC(word_containing_hash, "word containing hash") 335 { 336 const char *word = "hello#world"; 337 struct t_file *tf; 338 int ret; 339 340 tf = t_fopen(NULL); 341 t_fprintf(tf, "%s\n", word); 342 t_frewind(tf); 343 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 344 t_fclose(tf); 345 return (ret); 346 } 347 348 T_FUNC(two_words, "two words") 349 { 350 const char *word[] = { "hello", "world" }; 351 struct t_file *tf; 352 int ret; 353 354 tf = t_fopen(NULL); 355 t_fprintf(tf, "%s %s\n", word[0], word[1]); 356 t_frewind(tf); 357 ret = orw_expect(tf, word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 358 orw_expect(tf, word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 359 t_fclose(tf); 360 return (ret); 361 } 362 363 364 /*************************************************************************** 365 * Escapes 366 */ 367 368 T_FUNC(naked_escape, "naked escape") 369 { 370 struct t_file *tf; 371 int ret; 372 373 tf = t_fopen(NULL); 374 t_fprintf(tf, "\\"); 375 t_frewind(tf); 376 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 377 t_fclose(tf); 378 return (ret); 379 } 380 381 T_FUNC(escaped_escape, "escaped escape") 382 { 383 struct t_file *tf; 384 int ret; 385 386 tf = t_fopen(NULL); 387 t_fprintf(tf, "\\\\\n"); 388 t_frewind(tf); 389 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 390 t_fclose(tf); 391 return (ret); 392 } 393 394 T_FUNC(escaped_whitespace, "escaped whitespace") 395 { 396 struct t_file *tf; 397 int ret; 398 399 tf = t_fopen(NULL); 400 t_fprintf(tf, "\\ \\\t \\\r \\\n\n"); 401 t_frewind(tf); 402 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 403 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 404 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 405 /* this last one is a line continuation */ 406 orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 407 t_fclose(tf); 408 return (ret); 409 } 410 411 T_FUNC(escaped_newline_before_word, "escaped newline before word") 412 { 413 struct t_file *tf; 414 int ret; 415 416 tf = t_fopen(NULL); 417 t_fprintf(tf, "\\\nhello world\n"); 418 t_frewind(tf); 419 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 420 t_fclose(tf); 421 return (ret); 422 } 423 424 T_FUNC(escaped_newline_within_word, "escaped newline within word") 425 { 426 struct t_file *tf; 427 int ret; 428 429 tf = t_fopen(NULL); 430 t_fprintf(tf, "hello\\\nworld\n"); 431 t_frewind(tf); 432 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 433 t_fclose(tf); 434 return (ret); 435 } 436 437 T_FUNC(escaped_newline_after_word, "escaped newline after word") 438 { 439 struct t_file *tf; 440 int ret; 441 442 tf = t_fopen(NULL); 443 t_fprintf(tf, "hello\\\n world\n"); 444 t_frewind(tf); 445 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 446 t_fclose(tf); 447 return (ret); 448 } 449 450 T_FUNC(escaped_letter, "escaped letter") 451 { 452 struct t_file *tf; 453 int ret; 454 455 tf = t_fopen(NULL); 456 t_fprintf(tf, "\\z\n"); 457 t_frewind(tf); 458 ret = orw_expect(tf, "z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 459 t_fclose(tf); 460 return (ret); 461 } 462 463 T_FUNC(escaped_comment, "escaped comment") 464 { 465 struct t_file *tf; 466 int ret; 467 468 tf = t_fopen(NULL); 469 t_fprintf(tf, " \\# comment\n"); 470 t_frewind(tf); 471 ret = orw_expect(tf, "#", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 472 orw_expect(tf, "comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 473 t_fclose(tf); 474 return (ret); 475 } 476 477 T_FUNC(escape_at_eof, "escape at end of file") 478 { 479 struct t_file *tf; 480 int ret; 481 482 tf = t_fopen(NULL); 483 t_fprintf(tf, "z\\"); 484 t_frewind(tf); 485 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 486 t_fclose(tf); 487 return (ret); 488 } 489 490 491 /*************************************************************************** 492 * Quotes 493 */ 494 495 T_FUNC(naked_single_quote, "naked single quote") 496 { 497 struct t_file *tf; 498 int ret; 499 500 tf = t_fopen(NULL); 501 t_fprintf(tf, "'"); 502 t_frewind(tf); 503 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 504 t_fclose(tf); 505 return (ret); 506 } 507 508 T_FUNC(naked_double_quote, "naked double quote") 509 { 510 struct t_file *tf; 511 int ret; 512 513 tf = t_fopen(NULL); 514 t_fprintf(tf, "\""); 515 t_frewind(tf); 516 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 517 t_fclose(tf); 518 return (ret); 519 } 520 521 T_FUNC(empty_single_quotes, "empty single quotes") 522 { 523 struct t_file *tf; 524 int ret; 525 526 tf = t_fopen(NULL); 527 t_fprintf(tf, "''\n"); 528 t_frewind(tf); 529 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 530 t_fclose(tf); 531 return (ret); 532 } 533 534 T_FUNC(empty_double_quotes, "empty double quotes") 535 { 536 struct t_file *tf; 537 int ret; 538 539 tf = t_fopen(NULL); 540 t_fprintf(tf, "\"\"\n"); 541 t_frewind(tf); 542 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 543 t_fclose(tf); 544 return (ret); 545 } 546 547 T_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes") 548 { 549 struct t_file *tf; 550 int ret; 551 552 tf = t_fopen(NULL); 553 t_fprintf(tf, "\"' '\"\n"); 554 t_frewind(tf); 555 ret = orw_expect(tf, "' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 556 t_fclose(tf); 557 return (ret); 558 } 559 560 T_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes") 561 { 562 struct t_file *tf; 563 int ret; 564 565 tf = t_fopen(NULL); 566 t_fprintf(tf, "'\" \"'\n"); 567 t_frewind(tf); 568 ret = orw_expect(tf, "\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 569 t_fclose(tf); 570 return (ret); 571 } 572 573 T_FUNC(single_quoted_whitespace, "single-quoted whitespace") 574 { 575 struct t_file *tf; 576 int ret; 577 578 tf = t_fopen(NULL); 579 t_fprintf(tf, "' ' '\t' '\r' '\n'\n"); 580 t_frewind(tf); 581 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 582 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 583 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 584 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 585 t_fclose(tf); 586 return (ret); 587 } 588 589 T_FUNC(double_quoted_whitespace, "double-quoted whitespace") 590 { 591 struct t_file *tf; 592 int ret; 593 594 tf = t_fopen(NULL); 595 t_fprintf(tf, "\" \" \"\t\" \"\r\" \"\n\"\n"); 596 t_frewind(tf); 597 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 598 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 599 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 600 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 601 t_fclose(tf); 602 return (ret); 603 } 604 605 T_FUNC(single_quoted_words, "single-quoted words") 606 { 607 struct t_file *tf; 608 int ret; 609 610 tf = t_fopen(NULL); 611 t_fprintf(tf, "'hello world'\n"); 612 t_frewind(tf); 613 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 614 t_fclose(tf); 615 return (ret); 616 } 617 618 T_FUNC(double_quoted_words, "double-quoted words") 619 { 620 struct t_file *tf; 621 int ret; 622 623 tf = t_fopen(NULL); 624 t_fprintf(tf, "\"hello world\"\n"); 625 t_frewind(tf); 626 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 627 t_fclose(tf); 628 return (ret); 629 } 630 631 632 /*************************************************************************** 633 * Combinations of quoted and unquoted text 634 */ 635 636 T_FUNC(single_quote_before_word, "single quote before word") 637 { 638 struct t_file *tf; 639 int ret; 640 641 tf = t_fopen(NULL); 642 t_fprintf(tf, "'hello 'world\n"); 643 t_frewind(tf); 644 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 645 t_fclose(tf); 646 return (ret); 647 } 648 649 T_FUNC(double_quote_before_word, "double quote before word") 650 { 651 struct t_file *tf; 652 int ret; 653 654 tf = t_fopen(NULL); 655 t_fprintf(tf, "\"hello \"world\n"); 656 t_frewind(tf); 657 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 658 t_fclose(tf); 659 return (ret); 660 } 661 662 T_FUNC(single_quote_within_word, "single quote within word") 663 { 664 struct t_file *tf; 665 int ret; 666 667 tf = t_fopen(NULL); 668 t_fprintf(tf, "hello' 'world\n"); 669 t_frewind(tf); 670 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 671 t_fclose(tf); 672 return (ret); 673 } 674 675 T_FUNC(double_quote_within_word, "double quote within word") 676 { 677 struct t_file *tf; 678 int ret; 679 680 tf = t_fopen(NULL); 681 t_fprintf(tf, "hello\" \"world\n"); 682 t_frewind(tf); 683 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 684 t_fclose(tf); 685 return (ret); 686 } 687 688 T_FUNC(single_quote_after_word, "single quote after word") 689 { 690 struct t_file *tf; 691 int ret; 692 693 tf = t_fopen(NULL); 694 t_fprintf(tf, "hello' world'\n"); 695 t_frewind(tf); 696 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 697 t_fclose(tf); 698 return (ret); 699 } 700 701 T_FUNC(double_quote_after_word, "double quote after word") 702 { 703 struct t_file *tf; 704 int ret; 705 706 tf = t_fopen(NULL); 707 t_fprintf(tf, "hello\" world\"\n"); 708 t_frewind(tf); 709 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 710 t_fclose(tf); 711 return (ret); 712 } 713 714 715 /*************************************************************************** 716 * Combinations of escape and quotes 717 */ 718 719 T_FUNC(escaped_single_quote, 720 "escaped single quote") 721 { 722 struct t_file *tf; 723 int ret; 724 725 tf = t_fopen(NULL); 726 t_fprintf(tf, "\\'\n"); 727 t_frewind(tf); 728 ret = orw_expect(tf, "'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 729 t_fclose(tf); 730 return (ret); 731 } 732 733 T_FUNC(escaped_double_quote, 734 "escaped double quote") 735 { 736 struct t_file *tf; 737 int ret; 738 739 tf = t_fopen(NULL); 740 t_fprintf(tf, "\\\"\n"); 741 t_frewind(tf); 742 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 743 t_fclose(tf); 744 return (ret); 745 } 746 747 T_FUNC(escaped_whitespace_within_single_quotes, 748 "escaped whitespace within single quotes") 749 { 750 struct t_file *tf; 751 int ret; 752 753 tf = t_fopen(NULL); 754 t_fprintf(tf, "'\\ ' '\\\t' '\\\r' '\\\n'\n"); 755 t_frewind(tf); 756 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 757 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 758 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 759 orw_expect(tf, "\\\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 760 t_fclose(tf); 761 return (ret); 762 } 763 764 T_FUNC(escaped_whitespace_within_double_quotes, 765 "escaped whitespace within double quotes") 766 { 767 struct t_file *tf; 768 int ret; 769 770 tf = t_fopen(NULL); 771 t_fprintf(tf, "\"\\ \" \"\\\t\" \"\\\r\" \"\\\n\"\n"); 772 t_frewind(tf); 773 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 774 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 775 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 776 /* this last one is a line continuation */ 777 orw_expect(tf, "", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 778 t_fclose(tf); 779 return (ret); 780 } 781 782 T_FUNC(escaped_letter_within_single_quotes, 783 "escaped letter within single quotes") 784 { 785 struct t_file *tf; 786 int ret; 787 788 tf = t_fopen(NULL); 789 t_fprintf(tf, "'\\z'\n"); 790 t_frewind(tf); 791 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 792 t_fclose(tf); 793 return (ret); 794 } 795 796 T_FUNC(escaped_letter_within_double_quotes, 797 "escaped letter within double quotes") 798 { 799 struct t_file *tf; 800 int ret; 801 802 tf = t_fopen(NULL); 803 t_fprintf(tf, "\"\\z\"\n"); 804 t_frewind(tf); 805 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 806 t_fclose(tf); 807 return (ret); 808 } 809 810 T_FUNC(escaped_escape_within_single_quotes, 811 "escaped escape within single quotes") 812 { 813 struct t_file *tf; 814 int ret; 815 816 tf = t_fopen(NULL); 817 t_fprintf(tf, "'\\\\'\n"); 818 t_frewind(tf); 819 ret = orw_expect(tf, "\\\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 820 t_fclose(tf); 821 return (ret); 822 } 823 824 T_FUNC(escaped_escape_within_double_quotes, 825 "escaped escape within double quotes") 826 { 827 struct t_file *tf; 828 int ret; 829 830 tf = t_fopen(NULL); 831 t_fprintf(tf, "\"\\\\\"\n"); 832 t_frewind(tf); 833 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 834 t_fclose(tf); 835 return (ret); 836 } 837 838 T_FUNC(escaped_single_quote_within_single_quotes, 839 "escaped single quote within single quotes") 840 { 841 struct t_file *tf; 842 int ret; 843 844 tf = t_fopen(NULL); 845 t_fprintf(tf, "'\\''\n"); 846 t_frewind(tf); 847 ret = orw_expect(tf, NULL, 1 /*lines*/, 1 /*eof*/, 0 /*eol*/); 848 t_fclose(tf); 849 return (ret); 850 } 851 852 T_FUNC(escaped_double_quote_within_single_quotes, 853 "escaped double quote within single quotes") 854 { 855 struct t_file *tf; 856 int ret; 857 858 tf = t_fopen(NULL); 859 t_fprintf(tf, "'\\\"'\n"); 860 t_frewind(tf); 861 ret = orw_expect(tf, "\\\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 862 t_fclose(tf); 863 return (ret); 864 } 865 866 T_FUNC(escaped_single_quote_within_double_quotes, 867 "escaped single quote within double quotes") 868 { 869 struct t_file *tf; 870 int ret; 871 872 tf = t_fopen(NULL); 873 t_fprintf(tf, "\"\\'\"\n"); 874 t_frewind(tf); 875 ret = orw_expect(tf, "\\'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 876 t_fclose(tf); 877 return (ret); 878 } 879 880 T_FUNC(escaped_double_quote_within_double_quotes, 881 "escaped double quote within double quotes") 882 { 883 struct t_file *tf; 884 int ret; 885 886 tf = t_fopen(NULL); 887 t_fprintf(tf, "\"\\\"\"\n"); 888 t_frewind(tf); 889 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 890 t_fclose(tf); 891 return (ret); 892 } 893 894 895 /*************************************************************************** 896 * Line continuation 897 */ 898 899 T_FUNC(line_continuation_within_whitespace, "line continuation within whitespace") 900 { 901 struct t_file *tf; 902 int ret; 903 904 tf = t_fopen(NULL); 905 t_fprintf(tf, "hello \\\n world\n"); 906 t_frewind(tf); 907 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 908 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 909 t_fclose(tf); 910 return (ret); 911 } 912 913 T_FUNC(line_continuation_before_whitespace, "line continuation before whitespace") 914 { 915 struct t_file *tf; 916 int ret; 917 918 tf = t_fopen(NULL); 919 t_fprintf(tf, "hello\\\n world\n"); 920 t_frewind(tf); 921 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 922 orw_expect(tf, "world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 923 t_fclose(tf); 924 return (ret); 925 } 926 927 T_FUNC(line_continuation_after_whitespace, "line continuation after whitespace") 928 { 929 struct t_file *tf; 930 int ret; 931 932 tf = t_fopen(NULL); 933 t_fprintf(tf, "hello \\\nworld\n"); 934 t_frewind(tf); 935 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 936 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 937 t_fclose(tf); 938 return (ret); 939 } 940 941 T_FUNC(line_continuation_within_word, "line continuation within word") 942 { 943 struct t_file *tf; 944 int ret; 945 946 tf = t_fopen(NULL); 947 t_fprintf(tf, "hello\\\nworld\n"); 948 t_frewind(tf); 949 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 950 t_fclose(tf); 951 return (ret); 952 } 953 954 955 /*************************************************************************** 956 * Boilerplate 957 */ 958 959 static int 960 t_prepare(int argc, char *argv[]) 961 { 962 963 (void)argc; 964 (void)argv; 965 966 T(empty_input); 967 T(empty_line); 968 T(unterminated_line); 969 T(single_whitespace); 970 T(multiple_whitespace); 971 T(comment); 972 T(whitespace_before_comment); 973 T(single_quoted_comment); 974 T(double_quoted_comment); 975 T(comment_at_eof); 976 977 T(single_word); 978 T(single_whitespace_before_word); 979 T(double_whitespace_before_word); 980 T(single_whitespace_after_word); 981 T(double_whitespace_after_word); 982 T(comment_after_word); 983 T(word_containing_hash); 984 T(two_words); 985 986 T(naked_escape); 987 T(escaped_escape); 988 T(escaped_whitespace); 989 T(escaped_newline_before_word); 990 T(escaped_newline_within_word); 991 T(escaped_newline_after_word); 992 T(escaped_letter); 993 T(escaped_comment); 994 T(escape_at_eof); 995 996 T(naked_single_quote); 997 T(naked_double_quote); 998 T(empty_single_quotes); 999 T(empty_double_quotes); 1000 T(single_quotes_within_double_quotes); 1001 T(double_quotes_within_single_quotes); 1002 T(single_quoted_whitespace); 1003 T(double_quoted_whitespace); 1004 T(single_quoted_words); 1005 T(double_quoted_words); 1006 1007 T(single_quote_before_word); 1008 T(double_quote_before_word); 1009 T(single_quote_within_word); 1010 T(double_quote_within_word); 1011 T(single_quote_after_word); 1012 T(double_quote_after_word); 1013 1014 T(escaped_single_quote); 1015 T(escaped_double_quote); 1016 T(escaped_whitespace_within_single_quotes); 1017 T(escaped_whitespace_within_double_quotes); 1018 T(escaped_letter_within_single_quotes); 1019 T(escaped_letter_within_double_quotes); 1020 T(escaped_escape_within_single_quotes); 1021 T(escaped_escape_within_double_quotes); 1022 T(escaped_single_quote_within_single_quotes); 1023 T(escaped_double_quote_within_single_quotes); 1024 T(escaped_single_quote_within_double_quotes); 1025 T(escaped_double_quote_within_double_quotes); 1026 1027 T(line_continuation_within_whitespace); 1028 T(line_continuation_before_whitespace); 1029 T(line_continuation_after_whitespace); 1030 T(line_continuation_within_word); 1031 1032 return (0); 1033 } 1034 1035 int 1036 main(int argc, char *argv[]) 1037 { 1038 1039 t_main(t_prepare, NULL, argc, argv); 1040 } 1041