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$");
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
51static enum test_methods method = TEST_GETUSERSHELL;
52
53DECLARE_TEST_DATA(usershell)
54DECLARE_TEST_FILE_SNAPSHOT(usershell)
55DECLARE_2PASS_TEST(usershell)
56
57static void clone_usershell(struct usershell *, struct usershell const *);
58static int compare_usershell(struct usershell *, struct usershell *, void *);
59static void free_usershell(struct usershell *);
60
61static void sdump_usershell(struct usershell *, char *, size_t);
62static void dump_usershell(struct usershell *);
63
64IMPLEMENT_TEST_DATA(usershell)
65IMPLEMENT_TEST_FILE_SNAPSHOT(usershell)
66IMPLEMENT_2PASS_TEST(usershell)
67
68static void
69clone_usershell(struct usershell *dest, struct usershell const *src)
70{
71	assert(dest != NULL);
72	assert(src != NULL);
73
74	if (src->path != NULL) {
75		dest->path = strdup(src->path);
76		assert(dest->path != NULL);
77	}
78}
79
80static int
81compare_usershell(struct usershell *us1, struct usershell *us2, void *mdata)
82{
83	int rv;
84
85	assert(us1 != NULL);
86	assert(us2 != NULL);
87
88	dump_usershell(us1);
89	dump_usershell(us2);
90
91	if (us1 == us2)
92		return (0);
93
94	rv = strcmp(us1->path, us2->path);
95	if (rv != 0) {
96		printf("following structures are not equal:\n");
97		dump_usershell(us1);
98		dump_usershell(us2);
99	}
100
101	return (rv);
102}
103
104static void
105free_usershell(struct usershell *us)
106{
107	free(us->path);
108}
109
110static void
111sdump_usershell(struct usershell *us, char *buffer, size_t buflen)
112{
113	snprintf(buffer, buflen, "%s", us->path);
114}
115
116static void
117dump_usershell(struct usershell *us)
118{
119	if (us != NULL) {
120		char buffer[2048];
121		sdump_usershell(us, buffer, sizeof(buffer));
122		printf("%s\n", buffer);
123	} else
124		printf("(null)\n");
125}
126
127static int
128usershell_read_snapshot_func(struct usershell *us, char *line)
129{
130
131	us->path = strdup(line);
132	ATF_REQUIRE(us->path != NULL);
133
134	return (0);
135}
136
137int
138run_tests(const char *snapshot_file, enum test_methods method)
139{
140	struct usershell_test_data td, td_snap;
141	struct usershell ushell;
142	int rv;
143
144	rv = 0;
145
146	TEST_DATA_INIT(usershell, &td, clone_usershell, free_usershell);
147	TEST_DATA_INIT(usershell, &td_snap, clone_usershell, free_usershell);
148
149	setusershell();
150	while ((ushell.path = getusershell()) != NULL) {
151		printf("usershell found:\n");
152		dump_usershell(&ushell);
153		TEST_DATA_APPEND(usershell, &td, &ushell);
154	}
155	endusershell();
156
157	if (snapshot_file != NULL) {
158		if (access(snapshot_file, W_OK | R_OK) != 0) {
159			if (errno == ENOENT)
160				method = TEST_BUILD_SNAPSHOT;
161			else {
162				printf("can't access the snapshot file %s\n",
163				    snapshot_file);
164
165				rv = -1;
166				goto fin;
167			}
168		} else {
169			rv = TEST_SNAPSHOT_FILE_READ(usershell, snapshot_file,
170				&td_snap, usershell_read_snapshot_func);
171			if (rv != 0) {
172				printf("error reading snapshot file\n");
173				goto fin;
174			}
175		}
176	}
177
178	switch (method) {
179	case TEST_GETUSERSHELL:
180		rv = DO_2PASS_TEST(usershell, &td, &td_snap,
181			compare_usershell, NULL);
182		break;
183	case TEST_BUILD_SNAPSHOT:
184		if (snapshot_file != NULL) {
185			rv = TEST_SNAPSHOT_FILE_WRITE(usershell, snapshot_file,
186			    &td, sdump_usershell);
187		}
188		break;
189	default:
190		rv = 0;
191		break;
192	}
193
194fin:
195	TEST_DATA_DESTROY(usershell, &td_snap);
196	TEST_DATA_DESTROY(usershell, &td);
197
198	return (rv);
199}
200
201#define	SNAPSHOT_FILE	"snapshot_usershell"
202
203ATF_TC_WITHOUT_HEAD(getusershell_with_snapshot);
204ATF_TC_BODY(getusershell_with_snapshot, tc)
205{
206
207	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
208}
209
210ATF_TC_WITHOUT_HEAD(getusershell_with_two_pass);
211ATF_TC_BODY(getusershell_with_two_pass, tc)
212{
213
214	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
215	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETUSERSHELL) == 0);
216}
217
218ATF_TP_ADD_TCS(tp)
219{
220
221	ATF_TP_ADD_TC(tp, getusershell_with_snapshot);
222	ATF_TP_ADD_TC(tp, getusershell_with_two_pass);
223
224	return (atf_no_error());
225}
226