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