Add missing libxml2-tools dependency
[archive/platform/upstream/libvirt.git] / tests / virusbtest.c
1 /*
2  * Copyright (C) 2013-2014 Red Hat, Inc.
3  *
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.
8  *
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.
13  *
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/>.
17  *
18  * Author: Jan Tomko <jtomko@redhat.com>
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23
24 #include "viralloc.h"
25 #include "virerror.h"
26 #include "virfile.h"
27 #include "virusb.h"
28
29 #include "testutils.h"
30
31 #define VIR_FROM_THIS VIR_FROM_NONE
32
33 typedef enum {
34     FIND_BY_ALL,
35     FIND_BY_VENDOR,
36     FIND_BY_BUS
37 } testUSBFindFlags;
38
39 struct findTestInfo {
40     const char *name;
41     unsigned int vendor;
42     unsigned int product;
43     unsigned int bus;
44     unsigned int devno;
45     const char *vroot;
46     bool mandatory;
47     int how;
48     bool expectFailure;
49 };
50
51 static int testDeviceFileActor(virUSBDevicePtr dev,
52                                const char *path,
53                                void *opaque ATTRIBUTE_UNUSED)
54 {
55     char *str = NULL;
56     int ret = 0;
57
58     if (virAsprintf(&str, USB_DEVFS "%03d/%03d",
59                     virUSBDeviceGetBus(dev),
60                     virUSBDeviceGetDevno(dev)) < 0)
61         return -1;
62
63     if (STRNEQ(path, str)) {
64         virReportError(VIR_ERR_INTERNAL_ERROR,
65                        "Device path '%s' does not match expected '%s'",
66                        path, str);
67         ret = -1;
68     }
69     VIR_FREE(str);
70     return ret;
71 }
72
73 static int testDeviceFind(const void *opaque)
74 {
75     const struct findTestInfo *info = opaque;
76     int ret = -1;
77     virUSBDevicePtr dev = NULL;
78     virUSBDeviceListPtr devs = NULL;
79     int rv = 0;
80     size_t i, ndevs = 0;
81
82     switch (info->how) {
83     case FIND_BY_ALL:
84         rv = virUSBDeviceFind(info->vendor, info->product,
85                               info->bus, info->devno,
86                               info->vroot, info->mandatory, &dev);
87         break;
88     case FIND_BY_VENDOR:
89         rv = virUSBDeviceFindByVendor(info->vendor, info->product,
90                                       info->vroot, info->mandatory, &devs);
91         break;
92     case FIND_BY_BUS:
93         rv = virUSBDeviceFindByBus(info->bus, info->devno,
94                                    info->vroot, info->mandatory, &dev);
95         break;
96     }
97
98     if (info->expectFailure) {
99         if (rv == 0) {
100             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
101                            "unexpected success");
102         } else {
103             ret = 0;
104         }
105         goto cleanup;
106     } else if (rv < 0) {
107         goto cleanup;
108     }
109
110     switch (info->how) {
111     case FIND_BY_ALL:
112     case FIND_BY_BUS:
113         if (virUSBDeviceFileIterate(dev, testDeviceFileActor, NULL) < 0)
114             goto cleanup;
115         break;
116
117     case FIND_BY_VENDOR:
118         ndevs = virUSBDeviceListCount(devs);
119
120         for (i = 0; i < ndevs; i++) {
121             virUSBDevicePtr device = virUSBDeviceListGet(devs, i);
122             if (virUSBDeviceFileIterate(device, testDeviceFileActor, NULL) < 0)
123                 goto cleanup;
124         }
125         break;
126     }
127
128     ret = 0;
129
130  cleanup:
131     virObjectUnref(devs);
132     virUSBDeviceFree(dev);
133     return ret;
134 }
135
136
137 static int
138 testCheckNdevs(const char* occasion,
139                size_t got,
140                size_t expected)
141 {
142     if (got != expected) {
143         virReportError(VIR_ERR_INTERNAL_ERROR,
144                        "%s: got %zu devices, expected %zu",
145                        occasion, got, expected);
146         return -1;
147     }
148     return 0;
149 }
150
151
152 static int
153 testUSBList(const void *opaque ATTRIBUTE_UNUSED)
154 {
155     virUSBDeviceListPtr list = NULL;
156     virUSBDeviceListPtr devlist = NULL;
157     virUSBDevicePtr dev = NULL;
158     int ret = -1;
159     size_t i, ndevs;
160
161     if (!(list = virUSBDeviceListNew()))
162         goto cleanup;
163
164 #define EXPECTED_NDEVS_ONE 3
165     if (virUSBDeviceFindByVendor(0x1d6b, 0x0002, NULL, true, &devlist) < 0)
166         goto cleanup;
167
168     ndevs = virUSBDeviceListCount(devlist);
169     if (testCheckNdevs("After first find", ndevs, EXPECTED_NDEVS_ONE) < 0)
170         goto cleanup;
171
172     for (i = 0; i < ndevs; i++) {
173         dev = virUSBDeviceListGet(devlist, 0);
174         dev = virUSBDeviceListSteal(devlist, dev);
175
176         if (virUSBDeviceListAdd(list, dev) < 0)
177             goto cleanup;
178         dev = NULL;
179     }
180
181     virObjectUnref(devlist);
182     devlist = NULL;
183
184     ndevs = virUSBDeviceListCount(list);
185     if (testCheckNdevs("After first loop", ndevs, EXPECTED_NDEVS_ONE) < 0)
186         goto cleanup;
187
188 #define EXPECTED_NDEVS_TWO 3
189     if (virUSBDeviceFindByVendor(0x18d1, 0x4e22, NULL, true, &devlist) < 0)
190         goto cleanup;
191
192     ndevs = virUSBDeviceListCount(devlist);
193     if (testCheckNdevs("After second find", ndevs, EXPECTED_NDEVS_TWO) < 0)
194         goto cleanup;
195     for (i = 0; i < ndevs; i++) {
196         dev = virUSBDeviceListGet(devlist, 0);
197         dev = virUSBDeviceListSteal(devlist, dev);
198
199         if (virUSBDeviceListAdd(list, dev) < 0)
200             goto cleanup;
201         dev = NULL;
202     }
203
204     if (testCheckNdevs("After second loop",
205                        virUSBDeviceListCount(list),
206                        EXPECTED_NDEVS_ONE + EXPECTED_NDEVS_TWO) < 0)
207         goto cleanup;
208
209     if (virUSBDeviceFind(0x18d1, 0x4e22, 1, 20, NULL, true, &dev) < 0)
210         goto cleanup;
211
212     if (!virUSBDeviceListFind(list, dev)) {
213         virReportError(VIR_ERR_INTERNAL_ERROR,
214                        "Device '%s' not in list when it should be",
215                        virUSBDeviceGetName(dev));
216         goto cleanup;
217     }
218
219     virUSBDeviceListDel(list, dev);
220     dev = NULL;
221
222     if (testCheckNdevs("After deleting one",
223                        virUSBDeviceListCount(list),
224                        EXPECTED_NDEVS_ONE + EXPECTED_NDEVS_TWO - 1) < 0)
225         goto cleanup;
226
227     ret = 0;
228
229  cleanup:
230     virObjectUnref(list);
231     virObjectUnref(devlist);
232     virUSBDeviceFree(dev);
233     return ret;
234 }
235
236
237 static int
238 mymain(void)
239 {
240     int rv = 0;
241
242 #define DO_TEST_FIND_FULL(name, vend, prod, bus, devno, vroot, mand, how, fail) \
243     do {                                                                    \
244         struct findTestInfo data = { name, vend, prod, bus,                 \
245             devno, vroot, mand, how, fail                                   \
246         };                                                                  \
247         if (virtTestRun("USBDeviceFind " name, testDeviceFind, &data) < 0)  \
248             rv = -1;                                                        \
249     } while (0)
250
251 #define DO_TEST_FIND(name, vend, prod, bus, devno)                          \
252     DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, true,             \
253                       FIND_BY_ALL, false)
254 #define DO_TEST_FIND_FAIL(name, vend, prod, bus, devno)                     \
255     DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, true,             \
256                       FIND_BY_ALL, true)
257
258 #define DO_TEST_FIND_BY_BUS(name, bus, devno)                               \
259     DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true,               \
260                       FIND_BY_BUS, false)
261 #define DO_TEST_FIND_BY_BUS_FAIL(name, bus, devno)                          \
262     DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true,               \
263                       FIND_BY_BUS, true)
264
265 #define DO_TEST_FIND_BY_VENDOR(name, vend, prod)                            \
266     DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, true,               \
267                       FIND_BY_VENDOR, false)
268 #define DO_TEST_FIND_BY_VENDOR_FAIL(name, vend, prod)                       \
269     DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, true,               \
270                       FIND_BY_VENDOR, true)
271
272     DO_TEST_FIND("Nexus", 0x18d1, 0x4e22, 1, 20);
273     DO_TEST_FIND_FAIL("Nexus wrong devnum", 0x18d1, 0x4e22, 1, 25);
274     DO_TEST_FIND_FAIL("Bogus", 0xf00d, 0xbeef, 1024, 768);
275
276     DO_TEST_FIND_BY_BUS("integrated camera", 1, 5);
277     DO_TEST_FIND_BY_BUS_FAIL("wrong bus/devno combination", 2, 20);
278     DO_TEST_FIND_BY_BUS_FAIL("missing bus", 5, 20);
279     DO_TEST_FIND_BY_BUS_FAIL("missing devnum", 1, 158);
280
281     DO_TEST_FIND_BY_VENDOR("Nexus (multiple results)", 0x18d1, 0x4e22);
282     DO_TEST_FIND_BY_VENDOR_FAIL("Bogus vendor and product", 0xf00d, 0xbeef);
283     DO_TEST_FIND_BY_VENDOR_FAIL("Valid vendor", 0x1d6b, 0xbeef);
284
285     if (virtTestRun("USB List test", testUSBList, NULL) < 0)
286         rv = -1;
287
288     if (rv < 0)
289         return EXIT_FAILURE;
290     return EXIT_SUCCESS;
291 }
292
293 VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virusbmock.so")