xref: /netbsd-src/external/bsd/openpam/dist/t/t_openpam_readword.c (revision 0d9d0fd8a30be9a1924e715bbcf67a4a83efd262)
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
orw_expect(struct t_file * tf,const char * expected,int lines,int eof,int eol)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