Chunyan Liu wrote: > Add unit test for hostdev common library. Current tests are based on virpcimock. > > Signed-off-by: Chunyan Liu <cyliu@xxxxxxxx> > --- > tests/Makefile.am | 5 + > tests/virhostdevtest.c | 481 ++++++++++++++++++++++++++++++++++++++++++++++++ > tests/virpcimock.c | 23 +++- > 3 files changed, 508 insertions(+), 1 deletions(-) > create mode 100644 tests/virhostdevtest.c > > diff --git a/tests/Makefile.am b/tests/Makefile.am > index 568b7a0..3e66d8c 100644 > --- a/tests/Makefile.am > +++ b/tests/Makefile.am > @@ -141,6 +141,7 @@ test_programs = virshtest sockettest \ > virportallocatortest \ > sysinfotest \ > virstoragetest \ > + virhostdevtest \ > $(NULL) > > if WITH_REMOTE > @@ -754,6 +755,10 @@ vircgroupmock_la_CFLAGS = $(AM_CFLAGS) > vircgroupmock_la_LDFLAGS = -module -avoid-version \ > -rpath /evil/libtool/hack/to/force/shared/lib/creation > > +virhostdevtest_SOURCES = \ > + virhostdevtest.c testutils.h testutils.c > +virhostdevtest_LDADD = $(LDADDS) > + > virpcitest_SOURCES = \ > virpcitest.c testutils.h testutils.c > virpcitest_LDADD = $(LDADDS) > diff --git a/tests/virhostdevtest.c b/tests/virhostdevtest.c > new file mode 100644 > index 0000000..5b45548 > --- /dev/null > +++ b/tests/virhostdevtest.c > @@ -0,0 +1,481 @@ > +/* > + * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. > Nitpick - Copyright should be updated to 2014 here and elsewhere in this series. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library. If not, see > + * <http://www.gnu.org/licenses/>. > + * > + * Author: Chunyan Liu <cyliu@xxxxxxxx> > + */ > + > +#include <config.h> > + > +#include "testutils.h" > + > +#ifdef __linux__ > + > +# include <stdlib.h> > +# include <stdio.h> > +# include <sys/types.h> > +# include <sys/stat.h> > +# include <fcntl.h> > +# include <virhostdev.h> > + > +# define VIR_FROM_THIS VIR_FROM_NONE > + > +# define CHECK_LIST_COUNT(list, cnt) \ > + if ((count = virPCIDeviceListCount(list)) != cnt) { \ > + virReportError(VIR_ERR_INTERNAL_ERROR, \ > + "Unexpected count of items in " #list ": %d, " \ > + "expecting %zu", count, (size_t) cnt); \ > + goto cleanup; \ > + } > + > +#ifdef DEBUG > +#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) > +#else > +#define DPRINTF(fmt, ...) do { } while (0) > +#endif > VIR_DEBUG can be used in place of this right? > + > +#define TEST_STATE_DIR abs_builddir "/hostdevmgr" > Indentation is off here. Fails 'make syntax-check' with cppi installed. > +static const char *drv_name = "test_driver"; > +static const char *dom_name = "test_domain"; > +static const unsigned char *uuid = > + (unsigned char *)("f92360b0-2541-8791-fb32-d1f838811541"); > +static int nhostdevs = 3; > +static virDomainHostdevDefPtr hostdevs[] = {NULL, NULL, NULL}; > +static virPCIDevicePtr dev[] = {NULL, NULL, NULL}; > +static virHostdevManagerPtr mgr = NULL; > + > +static void > +myCleanup(void) > +{ > + size_t i; > + for (i = 0; i < nhostdevs; i++) { > + virPCIDeviceFree(dev[i]); > + virDomainHostdevDefFree(hostdevs[i]); > + } > + > + if (mgr) { > + virObjectUnref(mgr->activePciHostdevs); > + virObjectUnref(mgr->inactivePciHostdevs); > + virObjectUnref(mgr->activeUsbHostdevs); > + VIR_FREE(mgr->stateDir); > + VIR_FREE(mgr); > + } > +} > + > +static int > +myInit(void) > +{ > + size_t i; > + > + for (i = 0; i < nhostdevs; i++) { > + virDomainHostdevSubsys subsys; > + hostdevs[i] = virDomainHostdevDefAlloc(); > + if (!hostdevs[i]) > + goto cleanup; > + hostdevs[i]->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; > + subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; > + subsys.u.pci.addr.domain = 0; > + subsys.u.pci.addr.bus = 0; > + subsys.u.pci.addr.slot = i + 1; > + subsys.u.pci.addr.function = 0; > + subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM; > + hostdevs[i]->source.subsys = subsys; > + } > + > + for (i = 0; i < nhostdevs; i++) { > + if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)) || > + virPCIDeviceSetStubDriver(dev[i], "pci-stub") < 0) > + goto cleanup; > + } > + > + if (VIR_ALLOC(mgr) < 0) > + goto cleanup; > + if ((mgr->activePciHostdevs = virPCIDeviceListNew()) == NULL) > + goto cleanup; > + if ((mgr->activeUsbHostdevs = virUSBDeviceListNew()) == NULL) > + goto cleanup; > + if ((mgr->inactivePciHostdevs = virPCIDeviceListNew()) == NULL) > + goto cleanup; > + if ((mgr->activeScsiHostdevs = virSCSIDeviceListNew()) == NULL) > + goto cleanup; > + if (VIR_STRDUP(mgr->stateDir, TEST_STATE_DIR) < 0) > + goto cleanup; > + if (virFileMakePath(mgr->stateDir) < 0) { > + goto cleanup; > + } > Parens can be dropped here. > + > + return 0; > + > +cleanup: > + myCleanup(); > + return -1; > +} > + > +static int > +testVirHostdevPreparePciHostdevs_unmanaged(const void *oaque ATTRIBUTE_UNUSED) > +{ > + int ret = -1; > + size_t i; > + int count, count1, count2; > + > + for (i = 0; i < nhostdevs; i++) { > + hostdevs[i]->managed = false; > + } > And here. > + > + /* Test invalid args */ > + DPRINTF("Test hostdev mgr=NULL\n"); > + if (!virHostdevPreparePciHostdevs(NULL, drv_name, dom_name, uuid, > + hostdevs, nhostdevs, 0)) > + goto cleanup; > + > + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); > + count2 = virPCIDeviceListCount(mgr->inactivePciHostdevs); > + > + /* Test normal functionality */ > + DPRINTF("Test 0 hostdevs\n"); > + if (virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, > + NULL, 0, 0) < 0) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + > + /* Test unmanaged hostdevs */ > + DPRINTF("Test >=1 unmanaged hostdevs\n"); > + if (virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, > + hostdevs, nhostdevs, 0) < 0) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 + 3); > + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2 - 3); > + > + /* Test conflict */ > + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); > + count2 = virPCIDeviceListCount(mgr->inactivePciHostdevs); > + DPRINTF("Test: prepare same hostdevs for same driver/domain again\n"); > + if (!virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, > + &hostdevs[0], 1, 0)) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2); > + > + DPRINTF("Test: prepare same hostdevs for same driver, diff domain again\n"); > + if (!virHostdevPreparePciHostdevs(mgr, drv_name, "test_domain1", uuid, > + &hostdevs[1], 1, 0)) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2); > + > + DPRINTF("Test: prepare same hostdevs for diff driver/domain again\n"); > + if (!virHostdevPreparePciHostdevs(mgr, "test_driver1", dom_name, uuid, > + &hostdevs[2], 1, 0)) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2); > + > + ret = 0; > + > +cleanup: > + return ret; > + > +} > + > +static int > +testVirHostdevReAttachPciHostdevs_unmanaged(const void *oaque ATTRIBUTE_UNUSED) > +{ > + int ret = -1; > + size_t i; > + int count, count1, count2; > + > + for (i = 0; i < nhostdevs; i++) { > + if (hostdevs[i]->managed != false) { > + DPRINTF("invalid test\n"); > + return -1; > + } > + } > + > + DPRINTF("Test hostdev mgr=NULL\n"); > + virHostdevReAttachPciHostdevs(NULL, drv_name, dom_name, > + hostdevs, nhostdevs); > + > + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); > + count2 = virPCIDeviceListCount(mgr->inactivePciHostdevs); > + > + DPRINTF("Test 0 hostdevs\n"); > + virHostdevReAttachPciHostdevs(mgr, drv_name, dom_name, NULL, 0); > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + > + DPRINTF("Test >=1 unmanaged hostdevs\n"); > + virHostdevReAttachPciHostdevs(mgr, drv_name, dom_name, hostdevs, nhostdevs); > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 - 3); > + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count2 + 3); > + > + ret = 0; > + > +cleanup: > + return ret; > + > +} > + > +static int > +testVirHostdevPreparePciHostdevs_managed(const void *oaque ATTRIBUTE_UNUSED) > +{ > + int ret = -1; > + size_t i; > + int count, count1; > + > + for (i = 0; i < nhostdevs; i++) { > + hostdevs[i]->managed = true; > + } > Unneeded parens. Looks good otherwise. Thanks for the test cases! Regards, Jim > + > + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); > + > + /* Test normal functionality */ > + DPRINTF("Test >=1 hostdevs\n"); > + if (virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, > + hostdevs, nhostdevs, 0) < 0) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 + 3); > + > + /* Test conflict */ > + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); > + DPRINTF("Test: prepare same hostdevs for same driver/domain again\n"); > + if (!virHostdevPreparePciHostdevs(mgr, drv_name, dom_name, uuid, > + &hostdevs[0], 1, 0)) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + > + DPRINTF("Test: prepare same hostdevs for same driver, diff domain again\n"); > + if (!virHostdevPreparePciHostdevs(mgr, drv_name, "test_domain1", uuid, > + &hostdevs[1], 1, 0)) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + > + DPRINTF("Test: prepare same hostdevs for diff driver/domain again\n"); > + if (!virHostdevPreparePciHostdevs(mgr, "test_driver1", dom_name, uuid, > + &hostdevs[2], 1, 0)) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + > + ret = 0; > + > +cleanup: > + return ret; > + > +} > + > +static int > +testVirHostdevReAttachPciHostdevs_managed(const void *oaque ATTRIBUTE_UNUSED) > +{ > + int ret = -1; > + size_t i; > + int count, count1; > + > + for (i = 0; i < nhostdevs; i++) { > + if (hostdevs[i]->managed != true) { > + DPRINTF("invalid test\n"); > + return -1; > + } > + } > + > + DPRINTF("Test hostdev mgr=NULL\n"); > + virHostdevReAttachPciHostdevs(NULL, drv_name, dom_name, > + hostdevs, nhostdevs); > + > + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); > + > + DPRINTF("Test 0 hostdevs\n"); > + virHostdevReAttachPciHostdevs(mgr, drv_name, dom_name, NULL, 0); > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + > + DPRINTF("Test >=1 hostdevs\n"); > + virHostdevReAttachPciHostdevs(mgr, drv_name, dom_name, hostdevs, nhostdevs); > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 - 3); > + > + ret = 0; > + > +cleanup: > + return ret; > + > +} > + > +static int > +testVirHostdevDetachPciNodeDevice(const void *oaque ATTRIBUTE_UNUSED) > +{ > + int ret = -1; > + size_t i; > + int count, count1; > + > + if (!virHostdevPciNodeDeviceDetach(NULL, dev[0])) > + goto cleanup; > + > + if (!virHostdevPciNodeDeviceDetach(mgr, NULL)) > + goto cleanup; > + > + for (i = 0; i < nhostdevs; i++) { > + count1 = virPCIDeviceListCount(mgr->inactivePciHostdevs); > + if (virHostdevPciNodeDeviceDetach(mgr, dev[i]) < 0) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count1 + 1); > + } > + > + ret = 0; > + > +cleanup: > + return ret; > +} > +static int > +testVirHostdevResetPciNodeDevice(const void *oaque ATTRIBUTE_UNUSED) > +{ > + int ret = -1; > + size_t i; > + > + if (!virHostdevPciNodeDeviceReset(NULL, dev[0])) > + goto cleanup; > + > + if (!virHostdevPciNodeDeviceReAttach(mgr, NULL)) > + goto cleanup; > + > + for (i = 0; i < nhostdevs; i++) { > + if (virHostdevPciNodeDeviceReset(mgr, dev[i]) < 0) > + goto cleanup; > + } > + > + ret = 0; > + > +cleanup: > + return ret; > + > +} > + > +static int > +testVirHostdevReAttachPciNodeDevice(const void *oaque ATTRIBUTE_UNUSED) > +{ > + int ret = -1; > + size_t i; > + int count, count1; > + > + if (!virHostdevPciNodeDeviceReAttach(NULL, dev[0])) > + goto cleanup; > + > + if (!virHostdevPciNodeDeviceReAttach(mgr, NULL)) > + goto cleanup; > + > + for (i = 0; i < nhostdevs; i++) { > + count1 = virPCIDeviceListCount(mgr->inactivePciHostdevs); > + if (virHostdevPciNodeDeviceReAttach(mgr, dev[i]) < 0) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->inactivePciHostdevs, count1 - 1); > + } > + > + ret = 0; > + > +cleanup: > + return ret; > + > +} > + > +static int > +testVirHostdevUpdateActivePciHostdevs(const void *oaque ATTRIBUTE_UNUSED) > +{ > + int ret = -1; > + int count, count1; > + > + DPRINTF("Test hostdev mgr=NULL\n"); > + if (!virHostdevUpdateActivePciHostdevs(NULL, hostdevs, nhostdevs, > + drv_name, dom_name)) > + goto cleanup; > + > + count1 = virPCIDeviceListCount(mgr->activePciHostdevs); > + > + DPRINTF("Test 0 hostdevs\n"); > + if (virHostdevUpdateActivePciHostdevs(mgr, NULL, 0, > + drv_name, dom_name) < 0) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1); > + > + DPRINTF("Test >=1 hostdevs\n"); > + if (virHostdevUpdateActivePciHostdevs(mgr, hostdevs, nhostdevs, > + drv_name, dom_name) < 0) > + goto cleanup; > + CHECK_LIST_COUNT(mgr->activePciHostdevs, count1 + 3); > + > + ret = 0; > + > +cleanup: > + return ret; > +} > + > +# define FAKESYSFSDIRTEMPLATE abs_builddir "/fakesysfsdir-XXXXXX" > + > +static int > +mymain(void) > +{ > + int ret = 0; > + char *fakesysfsdir; > + > + if (VIR_STRDUP_QUIET(fakesysfsdir, FAKESYSFSDIRTEMPLATE) < 0) { > + fprintf(stderr, "Out of memory\n"); > + abort(); > + } > + > + if (!mkdtemp(fakesysfsdir)) { > + fprintf(stderr, "Cannot create fakesysfsdir"); > + abort(); > + } > + > + setenv("LIBVIRT_FAKE_SYSFS_DIR", fakesysfsdir, 1); > + > +# define DO_TEST(fnc) \ > + do { \ > + DPRINTF("\nTesting: %s", #fnc); \ > + if (virtTestRun(#fnc, fnc, NULL) < 0) \ > + ret = -1; \ > + } while (0) > + > + if (myInit() < 0) > + fprintf(stderr, "Init data structures failed."); > + > + DO_TEST(testVirHostdevDetachPciNodeDevice); > + if (virHostdevHostSupportsPassthroughKVM()) { > + /* following tests would check KVM support */ > + DO_TEST(testVirHostdevPreparePciHostdevs_unmanaged); > + DO_TEST(testVirHostdevReAttachPciHostdevs_unmanaged); > + } > + DO_TEST(testVirHostdevResetPciNodeDevice); > + DO_TEST(testVirHostdevReAttachPciNodeDevice); > + if (virHostdevHostSupportsPassthroughKVM()) { > + /* following tests would check KVM support */ > + DO_TEST(testVirHostdevPreparePciHostdevs_managed); > + DO_TEST(testVirHostdevReAttachPciHostdevs_managed); > + } > + DO_TEST(testVirHostdevUpdateActivePciHostdevs); > + > + myCleanup(); > + > + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) > + virFileDeleteTree(fakesysfsdir); > + > + VIR_FREE(fakesysfsdir); > + > + return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; > +} > + > +VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virpcimock.so") > +#else > +int > +main(void) > +{ > + return EXIT_AM_SKIP; > +} > +#endif > diff --git a/tests/virpcimock.c b/tests/virpcimock.c > index 49759b0..5676db7 100644 > --- a/tests/virpcimock.c > +++ b/tests/virpcimock.c > @@ -149,7 +149,7 @@ static int pci_driver_handle_bind(const char *path); > static int pci_driver_handle_unbind(const char *path); > static int pci_driver_handle_new_id(const char *path); > static int pci_driver_handle_remove_id(const char *path); > - > +static int pci_handle_drivers_probe(const char *path); > > /* > * Helper functions > @@ -585,6 +585,8 @@ pci_driver_handle_change(int fd ATTRIBUTE_UNUSED, const char *path) > } else if (STREQ(file, "remove_id")) { > /* handle write to remove_id */ > ret = pci_driver_handle_remove_id(path); > + } else if (STREQ(file, "drivers_probe")) { > + ret = pci_handle_drivers_probe(path); > } else { > /* yet not handled write */ > ABORT("Not handled write to: %s", path); > @@ -724,6 +726,16 @@ cleanup: > return ret; > } > > +static int > +pci_handle_drivers_probe(const char *path) > +{ > + struct pciDevice *dev = pci_device_find_by_content(path); > + > + if (pci_device_autobind(dev) < 0) > + ABORT("Unable to do driver reprobe."); > + > + return 0; > +} > > /* > * Functions to load the symbols and init the environment > @@ -760,6 +772,9 @@ init_syms(void) > static void > init_env(void) > { > + int fd = -1; > + char *filepath; > + > if (fakesysfsdir) > return; > > @@ -791,6 +806,12 @@ init_env(void) > MAKE_PCI_DEVICE("0005:90:01.0", 0x1033, 0x0035); > MAKE_PCI_DEVICE("0005:90:01.1", 0x1033, 0x0035); > MAKE_PCI_DEVICE("0005:90:01.2", 0x1033, 0x00e0); > + > + /* make file drivers_probe */ > + if (virAsprintfQuiet(&filepath, "%s/drivers_probe", fakesysfsdir) < 0) > + ABORT_OOM(); > + if ((fd = realopen(filepath, O_CREAT|O_WRONLY, 0200)) < 0) > + ABORT("Unable to create: %s", filepath); > } > > > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list