backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / virpcitest.c
blob0bd37268ef89a0c66f8c61786e1a5eac01d88dec
1 /*
2 * Copyright (C) 2013, 2014 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
19 #include <config.h>
21 #include "testutils.h"
23 #ifdef __linux__
25 # include <sys/types.h>
26 # include <sys/stat.h>
27 # include <fcntl.h>
28 # include <virpci.h>
30 # define VIR_FROM_THIS VIR_FROM_NONE
32 static int
33 testVirPCIDeviceCheckDriver(virPCIDevicePtr dev, const char *expected)
35 char *path = NULL;
36 char *driver = NULL;
37 int ret = -1;
39 if (virPCIDeviceGetDriverPathAndName(dev, &path, &driver) < 0)
40 goto cleanup;
42 if (STRNEQ_NULLABLE(driver, expected)) {
43 virReportError(VIR_ERR_INTERNAL_ERROR,
44 "PCI device %s driver mismatch: %s, expecting %s",
45 virPCIDeviceGetName(dev), NULLSTR(driver),
46 NULLSTR(expected));
47 goto cleanup;
50 ret = 0;
51 cleanup:
52 VIR_FREE(path);
53 VIR_FREE(driver);
54 return ret;
57 static int
58 testVirPCIDeviceNew(const void *opaque ATTRIBUTE_UNUSED)
60 int ret = -1;
61 virPCIDevicePtr dev;
62 const char *devName;
64 if (!(dev = virPCIDeviceNew(0, 0, 0, 0)))
65 goto cleanup;
67 devName = virPCIDeviceGetName(dev);
68 if (STRNEQ(devName, "0000:00:00.0")) {
69 virReportError(VIR_ERR_INTERNAL_ERROR,
70 "PCI device name mismatch: %s, expecting %s",
71 devName, "0000:00:00.0");
72 goto cleanup;
75 ret = 0;
76 cleanup:
77 virPCIDeviceFree(dev);
78 return ret;
81 # define CHECK_LIST_COUNT(list, cnt) \
82 if ((count = virPCIDeviceListCount(list)) != cnt) { \
83 virReportError(VIR_ERR_INTERNAL_ERROR, \
84 "Unexpected count of items in " #list ": %d, " \
85 "expecting %zu", count, (size_t) cnt); \
86 goto cleanup; \
89 static int
90 testVirPCIDeviceDetach(const void *opaque ATTRIBUTE_UNUSED)
92 int ret = -1;
93 virPCIDevicePtr dev[] = {NULL, NULL, NULL};
94 size_t i, nDev = ARRAY_CARDINALITY(dev);
95 virPCIDeviceListPtr activeDevs = NULL, inactiveDevs = NULL;
96 int count;
98 if (!(activeDevs = virPCIDeviceListNew()) ||
99 !(inactiveDevs = virPCIDeviceListNew()))
100 goto cleanup;
102 CHECK_LIST_COUNT(activeDevs, 0);
103 CHECK_LIST_COUNT(inactiveDevs, 0);
105 for (i = 0; i < nDev; i++) {
106 if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)))
107 goto cleanup;
109 virPCIDeviceSetStubDriver(dev[i], VIR_PCI_STUB_DRIVER_VFIO);
111 if (virPCIDeviceDetach(dev[i], activeDevs, inactiveDevs) < 0)
112 goto cleanup;
114 if (testVirPCIDeviceCheckDriver(dev[i], "vfio-pci") < 0)
115 goto cleanup;
117 CHECK_LIST_COUNT(activeDevs, 0);
118 CHECK_LIST_COUNT(inactiveDevs, i + 1);
121 ret = 0;
122 cleanup:
123 for (i = 0; i < nDev; i++)
124 virPCIDeviceFree(dev[i]);
125 virObjectUnref(activeDevs);
126 virObjectUnref(inactiveDevs);
127 return ret;
130 static int
131 testVirPCIDeviceReset(const void *opaque ATTRIBUTE_UNUSED)
133 int ret = -1;
134 virPCIDevicePtr dev[] = {NULL, NULL, NULL};
135 size_t i, nDev = ARRAY_CARDINALITY(dev);
136 virPCIDeviceListPtr activeDevs = NULL, inactiveDevs = NULL;
137 int count;
139 if (!(activeDevs = virPCIDeviceListNew()) ||
140 !(inactiveDevs = virPCIDeviceListNew()))
141 goto cleanup;
143 CHECK_LIST_COUNT(activeDevs, 0);
144 CHECK_LIST_COUNT(inactiveDevs, 0);
146 for (i = 0; i < nDev; i++) {
147 if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)))
148 goto cleanup;
150 virPCIDeviceSetStubDriver(dev[i], VIR_PCI_STUB_DRIVER_VFIO);
152 if (virPCIDeviceReset(dev[i], activeDevs, inactiveDevs) < 0)
153 goto cleanup;
156 ret = 0;
157 cleanup:
158 for (i = 0; i < nDev; i++)
159 virPCIDeviceFree(dev[i]);
160 virObjectUnref(activeDevs);
161 virObjectUnref(inactiveDevs);
162 return ret;
165 static int
166 testVirPCIDeviceReattach(const void *opaque ATTRIBUTE_UNUSED)
168 int ret = -1;
169 virPCIDevicePtr dev[] = {NULL, NULL, NULL};
170 size_t i, nDev = ARRAY_CARDINALITY(dev);
171 virPCIDeviceListPtr activeDevs = NULL, inactiveDevs = NULL;
172 int count;
174 if (!(activeDevs = virPCIDeviceListNew()) ||
175 !(inactiveDevs = virPCIDeviceListNew()))
176 goto cleanup;
178 for (i = 0; i < nDev; i++) {
179 if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)))
180 goto cleanup;
182 if (virPCIDeviceListAdd(inactiveDevs, dev[i]) < 0) {
183 virPCIDeviceFree(dev[i]);
184 goto cleanup;
187 CHECK_LIST_COUNT(activeDevs, 0);
188 CHECK_LIST_COUNT(inactiveDevs, i + 1);
190 virPCIDeviceSetStubDriver(dev[i], VIR_PCI_STUB_DRIVER_VFIO);
193 CHECK_LIST_COUNT(activeDevs, 0);
194 CHECK_LIST_COUNT(inactiveDevs, nDev);
196 for (i = 0; i < nDev; i++) {
197 if (virPCIDeviceReattach(dev[i], activeDevs, inactiveDevs) < 0)
198 goto cleanup;
200 CHECK_LIST_COUNT(activeDevs, 0);
201 CHECK_LIST_COUNT(inactiveDevs, nDev - i - 1);
204 ret = 0;
205 cleanup:
206 virObjectUnref(activeDevs);
207 virObjectUnref(inactiveDevs);
208 return ret;
211 struct testPCIDevData {
212 unsigned int domain;
213 unsigned int bus;
214 unsigned int slot;
215 unsigned int function;
216 const char *driver;
219 static int
220 testVirPCIDeviceIsAssignable(const void *opaque)
222 const struct testPCIDevData *data = opaque;
223 int ret = -1;
224 virPCIDevicePtr dev;
226 if (!(dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function)))
227 goto cleanup;
229 if (virPCIDeviceIsAssignable(dev, true))
230 ret = 0;
232 virPCIDeviceFree(dev);
233 cleanup:
234 return ret;
237 static int
238 testVirPCIDeviceDetachSingle(const void *opaque)
240 const struct testPCIDevData *data = opaque;
241 int ret = -1;
242 virPCIDevicePtr dev;
244 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
245 if (!dev)
246 goto cleanup;
248 virPCIDeviceSetStubDriver(dev, VIR_PCI_STUB_DRIVER_VFIO);
250 if (virPCIDeviceDetach(dev, NULL, NULL) < 0)
251 goto cleanup;
253 ret = 0;
254 cleanup:
255 virPCIDeviceFree(dev);
256 return ret;
259 static int
260 testVirPCIDeviceReattachSingle(const void *opaque)
262 const struct testPCIDevData *data = opaque;
263 int ret = -1;
264 virPCIDevicePtr dev;
266 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
267 if (!dev)
268 goto cleanup;
270 virPCIDeviceSetUnbindFromStub(dev, true);
271 virPCIDeviceSetRemoveSlot(dev, true);
272 virPCIDeviceSetReprobe(dev, true);
274 if (virPCIDeviceReattach(dev, NULL, NULL) < 0)
275 goto cleanup;
277 ret = 0;
278 cleanup:
279 virPCIDeviceFree(dev);
280 return ret;
283 static int
284 testVirPCIDeviceCheckDriverTest(const void *opaque)
286 const struct testPCIDevData *data = opaque;
287 int ret = -1;
288 virPCIDevicePtr dev;
290 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
291 if (!dev)
292 goto cleanup;
294 if (testVirPCIDeviceCheckDriver(dev, data->driver) < 0)
295 goto cleanup;
297 ret = 0;
298 cleanup:
299 virPCIDeviceFree(dev);
300 return ret;
303 static int
304 testVirPCIDeviceUnbind(const void *opaque)
306 const struct testPCIDevData *data = opaque;
307 int ret = -1;
308 virPCIDevicePtr dev;
310 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
311 if (!dev)
312 goto cleanup;
314 if (virPCIDeviceUnbind(dev) < 0)
315 goto cleanup;
317 ret = 0;
318 cleanup:
319 virPCIDeviceFree(dev);
320 return ret;
323 # define FAKEROOTDIRTEMPLATE abs_builddir "/fakerootdir-XXXXXX"
325 static int
326 mymain(void)
328 int ret = 0;
329 char *fakerootdir;
331 if (VIR_STRDUP_QUIET(fakerootdir, FAKEROOTDIRTEMPLATE) < 0) {
332 VIR_TEST_DEBUG("Out of memory\n");
333 abort();
336 if (!mkdtemp(fakerootdir)) {
337 VIR_TEST_DEBUG("Cannot create fakerootdir");
338 abort();
341 setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir, 1);
343 # define DO_TEST(fnc) \
344 do { \
345 if (virTestRun(#fnc, fnc, NULL) < 0) \
346 ret = -1; \
347 } while (0)
349 # define DO_TEST_PCI(fnc, domain, bus, slot, function) \
350 do { \
351 struct testPCIDevData data = { \
352 domain, bus, slot, function, NULL \
353 }; \
354 char *label = NULL; \
355 if (virAsprintf(&label, "%s(%04x:%02x:%02x.%x)", \
356 #fnc, domain, bus, slot, function) < 0) { \
357 ret = -1; \
358 break; \
360 if (virTestRun(label, fnc, &data) < 0) \
361 ret = -1; \
362 VIR_FREE(label); \
363 } while (0)
365 # define DO_TEST_PCI_DRIVER(domain, bus, slot, function, driver) \
366 do { \
367 struct testPCIDevData data = { \
368 domain, bus, slot, function, driver \
369 }; \
370 char *label = NULL; \
371 if (virAsprintf(&label, "PCI driver %04x:%02x:%02x.%x is %s", \
372 domain, bus, slot, function, \
373 NULLSTR(driver)) < 0) { \
374 ret = -1; \
375 break; \
377 if (virTestRun(label, testVirPCIDeviceCheckDriverTest, \
378 &data) < 0) \
379 ret = -1; \
380 VIR_FREE(label); \
381 } while (0)
383 /* Changes made to individual devices are persistent and the
384 * tests often rely on the state set by previous tests.
387 DO_TEST(testVirPCIDeviceNew);
388 DO_TEST(testVirPCIDeviceDetach);
389 DO_TEST(testVirPCIDeviceReset);
390 DO_TEST(testVirPCIDeviceReattach);
391 DO_TEST_PCI(testVirPCIDeviceIsAssignable, 5, 0x90, 1, 0);
392 DO_TEST_PCI(testVirPCIDeviceIsAssignable, 1, 1, 0, 0);
394 /* Reattach a device already bound to non-stub a driver */
395 DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915");
396 DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 1, 0);
397 DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915");
399 /* Reattach an unbound device */
400 DO_TEST_PCI(testVirPCIDeviceUnbind, 0, 0x0a, 1, 0);
401 DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, NULL);
402 DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 1, 0);
403 DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915");
405 /* Detach an unbound device */
406 DO_TEST_PCI_DRIVER(0, 0x0a, 2, 0, NULL);
407 DO_TEST_PCI(testVirPCIDeviceDetachSingle, 0, 0x0a, 2, 0);
408 DO_TEST_PCI_DRIVER(0, 0x0a, 2, 0, "vfio-pci");
410 /* Reattach an unknown unbound device */
411 DO_TEST_PCI_DRIVER(0, 0x0a, 3, 0, NULL);
412 DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 3, 0);
413 DO_TEST_PCI_DRIVER(0, 0x0a, 3, 0, NULL);
415 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
416 virFileDeleteTree(fakerootdir);
418 VIR_FREE(fakerootdir);
420 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
423 VIR_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virpcimock.so")
424 #else
426 main(void)
428 return EXIT_AM_SKIP;
430 #endif