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/>.
18 * Author: Michal Privoznik <mprivozn@redhat.com>
23 #include "testutils.h"
29 # include <sys/types.h>
30 # include <sys/stat.h>
34 # define VIR_FROM_THIS VIR_FROM_NONE
37 testVirPCIDeviceCheckDriver(virPCIDevicePtr dev, const char *expected)
43 if (virPCIDeviceGetDriverPathAndName(dev, &path, &driver) < 0)
46 if (STRNEQ_NULLABLE(driver, expected)) {
47 virReportError(VIR_ERR_INTERNAL_ERROR,
48 "PCI device %s driver mismatch: %s, expecting %s",
49 virPCIDeviceGetName(dev), NULLSTR(driver),
62 testVirPCIDeviceNew(const void *opaque ATTRIBUTE_UNUSED)
68 if (!(dev = virPCIDeviceNew(0, 0, 0, 0)))
71 devName = virPCIDeviceGetName(dev);
72 if (STRNEQ(devName, "0000:00:00.0")) {
73 virReportError(VIR_ERR_INTERNAL_ERROR,
74 "PCI device name mismatch: %s, expecting %s",
75 devName, "0000:00:00.0");
81 virPCIDeviceFree(dev);
85 # define CHECK_LIST_COUNT(list, cnt) \
86 if ((count = virPCIDeviceListCount(list)) != cnt) { \
87 virReportError(VIR_ERR_INTERNAL_ERROR, \
88 "Unexpected count of items in " #list ": %d, " \
89 "expecting %zu", count, (size_t) cnt); \
94 testVirPCIDeviceDetach(const void *oaque ATTRIBUTE_UNUSED)
97 virPCIDevicePtr dev[] = {NULL, NULL, NULL};
98 size_t i, nDev = ARRAY_CARDINALITY(dev);
99 virPCIDeviceListPtr activeDevs = NULL, inactiveDevs = NULL;
102 if (!(activeDevs = virPCIDeviceListNew()) ||
103 !(inactiveDevs = virPCIDeviceListNew()))
106 CHECK_LIST_COUNT(activeDevs, 0);
107 CHECK_LIST_COUNT(inactiveDevs, 0);
109 for (i = 0; i < nDev; i++) {
110 if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)) ||
111 virPCIDeviceSetStubDriver(dev[i], "pci-stub") < 0)
114 if (virPCIDeviceDetach(dev[i], activeDevs, inactiveDevs) < 0)
117 if (testVirPCIDeviceCheckDriver(dev[i], "pci-stub") < 0)
120 CHECK_LIST_COUNT(activeDevs, 0);
121 CHECK_LIST_COUNT(inactiveDevs, i + 1);
126 for (i = 0; i < nDev; i++)
127 virPCIDeviceFree(dev[i]);
128 virObjectUnref(activeDevs);
129 virObjectUnref(inactiveDevs);
134 testVirPCIDeviceReset(const void *opaque ATTRIBUTE_UNUSED)
137 virPCIDevicePtr dev[] = {NULL, NULL, NULL};
138 size_t i, nDev = ARRAY_CARDINALITY(dev);
139 virPCIDeviceListPtr activeDevs = NULL, inactiveDevs = NULL;
142 if (!(activeDevs = virPCIDeviceListNew()) ||
143 !(inactiveDevs = virPCIDeviceListNew()))
146 CHECK_LIST_COUNT(activeDevs, 0);
147 CHECK_LIST_COUNT(inactiveDevs, 0);
149 for (i = 0; i < nDev; i++) {
150 if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)) ||
151 virPCIDeviceSetStubDriver(dev[i], "pci-stub") < 0)
154 if (virPCIDeviceReset(dev[i], activeDevs, inactiveDevs) < 0)
160 for (i = 0; i < nDev; i++)
161 virPCIDeviceFree(dev[i]);
162 virObjectUnref(activeDevs);
163 virObjectUnref(inactiveDevs);
168 testVirPCIDeviceReattach(const void *opaque ATTRIBUTE_UNUSED)
171 virPCIDevicePtr dev[] = {NULL, NULL, NULL};
172 size_t i, nDev = ARRAY_CARDINALITY(dev);
173 virPCIDeviceListPtr activeDevs = NULL, inactiveDevs = NULL;
176 if (!(activeDevs = virPCIDeviceListNew()) ||
177 !(inactiveDevs = virPCIDeviceListNew()))
180 for (i = 0; i < nDev; i++) {
181 if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)))
184 if (virPCIDeviceListAdd(inactiveDevs, dev[i]) < 0) {
185 virPCIDeviceFree(dev[i]);
189 CHECK_LIST_COUNT(activeDevs, 0);
190 CHECK_LIST_COUNT(inactiveDevs, i + 1);
192 if (virPCIDeviceSetStubDriver(dev[i], "pci-stub") < 0)
196 CHECK_LIST_COUNT(activeDevs, 0);
197 CHECK_LIST_COUNT(inactiveDevs, nDev);
199 for (i = 0; i < nDev; i++) {
200 if (virPCIDeviceReattach(dev[i], activeDevs, inactiveDevs) < 0)
203 CHECK_LIST_COUNT(activeDevs, 0);
204 CHECK_LIST_COUNT(inactiveDevs, nDev - i - 1);
209 virObjectUnref(activeDevs);
210 virObjectUnref(inactiveDevs);
214 struct testPCIDevData {
218 unsigned int function;
223 testVirPCIDeviceIsAssignable(const void *opaque)
225 const struct testPCIDevData *data = opaque;
229 if (!(dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function)))
232 if (virPCIDeviceIsAssignable(dev, true))
235 virPCIDeviceFree(dev);
241 testVirPCIDeviceDetachSingle(const void *opaque)
243 const struct testPCIDevData *data = opaque;
247 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
251 if (virPCIDeviceSetStubDriver(dev, "pci-stub") < 0 ||
252 virPCIDeviceDetach(dev, NULL, NULL) < 0)
257 virPCIDeviceFree(dev);
262 testVirPCIDeviceDetachFail(const void *opaque)
264 const struct testPCIDevData *data = opaque;
268 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
272 if (virPCIDeviceSetStubDriver(dev, "vfio-pci") < 0)
275 if (virPCIDeviceDetach(dev, NULL, NULL) < 0) {
276 if (virTestGetVerbose() || virTestGetDebug())
277 virDispatchError(NULL);
281 virReportError(VIR_ERR_INTERNAL_ERROR,
282 "Attaching device %s to %s should have failed",
283 virPCIDeviceGetName(dev),
284 virPCIDeviceGetStubDriver(dev));
288 virPCIDeviceFree(dev);
293 testVirPCIDeviceReattachSingle(const void *opaque)
295 const struct testPCIDevData *data = opaque;
299 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
303 virPCIDeviceReattachInit(dev);
304 if (virPCIDeviceReattach(dev, NULL, NULL) < 0)
309 virPCIDeviceFree(dev);
314 testVirPCIDeviceCheckDriverTest(const void *opaque)
316 const struct testPCIDevData *data = opaque;
320 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
324 if (testVirPCIDeviceCheckDriver(dev, data->driver) < 0)
329 virPCIDeviceFree(dev);
334 testVirPCIDeviceUnbind(const void *opaque)
336 const struct testPCIDevData *data = opaque;
340 dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function);
344 if (virPCIDeviceUnbind(dev, false) < 0)
349 virPCIDeviceFree(dev);
353 # define FAKESYSFSDIRTEMPLATE abs_builddir "/fakesysfsdir-XXXXXX"
361 if (VIR_STRDUP_QUIET(fakesysfsdir, FAKESYSFSDIRTEMPLATE) < 0) {
362 fprintf(stderr, "Out of memory\n");
366 if (!mkdtemp(fakesysfsdir)) {
367 fprintf(stderr, "Cannot create fakesysfsdir");
371 setenv("LIBVIRT_FAKE_SYSFS_DIR", fakesysfsdir, 1);
373 # define DO_TEST(fnc) \
375 if (virtTestRun(#fnc, fnc, NULL) < 0) \
379 # define DO_TEST_PCI(fnc, domain, bus, slot, function) \
381 struct testPCIDevData data = { \
382 domain, bus, slot, function, NULL \
384 char *label = NULL; \
385 if (virAsprintf(&label, "%s(%04x:%02x:%02x.%x)", \
386 #fnc, domain, bus, slot, function) < 0) { \
390 if (virtTestRun(label, fnc, &data) < 0) \
395 # define DO_TEST_PCI_DRIVER(domain, bus, slot, function, driver) \
397 struct testPCIDevData data = { \
398 domain, bus, slot, function, driver \
400 char *label = NULL; \
401 if (virAsprintf(&label, "PCI driver %04x:%02x:%02x.%x is %s", \
402 domain, bus, slot, function, \
403 NULLSTR(driver)) < 0) { \
407 if (virtTestRun(label, testVirPCIDeviceCheckDriverTest, \
413 /* Changes made to individual devices are persistent and the
414 * tests often rely on the state set by previous tests.
417 DO_TEST(testVirPCIDeviceNew);
418 DO_TEST(testVirPCIDeviceDetach);
419 DO_TEST(testVirPCIDeviceReset);
420 DO_TEST(testVirPCIDeviceReattach);
421 DO_TEST_PCI(testVirPCIDeviceIsAssignable, 5, 0x90, 1, 0);
422 DO_TEST_PCI(testVirPCIDeviceIsAssignable, 1, 1, 0, 0);
424 DO_TEST_PCI(testVirPCIDeviceDetachFail, 0, 0x0a, 1, 0);
426 /* Reattach a device already bound to non-stub a driver */
427 DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915");
428 DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 1, 0);
429 DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915");
431 /* Reattach an unbound device */
432 DO_TEST_PCI(testVirPCIDeviceUnbind, 0, 0x0a, 1, 0);
433 DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, NULL);
434 DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 1, 0);
435 DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915");
437 /* Detach an unbound device */
438 DO_TEST_PCI_DRIVER(0, 0x0a, 2, 0, NULL);
439 DO_TEST_PCI(testVirPCIDeviceDetachSingle, 0, 0x0a, 2, 0);
440 DO_TEST_PCI_DRIVER(0, 0x0a, 2, 0, "pci-stub");
442 /* Reattach an unknown unbound device */
443 DO_TEST_PCI_DRIVER(0, 0x0a, 3, 0, NULL);
444 DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 3, 0);
445 DO_TEST_PCI_DRIVER(0, 0x0a, 3, 0, NULL);
447 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
448 virFileDeleteTree(fakesysfsdir);
450 VIR_FREE(fakesysfsdir);
452 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
455 VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virpcimock.so")