xref: /freebsd/lib/libcam/tests/libcam_test.c (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
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$");
30 
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <camlib.h>
35 
36 #include <atf-c.h>
37 
38 static const char *
39 get_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 
48 static void
49 cam_clear_error(void)
50 {
51 
52 	strcpy(cam_errbuf, "");
53 }
54 
55 static bool
56 cam_has_error(void)
57 {
58 
59 	return (strlen(cam_errbuf) != 0);
60 }
61 
62 ATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_NULL_path);
63 ATF_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 
73 ATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_bad_path);
74 ATF_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 
84 ATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_nul_path);
85 ATF_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 
95 ATF_TC_WITHOUT_HEAD(cam_get_device_negative_test_root);
96 ATF_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 
106 ATF_TC_WITHOUT_HEAD(cam_get_device_positive_test);
107 ATF_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  */
136 ATF_TC_WITHOUT_HEAD(cam_get_device_sa_test);
137 ATF_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 
158 ATF_TC(cam_open_device_negative_test_O_RDONLY);
159 ATF_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 
169 ATF_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 
180 ATF_TC(cam_open_device_negative_test_nonexistent);
181 ATF_TC_HEAD(cam_open_device_negative_test_nonexistent, tc)
182 {
183 
184 	atf_tc_set_md_var(tc, "require.user", "root");
185 }
186 
187 ATF_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 
195 ATF_TC(cam_open_device_negative_test_unprivileged);
196 ATF_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 
203 ATF_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 
218 ATF_TC(cam_open_device_positive_test);
219 ATF_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 
226 ATF_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 
241 ATF_TC(cam_close_device_negative_test_NULL);
242 ATF_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 
250 ATF_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 
258 ATF_TC(cam_getccb_positive_test);
259 ATF_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 
266 ATF_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 
286 ATF_TC(cam_freeccb_negative_test_NULL);
287 ATF_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 
295 ATF_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 
303 ATF_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