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