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