1/*-
2 * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
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 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: stable/11/lib/libc/tests/nss/getusershell_test.c 319299 2017-05-31 08:32:05Z ngie $");
30
31#include <assert.h>
32#include <errno.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37
38#include <atf-c.h>
39
40#include "testutil.h"
41
42enum test_methods {
43	TEST_GETUSERSHELL,
44	TEST_BUILD_SNAPSHOT
45};
46
47struct usershell {
48	char *path;
49};
50
51DECLARE_TEST_DATA(usershell)
52DECLARE_TEST_FILE_SNAPSHOT(usershell)
53DECLARE_2PASS_TEST(usershell)
54
55static void clone_usershell(struct usershell *, struct usershell const *);
56static int compare_usershell(struct usershell *, struct usershell *, void *);
57static void free_usershell(struct usershell *);
58
59static void sdump_usershell(struct usershell *, char *, size_t);
60static void dump_usershell(struct usershell *);
61
62IMPLEMENT_TEST_DATA(usershell)
63IMPLEMENT_TEST_FILE_SNAPSHOT(usershell)
64IMPLEMENT_2PASS_TEST(usershell)
65
66static void
67clone_usershell(struct usershell *dest, struct usershell const *src)
68{
69	assert(dest != NULL);
70	assert(src != NULL);
71
72	if (src->path != NULL) {
73		dest->path = strdup(src->path);
74		assert(dest->path != NULL);
75	}
76}
77
78static int
79compare_usershell(struct usershell *us1, struct usershell *us2,
80    void *mdata __unused)
81{
82	int rv;
83
84	assert(us1 != NULL);
85	assert(us2 != NULL);
86
87	dump_usershell(us1);
88	dump_usershell(us2);
89
90	if (us1 == us2)
91		return (0);
92
93	rv = strcmp(us1->path, us2->path);
94	if (rv != 0) {
95		printf("following structures are not equal:\n");
96		dump_usershell(us1);
97		dump_usershell(us2);
98	}
99
100	return (rv);
101}
102
103static void
104free_usershell(struct usershell *us)
105{
106	free(us->path);
107}
108
109static void
110sdump_usershell(struct usershell *us, char *buffer, size_t buflen)
111{
112	snprintf(buffer, buflen, "%s", us->path);
113}
114
115static void
116dump_usershell(struct usershell *us)
117{
118	if (us != NULL) {
119		char buffer[2048];
120		sdump_usershell(us, buffer, sizeof(buffer));
121		printf("%s\n", buffer);
122	} else
123		printf("(null)\n");
124}
125
126static int
127usershell_read_snapshot_func(struct usershell *us, char *line)
128{
129
130	us->path = strdup(line);
131	ATF_REQUIRE(us->path != NULL);
132
133	return (0);
134}
135
136static int
137run_tests(const char *snapshot_file, enum test_methods method)
138{
139	struct usershell_test_data td, td_snap;
140	struct usershell ushell;
141	int rv;
142
143	rv = 0;
144
145	TEST_DATA_INIT(usershell, &td, clone_usershell, free_usershell);
146	TEST_DATA_INIT(usershell, &td_snap, clone_usershell, free_usershell);
147
148	setusershell();
149	while ((ushell.path = getusershell()) != NULL) {
150		printf("usershell found:\n");
151		dump_usershell(&ushell);
152		TEST_DATA_APPEND(usershell, &td, &ushell);
153	}
154	endusershell();
155
156	if (snapshot_file != NULL) {
157		if (access(snapshot_file, W_OK | R_OK) != 0) {
158			if (errno == ENOENT)
159				method = TEST_BUILD_SNAPSHOT;
160			else {
161				printf("can't access the snapshot file %s\n",
162				    snapshot_file);
163
164				rv = -1;
165				goto fin;
166			}
167		} else {
168			rv = TEST_SNAPSHOT_FILE_READ(usershell, snapshot_file,
169				&td_snap, usershell_read_snapshot_func);
170			if (rv != 0) {
171				printf("error reading snapshot file\n");
172				goto fin;
173			}
174		}
175	}
176
177	switch (method) {
178	case TEST_GETUSERSHELL:
179		rv = DO_2PASS_TEST(usershell, &td, &td_snap,
180			compare_usershell, NULL);
181		break;
182	case TEST_BUILD_SNAPSHOT:
183		if (snapshot_file != NULL) {
184			rv = TEST_SNAPSHOT_FILE_WRITE(usershell, snapshot_file,
185			    &td, sdump_usershell);
186		}
187		break;
188	default:
189		rv = 0;
190		break;
191	}
192
193fin:
194	TEST_DATA_DESTROY(usershell, &td_snap);
195	TEST_DATA_DESTROY(usershell, &td);
196
197	return (rv);
198}
199
200#define	SNAPSHOT_FILE	"snapshot_usershell"
201
202ATF_TC_WITHOUT_HEAD(getusershell_with_snapshot);
203ATF_TC_BODY(getusershell_with_snapshot, tc)
204{
205
206	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
207}
208
209ATF_TC_WITHOUT_HEAD(getusershell_with_two_pass);
210ATF_TC_BODY(getusershell_with_two_pass, tc)
211{
212
213	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
214	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETUSERSHELL) == 0);
215}
216
217ATF_TP_ADD_TCS(tp)
218{
219
220	ATF_TP_ADD_TC(tp, getusershell_with_snapshot);
221	ATF_TP_ADD_TC(tp, getusershell_with_two_pass);
222
223	return (atf_no_error());
224}
225