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