1/*-
2 * Copyright (c) 2017 Enji Cooper <ngie@freebsd.org>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26/* Tests functions in lib/libcam/camlib.c */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: stable/11/lib/libcam/tests/libcam_test.c 346920 2019-04-29 19:36:46Z ngie $");
30
31#include <errno.h>
32#include <fcntl.h>
33#include <stdio.h>
34#include <camlib.h>
35
36#include <atf-c.h>
37
38static const char *
39get_cam_test_device(const atf_tc_t *tc)
40{
41	const char *cam_test_device;
42
43	cam_test_device = atf_tc_get_config_var(tc, "cam_test_device");
44
45	return (cam_test_device);
46}
47
48static void
49cam_clear_error(void)
50{
51
52	strcpy(cam_errbuf, "");
53}
54
55static bool
56cam_has_error(void)
57{
58
59	return (strlen(cam_errbuf) != 0);
60}
61
62ATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_NULL_path);
63ATF_TC_BODY(cam_get_device_negative_test_NULL_path, tc)
64{
65	char parsed_dev_name[DEV_IDLEN + 1];
66	int parsed_unit;
67
68	ATF_REQUIRE_MSG(cam_get_device(NULL, parsed_dev_name,
69	    nitems(parsed_dev_name), &parsed_unit) == -1,
70	    "cam_get_device succeeded unexpectedly");
71}
72
73ATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_bad_path);
74ATF_TC_BODY(cam_get_device_negative_test_bad_path, tc)
75{
76	char parsed_dev_name[DEV_IDLEN + 1];
77	int parsed_unit;
78
79	ATF_REQUIRE_MSG(cam_get_device("1ada", parsed_dev_name,
80	    nitems(parsed_dev_name), &parsed_unit) == -1,
81	    "cam_get_device succeeded unexpectedly");
82}
83
84ATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_nul_path);
85ATF_TC_BODY(cam_get_device_negative_test_nul_path, tc)
86{
87	char parsed_dev_name[DEV_IDLEN + 1];
88	int parsed_unit;
89
90	ATF_REQUIRE_MSG(cam_get_device("", parsed_dev_name,
91	    nitems(parsed_dev_name), &parsed_unit) == -1,
92	    "cam_get_device succeeded unexpectedly");
93}
94
95ATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_root);
96ATF_TC_BODY(cam_get_device_negative_test_root, tc)
97{
98	char parsed_dev_name[DEV_IDLEN + 1];
99	int parsed_unit;
100
101	ATF_REQUIRE_MSG(cam_get_device("/", parsed_dev_name,
102	    nitems(parsed_dev_name), &parsed_unit) == -1,
103	    "cam_get_device succeeded unexpectedly");
104}
105
106ATF_TC_WITHOUT_HEAD(cam_get_device_positive_test);
107ATF_TC_BODY(cam_get_device_positive_test, tc)
108{
109	char expected_dev_name[] = "foo";
110	char parsed_dev_name[DEV_IDLEN + 1];
111	int expected_unit, parsed_unit;
112
113	expected_unit = 1;
114
115	ATF_REQUIRE_MSG(cam_get_device("/dev/foo1", parsed_dev_name,
116	    nitems(parsed_dev_name), &parsed_unit) == 0,
117	    "cam_get_device failed");
118	ATF_REQUIRE_STREQ(parsed_dev_name, expected_dev_name);
119	ATF_REQUIRE(parsed_unit == expected_unit);
120
121	strcpy(parsed_dev_name, "");
122	parsed_unit = -1;
123
124	ATF_REQUIRE_MSG(cam_get_device("foo1", parsed_dev_name,
125	    nitems(parsed_dev_name), &parsed_unit) == 0,
126	    "cam_get_device failed");
127	ATF_REQUIRE_STREQ(parsed_dev_name, expected_dev_name);
128	ATF_REQUIRE(parsed_unit == expected_unit);
129}
130
131/*
132 * sa(4) uniquely creates nsa and esa device nodes for non-rewind operations
133 * and eject-on-close operations.  cam_get_device must special case these nodes
134 * to always return the base device.
135 */
136ATF_TC_WITHOUT_HEAD(cam_get_device_sa_test);
137ATF_TC_BODY(cam_get_device_sa_test, tc)
138{
139	char parsed_dev_name[DEV_IDLEN + 1];
140	int parsed_unit;
141
142	ATF_REQUIRE_MSG(cam_get_device("nsa99", parsed_dev_name,
143	    nitems(parsed_dev_name), &parsed_unit) == 0,
144	    "cam_get_device failed");
145	ATF_REQUIRE_STREQ(parsed_dev_name, "sa");
146	ATF_REQUIRE(parsed_unit == 99);
147
148	strcpy(parsed_dev_name, "");
149	parsed_unit = -1;
150
151	ATF_REQUIRE_MSG(cam_get_device("esa99", parsed_dev_name,
152	    nitems(parsed_dev_name), &parsed_unit) == 0,
153	    "cam_get_device failed");
154	ATF_REQUIRE_STREQ(parsed_dev_name, "sa");
155	ATF_REQUIRE(parsed_unit == 99);
156}
157
158ATF_TC(cam_open_device_negative_test_O_RDONLY);
159ATF_TC_HEAD(cam_open_device_negative_test_O_RDONLY, tc)
160{
161
162	atf_tc_set_md_var(tc, "descr",
163	    "test that cam_open_device(`cam_device`, O_RDONLY) fails to open "
164	    "the underlying pass(4) device (bug 217649)");
165	atf_tc_set_md_var(tc, "require.config", "cam_test_device");
166	atf_tc_set_md_var(tc, "require.user", "root");
167}
168
169ATF_TC_BODY(cam_open_device_negative_test_O_RDONLY, tc)
170{
171	const char *cam_test_device;
172
173	cam_test_device = get_cam_test_device(tc);
174
175	cam_clear_error();
176	ATF_CHECK(cam_open_device(cam_test_device, O_RDONLY) == NULL);
177	ATF_REQUIRE(cam_has_error());
178}
179
180ATF_TC(cam_open_device_negative_test_nonexistent);
181ATF_TC_HEAD(cam_open_device_negative_test_nonexistent, tc)
182{
183
184	atf_tc_set_md_var(tc, "require.user", "root");
185}
186
187ATF_TC_BODY(cam_open_device_negative_test_nonexistent, tc)
188{
189
190	cam_clear_error();
191	ATF_REQUIRE(cam_open_device("/nonexistent", O_RDWR) == NULL);
192	ATF_REQUIRE(cam_has_error());
193}
194
195ATF_TC(cam_open_device_negative_test_unprivileged);
196ATF_TC_HEAD(cam_open_device_negative_test_unprivileged, tc)
197{
198
199	atf_tc_set_md_var(tc, "require.config", "cam_test_device");
200	atf_tc_set_md_var(tc, "require.user", "unprivileged");
201}
202
203ATF_TC_BODY(cam_open_device_negative_test_unprivileged, tc)
204{
205	const char *cam_test_device;
206
207	cam_test_device = get_cam_test_device(tc);
208
209	cam_clear_error();
210	ATF_CHECK(cam_open_device(cam_test_device, O_RDONLY) == NULL);
211	ATF_REQUIRE(cam_has_error());
212
213	cam_clear_error();
214	ATF_CHECK(cam_open_device(cam_test_device, O_RDWR) == NULL);
215	ATF_REQUIRE(cam_has_error());
216}
217
218ATF_TC(cam_open_device_positive_test);
219ATF_TC_HEAD(cam_open_device_positive_test, tc)
220{
221
222	atf_tc_set_md_var(tc, "require.config", "cam_test_device");
223	atf_tc_set_md_var(tc, "require.user", "root");
224}
225
226ATF_TC_BODY(cam_open_device_positive_test, tc)
227{
228	struct cam_device *cam_dev;
229	const char *cam_test_device;
230
231	cam_test_device = get_cam_test_device(tc);
232
233	cam_clear_error();
234	cam_dev = cam_open_device(cam_test_device, O_RDWR);
235	ATF_CHECK_MSG(cam_dev != NULL, "cam_open_device failed: %s",
236	    cam_errbuf);
237	ATF_REQUIRE(!cam_has_error());
238	cam_close_device(cam_dev);
239}
240
241ATF_TC(cam_close_device_negative_test_NULL);
242ATF_TC_HEAD(cam_close_device_negative_test_NULL, tc)
243{
244
245	atf_tc_set_md_var(tc, "descr",
246	    "test that cam_close_device(NULL) succeeds without error");
247	atf_tc_set_md_var(tc, "require.user", "root");
248}
249
250ATF_TC_BODY(cam_close_device_negative_test_NULL, tc)
251{
252
253	cam_clear_error();
254	cam_close_device(NULL);
255	ATF_REQUIRE(!cam_has_error());
256}
257
258ATF_TC(cam_getccb_positive_test);
259ATF_TC_HEAD(cam_getccb_positive_test, tc)
260{
261
262	atf_tc_set_md_var(tc, "require.config", "cam_test_device");
263	atf_tc_set_md_var(tc, "require.user", "root");
264}
265
266ATF_TC_BODY(cam_getccb_positive_test, tc)
267{
268	union ccb *cam_ccb;
269	struct cam_device *cam_dev;
270	const char *cam_test_device;
271
272	cam_test_device = get_cam_test_device(tc);
273
274	cam_clear_error();
275	cam_dev = cam_open_device(cam_test_device, O_RDWR);
276	ATF_CHECK_MSG(cam_dev != NULL, "cam_open_device failed: %s",
277	    cam_errbuf);
278	ATF_REQUIRE(!cam_has_error());
279	cam_ccb = cam_getccb(cam_dev);
280	ATF_CHECK_MSG(cam_ccb != NULL, "get_camccb failed: %s", cam_errbuf);
281	ATF_REQUIRE(!cam_has_error());
282	cam_freeccb(cam_ccb);
283	cam_close_device(cam_dev);
284}
285
286ATF_TC(cam_freeccb_negative_test_NULL);
287ATF_TC_HEAD(cam_freeccb_negative_test_NULL, tc)
288{
289
290	atf_tc_set_md_var(tc, "descr",
291	    "test that cam_freeccb(NULL) succeeds without error");
292	atf_tc_set_md_var(tc, "require.user", "root");
293}
294
295ATF_TC_BODY(cam_freeccb_negative_test_NULL, tc)
296{
297
298	cam_clear_error();
299	cam_freeccb(NULL);
300	ATF_REQUIRE(!cam_has_error());
301}
302
303ATF_TP_ADD_TCS(tp)
304{
305
306	ATF_TP_ADD_TC(tp, cam_get_device_negative_test_NULL_path);
307	ATF_TP_ADD_TC(tp, cam_get_device_negative_test_bad_path);
308	ATF_TP_ADD_TC(tp, cam_get_device_negative_test_nul_path);
309	ATF_TP_ADD_TC(tp, cam_get_device_negative_test_root);
310	ATF_TP_ADD_TC(tp, cam_get_device_positive_test);
311	ATF_TP_ADD_TC(tp, cam_get_device_sa_test);
312	ATF_TP_ADD_TC(tp, cam_open_device_negative_test_O_RDONLY);
313	ATF_TP_ADD_TC(tp, cam_open_device_negative_test_nonexistent);
314	ATF_TP_ADD_TC(tp, cam_open_device_negative_test_unprivileged);
315	ATF_TP_ADD_TC(tp, cam_open_device_positive_test);
316	ATF_TP_ADD_TC(tp, cam_close_device_negative_test_NULL);
317	ATF_TP_ADD_TC(tp, cam_getccb_positive_test);
318	ATF_TP_ADD_TC(tp, cam_freeccb_negative_test_NULL);
319
320	return (atf_no_error());
321}
322