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(line_continuation_in_whitespace, "line continuation in whitespace") 180 { 181 struct t_file *tf; 182 int ret; 183 184 tf = t_fopen(NULL); 185 t_fprintf(tf, " \\\n \n"); 186 t_frewind(tf); 187 ret = orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 188 t_fclose(tf); 189 return (ret); 190 } 191 192 T_FUNC(comment, "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(whitespace_before_comment, "whitespace before 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, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 214 t_fclose(tf); 215 return (ret); 216 } 217 218 T_FUNC(single_quoted_comment, "single-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(double_quoted_comment, "double-quoted comment") 232 { 233 struct t_file *tf; 234 int ret; 235 236 tf = t_fopen(NULL); 237 t_fprintf(tf, " \"# comment\"\n"); 238 t_frewind(tf); 239 ret = orw_expect(tf, "# comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 240 t_fclose(tf); 241 return (ret); 242 } 243 244 T_FUNC(comment_at_eof, "comment at end of file") 245 { 246 struct t_file *tf; 247 int ret; 248 249 tf = t_fopen(NULL); 250 t_fprintf(tf, "# comment"); 251 t_frewind(tf); 252 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 253 t_fclose(tf); 254 return (ret); 255 } 256 257 258 /*************************************************************************** 259 * Simple cases - no quotes or escapes 260 */ 261 262 T_FUNC(single_word, "single word") 263 { 264 const char *word = "hello"; 265 struct t_file *tf; 266 int ret; 267 268 tf = t_fopen(NULL); 269 t_fprintf(tf, "%s\n", word); 270 t_frewind(tf); 271 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 272 t_fclose(tf); 273 return (ret); 274 } 275 276 T_FUNC(single_whitespace_before_word, "single whitespace before word") 277 { 278 const char *word = "hello"; 279 struct t_file *tf; 280 int ret; 281 282 tf = t_fopen(NULL); 283 t_fprintf(tf, " %s\n", word); 284 t_frewind(tf); 285 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 286 t_fclose(tf); 287 return (ret); 288 } 289 290 T_FUNC(double_whitespace_before_word, "double whitespace before word") 291 { 292 const char *word = "hello"; 293 struct t_file *tf; 294 int ret; 295 296 tf = t_fopen(NULL); 297 t_fprintf(tf, " %s\n", word); 298 t_frewind(tf); 299 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 300 t_fclose(tf); 301 return (ret); 302 } 303 304 T_FUNC(single_whitespace_after_word, "single whitespace after word") 305 { 306 const char *word = "hello"; 307 struct t_file *tf; 308 int ret; 309 310 tf = t_fopen(NULL); 311 t_fprintf(tf, "%s \n", word); 312 t_frewind(tf); 313 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 314 t_fclose(tf); 315 return (ret); 316 } 317 318 T_FUNC(double_whitespace_after_word, "double whitespace after word") 319 { 320 const char *word = "hello"; 321 struct t_file *tf; 322 int ret; 323 324 tf = t_fopen(NULL); 325 t_fprintf(tf, "%s \n", word); 326 t_frewind(tf); 327 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 328 t_fclose(tf); 329 return (ret); 330 } 331 332 T_FUNC(comment_after_word, "comment after word") 333 { 334 const char *word = "hello"; 335 struct t_file *tf; 336 int ret; 337 338 tf = t_fopen(NULL); 339 t_fprintf(tf, "%s # comment\n", word); 340 t_frewind(tf); 341 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 342 orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 343 t_fclose(tf); 344 return (ret); 345 } 346 347 T_FUNC(word_containing_hash, "word containing hash") 348 { 349 const char *word = "hello#world"; 350 struct t_file *tf; 351 int ret; 352 353 tf = t_fopen(NULL); 354 t_fprintf(tf, "%s\n", word); 355 t_frewind(tf); 356 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 357 t_fclose(tf); 358 return (ret); 359 } 360 361 T_FUNC(two_words, "two words") 362 { 363 const char *word[] = { "hello", "world" }; 364 struct t_file *tf; 365 int ret; 366 367 tf = t_fopen(NULL); 368 t_fprintf(tf, "%s %s\n", word[0], word[1]); 369 t_frewind(tf); 370 ret = orw_expect(tf, word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 371 orw_expect(tf, word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 372 t_fclose(tf); 373 return (ret); 374 } 375 376 377 /*************************************************************************** 378 * Escapes 379 */ 380 381 T_FUNC(naked_escape, "naked escape") 382 { 383 struct t_file *tf; 384 int ret; 385 386 tf = t_fopen(NULL); 387 t_fprintf(tf, "\\"); 388 t_frewind(tf); 389 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 390 t_fclose(tf); 391 return (ret); 392 } 393 394 T_FUNC(escaped_escape, "escaped escape") 395 { 396 struct t_file *tf; 397 int ret; 398 399 tf = t_fopen(NULL); 400 t_fprintf(tf, "\\\\\n"); 401 t_frewind(tf); 402 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 403 t_fclose(tf); 404 return (ret); 405 } 406 407 T_FUNC(escaped_whitespace, "escaped whitespace") 408 { 409 struct t_file *tf; 410 int ret; 411 412 tf = t_fopen(NULL); 413 t_fprintf(tf, "\\ \\\t \\\r \\\n\n"); 414 t_frewind(tf); 415 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 416 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 417 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 418 /* this last one is a line continuation */ 419 orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 420 t_fclose(tf); 421 return (ret); 422 } 423 424 T_FUNC(escaped_newline_before_word, "escaped newline before word") 425 { 426 struct t_file *tf; 427 int ret; 428 429 tf = t_fopen(NULL); 430 t_fprintf(tf, "\\\nhello world\n"); 431 t_frewind(tf); 432 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 433 t_fclose(tf); 434 return (ret); 435 } 436 437 T_FUNC(escaped_newline_within_word, "escaped newline within word") 438 { 439 struct t_file *tf; 440 int ret; 441 442 tf = t_fopen(NULL); 443 t_fprintf(tf, "hello\\\nworld\n"); 444 t_frewind(tf); 445 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 446 t_fclose(tf); 447 return (ret); 448 } 449 450 T_FUNC(escaped_newline_after_word, "escaped newline after word") 451 { 452 struct t_file *tf; 453 int ret; 454 455 tf = t_fopen(NULL); 456 t_fprintf(tf, "hello\\\n world\n"); 457 t_frewind(tf); 458 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 459 t_fclose(tf); 460 return (ret); 461 } 462 463 T_FUNC(escaped_letter, "escaped letter") 464 { 465 struct t_file *tf; 466 int ret; 467 468 tf = t_fopen(NULL); 469 t_fprintf(tf, "\\z\n"); 470 t_frewind(tf); 471 ret = orw_expect(tf, "z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 472 t_fclose(tf); 473 return (ret); 474 } 475 476 T_FUNC(escaped_comment, "escaped comment") 477 { 478 struct t_file *tf; 479 int ret; 480 481 tf = t_fopen(NULL); 482 t_fprintf(tf, " \\# comment\n"); 483 t_frewind(tf); 484 ret = orw_expect(tf, "#", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 485 orw_expect(tf, "comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 486 t_fclose(tf); 487 return (ret); 488 } 489 490 T_FUNC(escape_at_eof, "escape at end of file") 491 { 492 struct t_file *tf; 493 int ret; 494 495 tf = t_fopen(NULL); 496 t_fprintf(tf, "z\\"); 497 t_frewind(tf); 498 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 499 t_fclose(tf); 500 return (ret); 501 } 502 503 504 /*************************************************************************** 505 T_FUNC(escaped_comment, "escaped comment") 506 { 507 struct t_file *tf; 508 int ret; 509 510 tf = t_fopen(NULL); 511 t_fprintf(tf, " \\# comment\n"); 512 t_frewind(tf); 513 ret = orw_expect(tf, "#", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 514 orw_expect(tf, "comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 515 t_fclose(tf); 516 return (ret); 517 } 518 519 T_FUNC(escape_at_eof, "escape at end of file") 520 { 521 struct t_file *tf; 522 int ret; 523 524 tf = t_fopen(NULL); 525 t_fprintf(tf, "z\\"); 526 t_frewind(tf); 527 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 528 t_fclose(tf); 529 return (ret); 530 } 531 532 * Quotes 533 */ 534 535 T_FUNC(naked_single_quote, "naked single quote") 536 { 537 struct t_file *tf; 538 int ret; 539 540 tf = t_fopen(NULL); 541 t_fprintf(tf, "'"); 542 t_frewind(tf); 543 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 544 t_fclose(tf); 545 return (ret); 546 } 547 548 T_FUNC(naked_double_quote, "naked double quote") 549 { 550 struct t_file *tf; 551 int ret; 552 553 tf = t_fopen(NULL); 554 t_fprintf(tf, "\""); 555 t_frewind(tf); 556 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 557 t_fclose(tf); 558 return (ret); 559 } 560 561 T_FUNC(empty_single_quotes, "empty single quotes") 562 { 563 struct t_file *tf; 564 int ret; 565 566 tf = t_fopen(NULL); 567 t_fprintf(tf, "''\n"); 568 t_frewind(tf); 569 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 570 t_fclose(tf); 571 return (ret); 572 } 573 574 T_FUNC(empty_double_quotes, "empty double quotes") 575 { 576 struct t_file *tf; 577 int ret; 578 579 tf = t_fopen(NULL); 580 t_fprintf(tf, "\"\"\n"); 581 t_frewind(tf); 582 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 583 t_fclose(tf); 584 return (ret); 585 } 586 587 T_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes") 588 { 589 struct t_file *tf; 590 int ret; 591 592 tf = t_fopen(NULL); 593 t_fprintf(tf, "\"' '\"\n"); 594 t_frewind(tf); 595 ret = orw_expect(tf, "' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 596 t_fclose(tf); 597 return (ret); 598 } 599 600 T_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes") 601 { 602 struct t_file *tf; 603 int ret; 604 605 tf = t_fopen(NULL); 606 t_fprintf(tf, "'\" \"'\n"); 607 t_frewind(tf); 608 ret = orw_expect(tf, "\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 609 t_fclose(tf); 610 return (ret); 611 } 612 613 T_FUNC(single_quoted_whitespace, "single-quoted whitespace") 614 { 615 struct t_file *tf; 616 int ret; 617 618 tf = t_fopen(NULL); 619 t_fprintf(tf, "' ' '\t' '\r' '\n'\n"); 620 t_frewind(tf); 621 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 622 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 623 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 624 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 625 t_fclose(tf); 626 return (ret); 627 } 628 629 T_FUNC(double_quoted_whitespace, "double-quoted whitespace") 630 { 631 struct t_file *tf; 632 int ret; 633 634 tf = t_fopen(NULL); 635 t_fprintf(tf, "\" \" \"\t\" \"\r\" \"\n\"\n"); 636 t_frewind(tf); 637 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 638 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 639 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 640 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 641 t_fclose(tf); 642 return (ret); 643 } 644 645 T_FUNC(single_quoted_words, "single-quoted words") 646 { 647 struct t_file *tf; 648 int ret; 649 650 tf = t_fopen(NULL); 651 t_fprintf(tf, "'hello world'\n"); 652 t_frewind(tf); 653 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 654 t_fclose(tf); 655 return (ret); 656 } 657 658 T_FUNC(double_quoted_words, "double-quoted words") 659 { 660 struct t_file *tf; 661 int ret; 662 663 tf = t_fopen(NULL); 664 t_fprintf(tf, "\"hello world\"\n"); 665 t_frewind(tf); 666 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 667 t_fclose(tf); 668 return (ret); 669 } 670 671 672 /*************************************************************************** 673 * Combinations of quoted and unquoted text 674 */ 675 676 T_FUNC(single_quote_before_word, "single quote before word") 677 { 678 struct t_file *tf; 679 int ret; 680 681 tf = t_fopen(NULL); 682 t_fprintf(tf, "'hello 'world\n"); 683 t_frewind(tf); 684 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 685 t_fclose(tf); 686 return (ret); 687 } 688 689 T_FUNC(double_quote_before_word, "double quote before word") 690 { 691 struct t_file *tf; 692 int ret; 693 694 tf = t_fopen(NULL); 695 t_fprintf(tf, "\"hello \"world\n"); 696 t_frewind(tf); 697 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 698 t_fclose(tf); 699 return (ret); 700 } 701 702 T_FUNC(single_quote_within_word, "single quote within word") 703 { 704 struct t_file *tf; 705 int ret; 706 707 tf = t_fopen(NULL); 708 t_fprintf(tf, "hello' 'world\n"); 709 t_frewind(tf); 710 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 711 t_fclose(tf); 712 return (ret); 713 } 714 715 T_FUNC(double_quote_within_word, "double quote within word") 716 { 717 struct t_file *tf; 718 int ret; 719 720 tf = t_fopen(NULL); 721 t_fprintf(tf, "hello\" \"world\n"); 722 t_frewind(tf); 723 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 724 t_fclose(tf); 725 return (ret); 726 } 727 728 T_FUNC(single_quote_after_word, "single quote after word") 729 { 730 struct t_file *tf; 731 int ret; 732 733 tf = t_fopen(NULL); 734 t_fprintf(tf, "hello' world'\n"); 735 t_frewind(tf); 736 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 737 t_fclose(tf); 738 return (ret); 739 } 740 741 T_FUNC(double_quote_after_word, "double quote after word") 742 { 743 struct t_file *tf; 744 int ret; 745 746 tf = t_fopen(NULL); 747 t_fprintf(tf, "hello\" world\"\n"); 748 t_frewind(tf); 749 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 750 t_fclose(tf); 751 return (ret); 752 } 753 754 755 /*************************************************************************** 756 * Combinations of escape and quotes 757 */ 758 759 T_FUNC(escaped_single_quote, 760 "escaped single quote") 761 { 762 struct t_file *tf; 763 int ret; 764 765 tf = t_fopen(NULL); 766 t_fprintf(tf, "\\'\n"); 767 t_frewind(tf); 768 ret = orw_expect(tf, "'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 769 t_fclose(tf); 770 return (ret); 771 } 772 773 T_FUNC(escaped_double_quote, 774 "escaped double quote") 775 { 776 struct t_file *tf; 777 int ret; 778 779 tf = t_fopen(NULL); 780 t_fprintf(tf, "\\\"\n"); 781 t_frewind(tf); 782 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 783 t_fclose(tf); 784 return (ret); 785 } 786 787 T_FUNC(escaped_whitespace_within_single_quotes, 788 "escaped whitespace within single quotes") 789 { 790 struct t_file *tf; 791 int ret; 792 793 tf = t_fopen(NULL); 794 t_fprintf(tf, "'\\ ' '\\\t' '\\\r' '\\\n'\n"); 795 t_frewind(tf); 796 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 797 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 798 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 799 orw_expect(tf, "\\\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 800 t_fclose(tf); 801 return (ret); 802 } 803 804 T_FUNC(escaped_whitespace_within_double_quotes, 805 "escaped whitespace within double quotes") 806 { 807 struct t_file *tf; 808 int ret; 809 810 tf = t_fopen(NULL); 811 t_fprintf(tf, "\"\\ \" \"\\\t\" \"\\\r\" \"\\\n\"\n"); 812 t_frewind(tf); 813 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 814 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 815 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 816 /* this last one is a line continuation */ 817 orw_expect(tf, "", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 818 t_fclose(tf); 819 return (ret); 820 } 821 822 T_FUNC(escaped_letter_within_single_quotes, 823 "escaped letter within single quotes") 824 { 825 struct t_file *tf; 826 int ret; 827 828 tf = t_fopen(NULL); 829 t_fprintf(tf, "'\\z'\n"); 830 t_frewind(tf); 831 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 832 t_fclose(tf); 833 return (ret); 834 } 835 836 T_FUNC(escaped_letter_within_double_quotes, 837 "escaped letter within double quotes") 838 { 839 struct t_file *tf; 840 int ret; 841 842 tf = t_fopen(NULL); 843 t_fprintf(tf, "\"\\z\"\n"); 844 t_frewind(tf); 845 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 846 t_fclose(tf); 847 return (ret); 848 } 849 850 T_FUNC(escaped_escape_within_single_quotes, 851 "escaped escape within single quotes") 852 { 853 struct t_file *tf; 854 int ret; 855 856 tf = t_fopen(NULL); 857 t_fprintf(tf, "'\\\\'\n"); 858 t_frewind(tf); 859 ret = orw_expect(tf, "\\\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 860 t_fclose(tf); 861 return (ret); 862 } 863 864 T_FUNC(escaped_escape_within_double_quotes, 865 "escaped escape within double quotes") 866 { 867 struct t_file *tf; 868 int ret; 869 870 tf = t_fopen(NULL); 871 t_fprintf(tf, "\"\\\\\"\n"); 872 t_frewind(tf); 873 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 874 t_fclose(tf); 875 return (ret); 876 } 877 878 T_FUNC(escaped_single_quote_within_single_quotes, 879 "escaped single quote within single quotes") 880 { 881 struct t_file *tf; 882 int ret; 883 884 tf = t_fopen(NULL); 885 t_fprintf(tf, "'\\''\n"); 886 t_frewind(tf); 887 ret = orw_expect(tf, NULL, 1 /*lines*/, 1 /*eof*/, 0 /*eol*/); 888 t_fclose(tf); 889 return (ret); 890 } 891 892 T_FUNC(escaped_double_quote_within_single_quotes, 893 "escaped double quote within single quotes") 894 { 895 struct t_file *tf; 896 int ret; 897 898 tf = t_fopen(NULL); 899 t_fprintf(tf, "'\\\"'\n"); 900 t_frewind(tf); 901 ret = orw_expect(tf, "\\\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 902 t_fclose(tf); 903 return (ret); 904 } 905 906 T_FUNC(escaped_single_quote_within_double_quotes, 907 "escaped single quote within double quotes") 908 { 909 struct t_file *tf; 910 int ret; 911 912 tf = t_fopen(NULL); 913 t_fprintf(tf, "\"\\'\"\n"); 914 t_frewind(tf); 915 ret = orw_expect(tf, "\\'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 916 t_fclose(tf); 917 return (ret); 918 } 919 920 T_FUNC(escaped_double_quote_within_double_quotes, 921 "escaped double quote within double quotes") 922 { 923 struct t_file *tf; 924 int ret; 925 926 tf = t_fopen(NULL); 927 t_fprintf(tf, "\"\\\"\"\n"); 928 t_frewind(tf); 929 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 930 t_fclose(tf); 931 return (ret); 932 } 933 934 935 /*************************************************************************** 936 * Line continuation 937 */ 938 939 T_FUNC(line_continuation_within_whitespace, "line continuation within whitespace") 940 { 941 struct t_file *tf; 942 int ret; 943 944 tf = t_fopen(NULL); 945 t_fprintf(tf, "hello \\\n world\n"); 946 t_frewind(tf); 947 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 948 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 949 t_fclose(tf); 950 return (ret); 951 } 952 953 T_FUNC(line_continuation_before_whitespace, "line continuation before whitespace") 954 { 955 struct t_file *tf; 956 int ret; 957 958 tf = t_fopen(NULL); 959 t_fprintf(tf, "hello\\\n world\n"); 960 t_frewind(tf); 961 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 962 orw_expect(tf, "world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 963 t_fclose(tf); 964 return (ret); 965 } 966 967 T_FUNC(line_continuation_after_whitespace, "line continuation after whitespace") 968 { 969 struct t_file *tf; 970 int ret; 971 972 tf = t_fopen(NULL); 973 t_fprintf(tf, "hello \\\nworld\n"); 974 t_frewind(tf); 975 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 976 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 977 t_fclose(tf); 978 return (ret); 979 } 980 981 T_FUNC(line_continuation_within_word, "line continuation within word") 982 { 983 struct t_file *tf; 984 int ret; 985 986 tf = t_fopen(NULL); 987 t_fprintf(tf, "hello\\\nworld\n"); 988 t_frewind(tf); 989 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 990 t_fclose(tf); 991 return (ret); 992 } 993 994 995 /*************************************************************************** 996 * Boilerplate 997 */ 998 999 static int 1000 t_prepare(int argc, char *argv[]) 1001 { 1002 1003 (void)argc; 1004 (void)argv; 1005 1006 T(empty_input); 1007 T(empty_line); 1008 T(unterminated_line); 1009 T(single_whitespace); 1010 T(multiple_whitespace); 1011 T(comment); 1012 T(whitespace_before_comment); 1013 T(single_quoted_comment); 1014 T(double_quoted_comment); 1015 T(comment_at_eof); 1016 1017 T(single_word); 1018 T(single_whitespace_before_word); 1019 T(double_whitespace_before_word); 1020 T(single_whitespace_after_word); 1021 T(double_whitespace_after_word); 1022 T(comment_after_word); 1023 T(word_containing_hash); 1024 T(two_words); 1025 1026 T(naked_escape); 1027 T(escaped_escape); 1028 T(escaped_whitespace); 1029 T(escaped_newline_before_word); 1030 T(escaped_newline_within_word); 1031 T(escaped_newline_after_word); 1032 T(escaped_letter); 1033 T(escaped_comment); 1034 T(escape_at_eof); 1035 1036 T(naked_single_quote); 1037 T(naked_double_quote); 1038 T(empty_single_quotes); 1039 T(empty_double_quotes); 1040 T(single_quotes_within_double_quotes); 1041 T(double_quotes_within_single_quotes); 1042 T(single_quoted_whitespace); 1043 T(double_quoted_whitespace); 1044 T(single_quoted_words); 1045 T(double_quoted_words); 1046 1047 T(single_quote_before_word); 1048 T(double_quote_before_word); 1049 T(single_quote_within_word); 1050 T(double_quote_within_word); 1051 T(single_quote_after_word); 1052 T(double_quote_after_word); 1053 1054 T(escaped_single_quote); 1055 T(escaped_double_quote); 1056 T(escaped_whitespace_within_single_quotes); 1057 T(escaped_whitespace_within_double_quotes); 1058 T(escaped_letter_within_single_quotes); 1059 T(escaped_letter_within_double_quotes); 1060 T(escaped_escape_within_single_quotes); 1061 T(escaped_escape_within_double_quotes); 1062 T(escaped_single_quote_within_single_quotes); 1063 T(escaped_double_quote_within_single_quotes); 1064 T(escaped_single_quote_within_double_quotes); 1065 T(escaped_double_quote_within_double_quotes); 1066 1067 T(line_continuation_within_whitespace); 1068 T(line_continuation_before_whitespace); 1069 T(line_continuation_after_whitespace); 1070 T(line_continuation_within_word); 1071 1072 return (0); 1073 } 1074 1075 int 1076 main(int argc, char *argv[]) 1077 { 1078 1079 t_main(t_prepare, NULL, argc, argv); 1080 } 1081