]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/openpam/t/t_openpam_readword.c
Upgrade to OpenPAM Radula.
[FreeBSD/FreeBSD.git] / contrib / openpam / t / t_openpam_readword.c
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 }