Home | History | Annotate | Line # | Download | only in t
      1  1.1  christos /*-
      2  1.3  christos  * Copyright (c) 2012-2017 Dag-Erling Smrgrav
      3  1.1  christos  * All rights reserved.
      4  1.1  christos  *
      5  1.1  christos  * Redistribution and use in source and binary forms, with or without
      6  1.1  christos  * modification, are permitted provided that the following conditions
      7  1.1  christos  * are met:
      8  1.1  christos  * 1. Redistributions of source code must retain the above copyright
      9  1.2  christos  *    notice, this list of conditions and the following disclaimer.
     10  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     11  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     12  1.1  christos  *    documentation and/or other materials provided with the distribution.
     13  1.1  christos  * 3. The name of the author may not be used to endorse or promote
     14  1.1  christos  *    products derived from this software without specific prior written
     15  1.1  christos  *    permission.
     16  1.1  christos  *
     17  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     18  1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  1.1  christos  * SUCH DAMAGE.
     28  1.1  christos  */
     29  1.1  christos 
     30  1.1  christos #ifdef HAVE_CONFIG_H
     31  1.1  christos # include "config.h"
     32  1.1  christos #endif
     33  1.1  christos 
     34  1.1  christos #include <err.h>
     35  1.3  christos #include <stdint.h>
     36  1.1  christos #include <stdio.h>
     37  1.1  christos #include <stdlib.h>
     38  1.1  christos #include <string.h>
     39  1.1  christos 
     40  1.3  christos #include <cryb/test.h>
     41  1.3  christos 
     42  1.1  christos #include <security/pam_appl.h>
     43  1.1  christos #include <security/openpam.h>
     44  1.1  christos 
     45  1.1  christos #include "openpam_impl.h"
     46  1.3  christos 
     47  1.3  christos #define T_FUNC(n, d)							\
     48  1.3  christos 	static const char *t_ ## n ## _desc = d;			\
     49  1.3  christos 	static int t_ ## n ## _func(OPENPAM_UNUSED(char **desc),	\
     50  1.3  christos 	    OPENPAM_UNUSED(void *arg))
     51  1.3  christos 
     52  1.3  christos #define T(n)								\
     53  1.3  christos 	t_add_test(&t_ ## n ## _func, NULL, "%s", t_ ## n ## _desc)
     54  1.1  christos 
     55  1.1  christos /*
     56  1.1  christos  * Read a line from the temp file and verify that the result matches our
     57  1.1  christos  * expectations: whether a line was read at all, how many and which words
     58  1.1  christos  * it contained, how many lines were read (in case of quoted or escaped
     59  1.1  christos  * newlines) and whether we reached the end of the file.
     60  1.1  christos  */
     61  1.1  christos static int
     62  1.2  christos orlv_expect(struct t_file *tf, const char **expectedv, int lines, int eof)
     63  1.1  christos {
     64  1.1  christos 	int expectedc, gotc, i, lineno = 0;
     65  1.1  christos 	char **gotv;
     66  1.3  christos 	int ret;
     67  1.1  christos 
     68  1.3  christos 	ret = 1;
     69  1.1  christos 	expectedc = 0;
     70  1.1  christos 	if (expectedv != NULL)
     71  1.1  christos 		while (expectedv[expectedc] != NULL)
     72  1.1  christos 			++expectedc;
     73  1.2  christos 	gotv = openpam_readlinev(tf->file, &lineno, &gotc);
     74  1.2  christos 	if (t_ferror(tf))
     75  1.2  christos 		err(1, "%s(): %s", __func__, tf->name);
     76  1.1  christos 	if (expectedv != NULL && gotv == NULL) {
     77  1.3  christos 		t_printv("expected %d words, got nothing\n", expectedc);
     78  1.3  christos 		ret = 0;
     79  1.3  christos 	} else if (expectedv == NULL && gotv != NULL) {
     80  1.3  christos 		t_printv("expected nothing, got %d words\n", gotc);
     81  1.3  christos 		ret = 0;
     82  1.3  christos 	} else if (expectedv != NULL && gotv != NULL) {
     83  1.1  christos 		if (expectedc != gotc) {
     84  1.3  christos 			t_printv("expected %d words, got %d\n",
     85  1.1  christos 			    expectedc, gotc);
     86  1.3  christos 			ret = 0;
     87  1.1  christos 		}
     88  1.1  christos 		for (i = 0; i < gotc; ++i) {
     89  1.1  christos 			if (strcmp(expectedv[i], gotv[i]) != 0) {
     90  1.3  christos 				t_printv("word %d: expected <<%s>>, "
     91  1.1  christos 				    "got <<%s>>\n", i, expectedv[i], gotv[i]);
     92  1.3  christos 				ret = 0;
     93  1.1  christos 			}
     94  1.1  christos 		}
     95  1.1  christos 	}
     96  1.3  christos 	FREEV(gotc, gotv);
     97  1.1  christos 	if (lineno != lines) {
     98  1.3  christos 		t_printv("expected to advance %d lines, advanced %d lines\n",
     99  1.1  christos 		    lines, lineno);
    100  1.3  christos 		ret = 0;
    101  1.1  christos 	}
    102  1.2  christos 	if (eof && !t_feof(tf)) {
    103  1.3  christos 		t_printv("expected EOF, but didn't get it\n");
    104  1.3  christos 		ret = 0;
    105  1.3  christos 	} else if (!eof && t_feof(tf)) {
    106  1.3  christos 		t_printv("didn't expect EOF, but got it anyway\n");
    107  1.3  christos 		ret = 0;
    108  1.1  christos 	}
    109  1.3  christos 	return (ret);
    110  1.1  christos }
    111  1.1  christos 
    112  1.1  christos 
    113  1.1  christos /***************************************************************************
    115  1.1  christos  * Commonly-used lines
    116  1.1  christos  */
    117  1.1  christos 
    118  1.1  christos static const char *empty[] = {
    119  1.1  christos 	NULL
    120  1.1  christos };
    121  1.1  christos 
    122  1.1  christos static const char *hello[] = {
    123  1.1  christos 	"hello",
    124  1.1  christos 	NULL
    125  1.1  christos };
    126  1.1  christos 
    127  1.1  christos static const char *hello_world[] = {
    128  1.1  christos 	"hello",
    129  1.1  christos 	"world",
    130  1.1  christos 	NULL
    131  1.1  christos };
    132  1.3  christos 
    133  1.3  christos static const char *numbers[] = {
    134  1.3  christos 	"zero", "one", "two", "three", "four", "five", "six", "seven",
    135  1.3  christos 	"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
    136  1.3  christos 	"fifteen", "sixteen", "seventeen", "nineteen", "twenty",
    137  1.3  christos 	"twenty-one", "twenty-two", "twenty-three", "twenty-four",
    138  1.3  christos 	"twenty-five", "twenty-six", "twenty-seven", "twenty-eight",
    139  1.3  christos 	"twenty-nine", "thirty", "thirty-one", "thirty-two", "thirty-three",
    140  1.3  christos 	"thirty-four", "thirty-five", "thirty-six", "thirty-seven",
    141  1.3  christos 	"thirty-eight", "thirty-nine", "fourty", "fourty-one", "fourty-two",
    142  1.3  christos 	"fourty-three", "fourty-four", "fourty-five", "fourty-six",
    143  1.3  christos 	"fourty-seven", "fourty-eight", "fourty-nine", "fifty", "fifty-one",
    144  1.3  christos 	"fifty-two", "fifty-three", "fifty-four", "fifty-five", "fifty-six",
    145  1.3  christos 	"fifty-seven", "fifty-eight", "fifty-nine", "sixty", "sixty-one",
    146  1.3  christos 	"sixty-two", "sixty-three",
    147  1.3  christos 	NULL
    148  1.3  christos };
    149  1.1  christos 
    150  1.1  christos 
    151  1.1  christos /***************************************************************************
    153  1.1  christos  * Lines without words
    154  1.1  christos  */
    155  1.1  christos 
    156  1.2  christos T_FUNC(empty_input, "empty input")
    157  1.1  christos {
    158  1.1  christos 	struct t_file *tf;
    159  1.2  christos 	int ret;
    160  1.2  christos 
    161  1.2  christos 	tf = t_fopen(NULL);
    162  1.1  christos 	ret = orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/);
    163  1.1  christos 	t_fclose(tf);
    164  1.1  christos 	return (ret);
    165  1.1  christos }
    166  1.1  christos 
    167  1.2  christos T_FUNC(empty_line, "empty line")
    168  1.1  christos {
    169  1.1  christos 	struct t_file *tf;
    170  1.2  christos 	int ret;
    171  1.2  christos 
    172  1.2  christos 	tf = t_fopen(NULL);
    173  1.2  christos 	t_fprintf(tf, "\n");
    174  1.2  christos 	t_frewind(tf);
    175  1.1  christos 	ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/);
    176  1.1  christos 	t_fclose(tf);
    177  1.1  christos 	return (ret);
    178  1.1  christos }
    179  1.1  christos 
    180  1.2  christos T_FUNC(unterminated_empty_line, "unterminated empty line")
    181  1.1  christos {
    182  1.1  christos 	struct t_file *tf;
    183  1.2  christos 	int ret;
    184  1.2  christos 
    185  1.2  christos 	tf = t_fopen(NULL);
    186  1.2  christos 	t_fprintf(tf, " ");
    187  1.2  christos 	t_frewind(tf);
    188  1.1  christos 	ret = orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/);
    189  1.1  christos 	t_fclose(tf);
    190  1.1  christos 	return (ret);
    191  1.1  christos }
    192  1.1  christos 
    193  1.2  christos T_FUNC(whitespace, "whitespace")
    194  1.1  christos {
    195  1.1  christos 	struct t_file *tf;
    196  1.2  christos 	int ret;
    197  1.2  christos 
    198  1.2  christos 	tf = t_fopen(NULL);
    199  1.2  christos 	t_fprintf(tf, " \n");
    200  1.2  christos 	t_frewind(tf);
    201  1.1  christos 	ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/);
    202  1.1  christos 	t_fclose(tf);
    203  1.1  christos 	return (ret);
    204  1.1  christos }
    205  1.1  christos 
    206  1.2  christos T_FUNC(comment, "comment")
    207  1.1  christos {
    208  1.1  christos 	struct t_file *tf;
    209  1.2  christos 	int ret;
    210  1.2  christos 
    211  1.2  christos 	tf = t_fopen(NULL);
    212  1.2  christos 	t_fprintf(tf, "# comment\n");
    213  1.2  christos 	t_frewind(tf);
    214  1.1  christos 	ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/);
    215  1.1  christos 	t_fclose(tf);
    216  1.1  christos 	return (ret);
    217  1.1  christos }
    218  1.1  christos 
    219  1.2  christos T_FUNC(whitespace_before_comment, "whitespace before comment")
    220  1.1  christos {
    221  1.1  christos 	struct t_file *tf;
    222  1.2  christos 	int ret;
    223  1.2  christos 
    224  1.2  christos 	tf = t_fopen(NULL);
    225  1.2  christos 	t_fprintf(tf, " # comment\n");
    226  1.2  christos 	t_frewind(tf);
    227  1.1  christos 	ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/);
    228  1.1  christos 	t_fclose(tf);
    229  1.1  christos 	return (ret);
    230  1.3  christos }
    231  1.3  christos 
    232  1.3  christos T_FUNC(line_continuation_within_whitespace, "line continuation within whitespace")
    233  1.3  christos {
    234  1.3  christos 	struct t_file *tf;
    235  1.3  christos 	int ret;
    236  1.3  christos 
    237  1.3  christos 	tf = t_fopen(NULL);
    238  1.3  christos 	t_fprintf(tf, "%s \\\n %s\n", hello_world[0], hello_world[1]);
    239  1.3  christos 	t_frewind(tf);
    240  1.3  christos 	ret = orlv_expect(tf, hello_world, 2 /*lines*/, 0 /*eof*/) &&
    241  1.3  christos 	    orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/);
    242  1.3  christos 	t_fclose(tf);
    243  1.3  christos 	return (ret);
    244  1.1  christos }
    245  1.1  christos 
    246  1.1  christos 
    247  1.1  christos /***************************************************************************
    249  1.1  christos  * Simple words
    250  1.1  christos  */
    251  1.2  christos 
    252  1.1  christos T_FUNC(one_word, "one word")
    253  1.1  christos {
    254  1.2  christos 	struct t_file *tf;
    255  1.2  christos 	int ret;
    256  1.2  christos 
    257  1.2  christos 	tf = t_fopen(NULL);
    258  1.2  christos 	t_fprintf(tf, "hello\n");
    259  1.1  christos 	t_frewind(tf);
    260  1.1  christos 	ret = orlv_expect(tf, hello, 1 /*lines*/, 0 /*eof*/);
    261  1.1  christos 	t_fclose(tf);
    262  1.1  christos 	return (ret);
    263  1.1  christos }
    264  1.2  christos 
    265  1.2  christos T_FUNC(two_words, "two words")
    266  1.2  christos {
    267  1.2  christos 	struct t_file *tf;
    268  1.2  christos 	int ret;
    269  1.2  christos 
    270  1.2  christos 	tf = t_fopen(NULL);
    271  1.2  christos 	t_fprintf(tf, "hello world\n");
    272  1.2  christos 	t_frewind(tf);
    273  1.2  christos 	ret = orlv_expect(tf, hello_world, 1 /*lines*/, 0 /*eof*/);
    274  1.2  christos 	t_fclose(tf);
    275  1.2  christos 	return (ret);
    276  1.2  christos }
    277  1.2  christos 
    278  1.2  christos T_FUNC(many_words, "many words")
    279  1.1  christos {
    280  1.1  christos 	struct t_file *tf;
    281  1.2  christos 	const char **word;
    282  1.2  christos 	int ret;
    283  1.2  christos 
    284  1.2  christos 	tf = t_fopen(NULL);
    285  1.2  christos 	for (word = numbers; *word; ++word)
    286  1.2  christos 		t_fprintf(tf, " %s", *word);
    287  1.2  christos 	t_fprintf(tf, "\n");
    288  1.1  christos 	t_frewind(tf);
    289  1.1  christos 	ret = orlv_expect(tf, numbers, 1 /*lines*/, 0 /*eof*/);
    290  1.1  christos 	t_fclose(tf);
    291  1.1  christos 	return (ret);
    292  1.1  christos }
    293  1.2  christos 
    294  1.1  christos T_FUNC(unterminated_line, "unterminated line")
    295  1.1  christos {
    296  1.2  christos 	struct t_file *tf;
    297  1.2  christos 	int ret;
    298  1.2  christos 
    299  1.2  christos 	tf = t_fopen(NULL);
    300  1.2  christos 	t_fprintf(tf, "hello world");
    301  1.1  christos 	t_frewind(tf);
    302  1.1  christos 	ret = orlv_expect(tf, hello_world, 0 /*lines*/, 1 /*eof*/);
    303  1.1  christos 	t_fclose(tf);
    304  1.1  christos 	return (ret);
    305  1.1  christos }
    306  1.1  christos 
    307  1.1  christos 
    308  1.1  christos /***************************************************************************
    310  1.1  christos  * Boilerplate
    311  1.1  christos  */
    312  1.1  christos 
    313  1.1  christos static int
    314  1.1  christos t_prepare(int argc, char *argv[])
    315  1.3  christos {
    316  1.3  christos 
    317  1.3  christos 	(void)argc;
    318  1.3  christos 	(void)argv;
    319  1.3  christos 
    320  1.3  christos 	T(empty_input);
    321  1.3  christos 	T(empty_line);
    322  1.3  christos 	T(unterminated_empty_line);
    323  1.3  christos 	T(whitespace);
    324  1.3  christos 	T(comment);
    325  1.3  christos 	T(whitespace_before_comment);
    326  1.3  christos 	T(line_continuation_within_whitespace);
    327  1.3  christos 
    328  1.3  christos 	T(one_word);
    329  1.3  christos 	T(two_words);
    330  1.1  christos 	T(many_words);
    331  1.1  christos 	T(unterminated_line);
    332  1.3  christos 
    333  1.3  christos 	return (0);
    334  1.1  christos }
    335  1.3  christos 
    336  1.3  christos int
    337  1.1  christos main(int argc, char *argv[])
    338                {
    339                
    340                	t_main(t_prepare, NULL, argc, argv);
    341                }
    342