1315320Sngie/*-
2346920Sngie * Copyright (c) 2017 Enji Cooper <ngie@freebsd.org>
3315320Sngie *
4315320Sngie * Redistribution and use in source and binary forms, with or without
5315320Sngie * modification, are permitted provided that the following conditions
6315320Sngie * are met:
7315320Sngie * 1. Redistributions of source code must retain the above copyright
8315320Sngie *    notice, this list of conditions and the following disclaimer.
9315320Sngie * 2. Redistributions in binary form must reproduce the above copyright
10315320Sngie *    notice, this list of conditions and the following disclaimer in the
11315320Sngie *    documentation and/or other materials provided with the distribution.
12315320Sngie *
13315320Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14315320Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15315320Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16315320Sngie * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17315320Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18315320Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19315320Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20315320Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21315320Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22315320Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23315320Sngie * SUCH DAMAGE.
24315320Sngie */
25315320Sngie
26326782Sasomers/* Tests functions in lib/libcam/camlib.c */
27326782Sasomers
28321117Sngie#include <sys/cdefs.h>
29321117Sngie__FBSDID("$FreeBSD: stable/11/lib/libcam/tests/libcam_test.c 346920 2019-04-29 19:36:46Z ngie $");
30321117Sngie
31315320Sngie#include <errno.h>
32315320Sngie#include <fcntl.h>
33315320Sngie#include <stdio.h>
34315320Sngie#include <camlib.h>
35315320Sngie
36315320Sngie#include <atf-c.h>
37315320Sngie
38315320Sngiestatic const char *
39315320Sngieget_cam_test_device(const atf_tc_t *tc)
40315320Sngie{
41315320Sngie	const char *cam_test_device;
42315320Sngie
43315320Sngie	cam_test_device = atf_tc_get_config_var(tc, "cam_test_device");
44315320Sngie
45315320Sngie	return (cam_test_device);
46315320Sngie}
47315320Sngie
48315320Sngiestatic void
49315320Sngiecam_clear_error(void)
50315320Sngie{
51315320Sngie
52315320Sngie	strcpy(cam_errbuf, "");
53315320Sngie}
54315320Sngie
55315320Sngiestatic bool
56315320Sngiecam_has_error(void)
57315320Sngie{
58315320Sngie
59315320Sngie	return (strlen(cam_errbuf) != 0);
60315320Sngie}
61315320Sngie
62321123SngieATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_NULL_path);
63321123SngieATF_TC_BODY(cam_get_device_negative_test_NULL_path, tc)
64321123Sngie{
65321123Sngie	char parsed_dev_name[DEV_IDLEN + 1];
66321123Sngie	int parsed_unit;
67321123Sngie
68321123Sngie	ATF_REQUIRE_MSG(cam_get_device(NULL, parsed_dev_name,
69321123Sngie	    nitems(parsed_dev_name), &parsed_unit) == -1,
70321123Sngie	    "cam_get_device succeeded unexpectedly");
71321123Sngie}
72321123Sngie
73321123SngieATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_bad_path);
74321123SngieATF_TC_BODY(cam_get_device_negative_test_bad_path, tc)
75321123Sngie{
76321123Sngie	char parsed_dev_name[DEV_IDLEN + 1];
77321123Sngie	int parsed_unit;
78321123Sngie
79321123Sngie	ATF_REQUIRE_MSG(cam_get_device("1ada", parsed_dev_name,
80321123Sngie	    nitems(parsed_dev_name), &parsed_unit) == -1,
81321123Sngie	    "cam_get_device succeeded unexpectedly");
82321123Sngie}
83321123Sngie
84321123SngieATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_nul_path);
85321123SngieATF_TC_BODY(cam_get_device_negative_test_nul_path, tc)
86321123Sngie{
87321123Sngie	char parsed_dev_name[DEV_IDLEN + 1];
88321123Sngie	int parsed_unit;
89321123Sngie
90321123Sngie	ATF_REQUIRE_MSG(cam_get_device("", parsed_dev_name,
91321123Sngie	    nitems(parsed_dev_name), &parsed_unit) == -1,
92321123Sngie	    "cam_get_device succeeded unexpectedly");
93321123Sngie}
94321123Sngie
95321123SngieATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_root);
96321123SngieATF_TC_BODY(cam_get_device_negative_test_root, tc)
97321123Sngie{
98321123Sngie	char parsed_dev_name[DEV_IDLEN + 1];
99321123Sngie	int parsed_unit;
100321123Sngie
101321123Sngie	ATF_REQUIRE_MSG(cam_get_device("/", parsed_dev_name,
102321123Sngie	    nitems(parsed_dev_name), &parsed_unit) == -1,
103321123Sngie	    "cam_get_device succeeded unexpectedly");
104321123Sngie}
105321123Sngie
106321123SngieATF_TC_WITHOUT_HEAD(cam_get_device_positive_test);
107321123SngieATF_TC_BODY(cam_get_device_positive_test, tc)
108321123Sngie{
109321123Sngie	char expected_dev_name[] = "foo";
110321123Sngie	char parsed_dev_name[DEV_IDLEN + 1];
111321123Sngie	int expected_unit, parsed_unit;
112321123Sngie
113321123Sngie	expected_unit = 1;
114321123Sngie
115321123Sngie	ATF_REQUIRE_MSG(cam_get_device("/dev/foo1", parsed_dev_name,
116321123Sngie	    nitems(parsed_dev_name), &parsed_unit) == 0,
117321123Sngie	    "cam_get_device failed");
118321123Sngie	ATF_REQUIRE_STREQ(parsed_dev_name, expected_dev_name);
119321123Sngie	ATF_REQUIRE(parsed_unit == expected_unit);
120321123Sngie
121321123Sngie	strcpy(parsed_dev_name, "");
122321123Sngie	parsed_unit = -1;
123321123Sngie
124321123Sngie	ATF_REQUIRE_MSG(cam_get_device("foo1", parsed_dev_name,
125321123Sngie	    nitems(parsed_dev_name), &parsed_unit) == 0,
126321123Sngie	    "cam_get_device failed");
127321123Sngie	ATF_REQUIRE_STREQ(parsed_dev_name, expected_dev_name);
128321123Sngie	ATF_REQUIRE(parsed_unit == expected_unit);
129321123Sngie}
130321123Sngie
131326827Sasomers/*
132326827Sasomers * sa(4) uniquely creates nsa and esa device nodes for non-rewind operations
133326827Sasomers * and eject-on-close operations.  cam_get_device must special case these nodes
134326827Sasomers * to always return the base device.
135326827Sasomers */
136326827SasomersATF_TC_WITHOUT_HEAD(cam_get_device_sa_test);
137326827SasomersATF_TC_BODY(cam_get_device_sa_test, tc)
138326827Sasomers{
139326827Sasomers	char parsed_dev_name[DEV_IDLEN + 1];
140326827Sasomers	int parsed_unit;
141326827Sasomers
142326827Sasomers	ATF_REQUIRE_MSG(cam_get_device("nsa99", parsed_dev_name,
143326827Sasomers	    nitems(parsed_dev_name), &parsed_unit) == 0,
144326827Sasomers	    "cam_get_device failed");
145326827Sasomers	ATF_REQUIRE_STREQ(parsed_dev_name, "sa");
146326827Sasomers	ATF_REQUIRE(parsed_unit == 99);
147326827Sasomers
148326827Sasomers	strcpy(parsed_dev_name, "");
149326827Sasomers	parsed_unit = -1;
150326827Sasomers
151326827Sasomers	ATF_REQUIRE_MSG(cam_get_device("esa99", parsed_dev_name,
152326827Sasomers	    nitems(parsed_dev_name), &parsed_unit) == 0,
153326827Sasomers	    "cam_get_device failed");
154326827Sasomers	ATF_REQUIRE_STREQ(parsed_dev_name, "sa");
155326827Sasomers	ATF_REQUIRE(parsed_unit == 99);
156326827Sasomers}
157326827Sasomers
158315320SngieATF_TC(cam_open_device_negative_test_O_RDONLY);
159315320SngieATF_TC_HEAD(cam_open_device_negative_test_O_RDONLY, tc)
160315320Sngie{
161315320Sngie
162315320Sngie	atf_tc_set_md_var(tc, "descr",
163315320Sngie	    "test that cam_open_device(`cam_device`, O_RDONLY) fails to open "
164315320Sngie	    "the underlying pass(4) device (bug 217649)");
165315320Sngie	atf_tc_set_md_var(tc, "require.config", "cam_test_device");
166315320Sngie	atf_tc_set_md_var(tc, "require.user", "root");
167315320Sngie}
168315320Sngie
169315320SngieATF_TC_BODY(cam_open_device_negative_test_O_RDONLY, tc)
170315320Sngie{
171315320Sngie	const char *cam_test_device;
172315320Sngie
173315320Sngie	cam_test_device = get_cam_test_device(tc);
174315320Sngie
175315320Sngie	cam_clear_error();
176315320Sngie	ATF_CHECK(cam_open_device(cam_test_device, O_RDONLY) == NULL);
177315320Sngie	ATF_REQUIRE(cam_has_error());
178315320Sngie}
179315320Sngie
180315320SngieATF_TC(cam_open_device_negative_test_nonexistent);
181315320SngieATF_TC_HEAD(cam_open_device_negative_test_nonexistent, tc)
182315320Sngie{
183315320Sngie
184315320Sngie	atf_tc_set_md_var(tc, "require.user", "root");
185315320Sngie}
186315320Sngie
187315320SngieATF_TC_BODY(cam_open_device_negative_test_nonexistent, tc)
188315320Sngie{
189315320Sngie
190315320Sngie	cam_clear_error();
191315320Sngie	ATF_REQUIRE(cam_open_device("/nonexistent", O_RDWR) == NULL);
192315320Sngie	ATF_REQUIRE(cam_has_error());
193315320Sngie}
194315320Sngie
195315320SngieATF_TC(cam_open_device_negative_test_unprivileged);
196315320SngieATF_TC_HEAD(cam_open_device_negative_test_unprivileged, tc)
197315320Sngie{
198315320Sngie
199315320Sngie	atf_tc_set_md_var(tc, "require.config", "cam_test_device");
200315320Sngie	atf_tc_set_md_var(tc, "require.user", "unprivileged");
201315320Sngie}
202315320Sngie
203315320SngieATF_TC_BODY(cam_open_device_negative_test_unprivileged, tc)
204315320Sngie{
205315320Sngie	const char *cam_test_device;
206315320Sngie
207315320Sngie	cam_test_device = get_cam_test_device(tc);
208315320Sngie
209315320Sngie	cam_clear_error();
210315320Sngie	ATF_CHECK(cam_open_device(cam_test_device, O_RDONLY) == NULL);
211315320Sngie	ATF_REQUIRE(cam_has_error());
212315320Sngie
213315320Sngie	cam_clear_error();
214315320Sngie	ATF_CHECK(cam_open_device(cam_test_device, O_RDWR) == NULL);
215315320Sngie	ATF_REQUIRE(cam_has_error());
216315320Sngie}
217315320Sngie
218315320SngieATF_TC(cam_open_device_positive_test);
219315320SngieATF_TC_HEAD(cam_open_device_positive_test, tc)
220315320Sngie{
221315320Sngie
222315320Sngie	atf_tc_set_md_var(tc, "require.config", "cam_test_device");
223315320Sngie	atf_tc_set_md_var(tc, "require.user", "root");
224315320Sngie}
225315320Sngie
226315320SngieATF_TC_BODY(cam_open_device_positive_test, tc)
227315320Sngie{
228315320Sngie	struct cam_device *cam_dev;
229315320Sngie	const char *cam_test_device;
230315320Sngie
231315320Sngie	cam_test_device = get_cam_test_device(tc);
232315320Sngie
233315320Sngie	cam_clear_error();
234315320Sngie	cam_dev = cam_open_device(cam_test_device, O_RDWR);
235315320Sngie	ATF_CHECK_MSG(cam_dev != NULL, "cam_open_device failed: %s",
236315320Sngie	    cam_errbuf);
237315320Sngie	ATF_REQUIRE(!cam_has_error());
238315320Sngie	cam_close_device(cam_dev);
239315320Sngie}
240315320Sngie
241315320SngieATF_TC(cam_close_device_negative_test_NULL);
242315320SngieATF_TC_HEAD(cam_close_device_negative_test_NULL, tc)
243315320Sngie{
244315320Sngie
245315320Sngie	atf_tc_set_md_var(tc, "descr",
246315320Sngie	    "test that cam_close_device(NULL) succeeds without error");
247315320Sngie	atf_tc_set_md_var(tc, "require.user", "root");
248315320Sngie}
249315320Sngie
250315320SngieATF_TC_BODY(cam_close_device_negative_test_NULL, tc)
251315320Sngie{
252315320Sngie
253315320Sngie	cam_clear_error();
254315320Sngie	cam_close_device(NULL);
255315320Sngie	ATF_REQUIRE(!cam_has_error());
256315320Sngie}
257315320Sngie
258315320SngieATF_TC(cam_getccb_positive_test);
259315320SngieATF_TC_HEAD(cam_getccb_positive_test, tc)
260315320Sngie{
261315320Sngie
262315320Sngie	atf_tc_set_md_var(tc, "require.config", "cam_test_device");
263315320Sngie	atf_tc_set_md_var(tc, "require.user", "root");
264315320Sngie}
265315320Sngie
266315320SngieATF_TC_BODY(cam_getccb_positive_test, tc)
267315320Sngie{
268315320Sngie	union ccb *cam_ccb;
269315320Sngie	struct cam_device *cam_dev;
270315320Sngie	const char *cam_test_device;
271315320Sngie
272315320Sngie	cam_test_device = get_cam_test_device(tc);
273315320Sngie
274315320Sngie	cam_clear_error();
275315320Sngie	cam_dev = cam_open_device(cam_test_device, O_RDWR);
276315320Sngie	ATF_CHECK_MSG(cam_dev != NULL, "cam_open_device failed: %s",
277315320Sngie	    cam_errbuf);
278315320Sngie	ATF_REQUIRE(!cam_has_error());
279315320Sngie	cam_ccb = cam_getccb(cam_dev);
280315320Sngie	ATF_CHECK_MSG(cam_ccb != NULL, "get_camccb failed: %s", cam_errbuf);
281315320Sngie	ATF_REQUIRE(!cam_has_error());
282315320Sngie	cam_freeccb(cam_ccb);
283315320Sngie	cam_close_device(cam_dev);
284315320Sngie}
285315320Sngie
286315320SngieATF_TC(cam_freeccb_negative_test_NULL);
287315320SngieATF_TC_HEAD(cam_freeccb_negative_test_NULL, tc)
288315320Sngie{
289315320Sngie
290315320Sngie	atf_tc_set_md_var(tc, "descr",
291315320Sngie	    "test that cam_freeccb(NULL) succeeds without error");
292315320Sngie	atf_tc_set_md_var(tc, "require.user", "root");
293315320Sngie}
294315320Sngie
295315320SngieATF_TC_BODY(cam_freeccb_negative_test_NULL, tc)
296315320Sngie{
297315320Sngie
298315320Sngie	cam_clear_error();
299315320Sngie	cam_freeccb(NULL);
300315320Sngie	ATF_REQUIRE(!cam_has_error());
301315320Sngie}
302315320Sngie
303315320SngieATF_TP_ADD_TCS(tp)
304315320Sngie{
305315320Sngie
306321123Sngie	ATF_TP_ADD_TC(tp, cam_get_device_negative_test_NULL_path);
307321123Sngie	ATF_TP_ADD_TC(tp, cam_get_device_negative_test_bad_path);
308321123Sngie	ATF_TP_ADD_TC(tp, cam_get_device_negative_test_nul_path);
309321123Sngie	ATF_TP_ADD_TC(tp, cam_get_device_negative_test_root);
310321123Sngie	ATF_TP_ADD_TC(tp, cam_get_device_positive_test);
311326827Sasomers	ATF_TP_ADD_TC(tp, cam_get_device_sa_test);
312315320Sngie	ATF_TP_ADD_TC(tp, cam_open_device_negative_test_O_RDONLY);
313315320Sngie	ATF_TP_ADD_TC(tp, cam_open_device_negative_test_nonexistent);
314315320Sngie	ATF_TP_ADD_TC(tp, cam_open_device_negative_test_unprivileged);
315315320Sngie	ATF_TP_ADD_TC(tp, cam_open_device_positive_test);
316315320Sngie	ATF_TP_ADD_TC(tp, cam_close_device_negative_test_NULL);
317315320Sngie	ATF_TP_ADD_TC(tp, cam_getccb_positive_test);
318315320Sngie	ATF_TP_ADD_TC(tp, cam_freeccb_negative_test_NULL);
319315320Sngie
320315320Sngie	return (atf_no_error());
321315320Sngie}
322