VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/usb/tdUsb1.py@ 60634

Last change on this file since 60634 was 60634, checked in by vboxsync, 9 years ago

ValidationKit/usb: Format the port as a hexadecimal number because the filter requires it that way

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdUsb1.py 60634 2016-04-21 16:06:58Z vboxsync $
4
5"""
6VirtualBox Validation Kit - USB testcase and benchmark.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2014-2016 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 60634 $"
31
32
33# Standard Python imports.
34import os;
35import sys;
36import socket;
37
38# Only the main script needs to modify the path.
39try: __file__
40except: __file__ = sys.argv[0];
41g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
42sys.path.append(g_ksValidationKitDir);
43
44# Validation Kit imports.
45from testdriver import reporter;
46from testdriver import base;
47from testdriver import vbox;
48from testdriver import vboxcon;
49
50# USB gadget control import
51import usbgadget;
52
53class tdUsbBenchmark(vbox.TestDriver): # pylint: disable=R0902
54 """
55 USB benchmark.
56 """
57
58 # The available test devices
59 #
60 # The first key is the hostname of the host the test is running on.
61 # It contains a new dictionary with the attached gadgets based on the
62 # USB speed we want to test (Low, Full, High, Super).
63 # The parameters consist of the hostname of the gadget in the network
64 # and the hardware type.
65 kdGadgetParams = {
66 'adaris': {
67 'Low': ('usbtest.de.oracle.com', None),
68 'Full': ('usbtest.de.oracle.com', None),
69 'High': ('usbtest.de.oracle.com', None),
70 'Super': ('usbtest.de.oracle.com', None)
71 },
72 };
73
74 # Mappings of USB controllers to supported USB device speeds.
75 kdUsbSpeedMappings = {
76 'OHCI': ['Low', 'Full'],
77 'EHCI': ['High'],
78 'XHCI': ['Low', 'Full', 'High', 'Super']
79 };
80
81 def __init__(self):
82 vbox.TestDriver.__init__(self);
83 self.asRsrcs = None;
84 self.asTestVMsDef = ['tst-arch'];
85 self.asTestVMs = self.asTestVMsDef;
86 self.asSkipVMs = [];
87 self.asVirtModesDef = ['hwvirt', 'hwvirt-np', 'raw'];
88 self.asVirtModes = self.asVirtModesDef;
89 self.acCpusDef = [1, 2,];
90 self.acCpus = self.acCpusDef;
91 self.asUsbCtrlsDef = ['OHCI', 'EHCI', 'XHCI'];
92 self.asUsbCtrls = self.asUsbCtrlsDef;
93 self.asUsbSpeedDef = ['Low', 'Full', 'High', 'Super'];
94 self.asUsbSpeed = self.asUsbSpeedDef;
95 self.asUsbTestsDef = ['Compliance', 'Reattach'];
96 self.asUsbTests = self.asUsbTestsDef;
97 self.cUsbReattachCyclesDef = 100;
98 self.cUsbReattachCycles = self.cUsbReattachCyclesDef;
99 self.sHostname = socket.gethostname().lower();
100 self.sGadgetHostnameDef = 'usbtest.de.oracle.com';
101 self.uGadgetPortDef = None;
102
103 #
104 # Overridden methods.
105 #
106 def showUsage(self):
107 rc = vbox.TestDriver.showUsage(self);
108 reporter.log('');
109 reporter.log('tdUsb1 Options:');
110 reporter.log(' --virt-modes <m1[:m2[:]]');
111 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
112 reporter.log(' --cpu-counts <c1[:c2[:]]');
113 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
114 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
115 reporter.log(' Test the specified VMs in the given order. Use this to change');
116 reporter.log(' the execution order or limit the choice of VMs');
117 reporter.log(' Default: %s (all)' % (':'.join(self.asTestVMsDef)));
118 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
119 reporter.log(' Skip the specified VMs when testing.');
120 reporter.log(' --usb-ctrls <u1[:u2[:]]');
121 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.asUsbCtrlsDef)));
122 reporter.log(' --usb-speed <s1[:s2[:]]');
123 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.asUsbSpeedDef)));
124 reporter.log(' --usb-tests <s1[:s2[:]]');
125 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.asUsbTestsDef)));
126 reporter.log(' --usb-reattach-cycles <cycles>');
127 reporter.log(' Default: %s' % (self.cUsbReattachCyclesDef));
128 reporter.log(' --hostname: <hostname>');
129 reporter.log(' Default: %s' % (self.sHostname));
130 reporter.log(' --default-gadget-host <hostname>');
131 reporter.log(' Default: %s' % (self.sGadgetHostnameDef));
132 reporter.log(' --default-gadget-port <port>');
133 reporter.log(' Default: %s' % (6042));
134 return rc;
135
136 def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
137 if asArgs[iArg] == '--virt-modes':
138 iArg += 1;
139 if iArg >= len(asArgs): raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
140 self.asVirtModes = asArgs[iArg].split(':');
141 for s in self.asVirtModes:
142 if s not in self.asVirtModesDef:
143 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
144 % (s, ' '.join(self.asVirtModesDef)));
145 elif asArgs[iArg] == '--cpu-counts':
146 iArg += 1;
147 if iArg >= len(asArgs): raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
148 self.acCpus = [];
149 for s in asArgs[iArg].split(':'):
150 try: c = int(s);
151 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
152 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
153 self.acCpus.append(c);
154 elif asArgs[iArg] == '--test-vms':
155 iArg += 1;
156 if iArg >= len(asArgs): raise base.InvalidOption('The "--test-vms" takes colon separated list');
157 self.asTestVMs = asArgs[iArg].split(':');
158 for s in self.asTestVMs:
159 if s not in self.asTestVMsDef:
160 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
161 % (s, ' '.join(self.asTestVMsDef)));
162 elif asArgs[iArg] == '--skip-vms':
163 iArg += 1;
164 if iArg >= len(asArgs): raise base.InvalidOption('The "--skip-vms" takes colon separated list');
165 self.asSkipVMs = asArgs[iArg].split(':');
166 for s in self.asSkipVMs:
167 if s not in self.asTestVMsDef:
168 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s));
169 elif asArgs[iArg] == '--usb-ctrls':
170 iArg += 1;
171 if iArg >= len(asArgs): raise base.InvalidOption('The "--usb-ctrls" takes a colon separated list of USB controllers');
172 self.asUsbCtrls = asArgs[iArg].split(':');
173 for s in self.asUsbCtrls:
174 if s not in self.asUsbCtrlsDef:
175 reporter.log('warning: The "--usb-ctrls" value "%s" is not a valid USB controller.' % (s));
176 elif asArgs[iArg] == '--usb-speed':
177 iArg += 1;
178 if iArg >= len(asArgs): raise base.InvalidOption('The "--usb-speed" takes a colon separated list of USB speeds');
179 self.asUsbSpeed = asArgs[iArg].split(':');
180 for s in self.asUsbSpeed:
181 if s not in self.asUsbSpeedDef:
182 reporter.log('warning: The "--usb-speed" value "%s" is not a valid USB speed.' % (s));
183 elif asArgs[iArg] == '--usb-tests':
184 iArg += 1;
185 if iArg >= len(asArgs): raise base.InvalidOption('The "--usb-tests" takes a colon separated list of USB tests');
186 self.asUsbTests = asArgs[iArg].split(':');
187 for s in self.asUsbTests:
188 if s not in self.asUsbTestsDef:
189 reporter.log('warning: The "--usb-tests" value "%s" is not a valid USB test.' % (s));
190 elif asArgs[iArg] == '--usb-reattach-cycles':
191 iArg += 1;
192 if iArg >= len(asArgs): raise base.InvalidOption('The "--usb-reattach-cycles" takes cycle count');
193 try: self.cUsbReattachCycles = int(asArgs[iArg]);
194 except: raise base.InvalidOption('The "--usb-reattach-cycles" value "%s" is not an integer' \
195 % (asArgs[iArg],));
196 if self.cUsbReattachCycles <= 0:
197 raise base.InvalidOption('The "--usb-reattach-cycles" value "%s" is zero or negative.' \
198 % (self.cUsbReattachCycles,));
199 elif asArgs[iArg] == '--hostname':
200 iArg += 1;
201 if iArg >= len(asArgs): raise base.InvalidOption('The "--hostname" takes a hostname');
202 self.sHostname = asArgs[iArg];
203 elif asArgs[iArg] == '--default-gadget-host':
204 iArg += 1;
205 if iArg >= len(asArgs): raise base.InvalidOption('The "--default-gadget-host" takes a hostname');
206 self.sGadgetHostnameDef = asArgs[iArg];
207 elif asArgs[iArg] == '--default-gadget-port':
208 iArg += 1;
209 if iArg >= len(asArgs): raise base.InvalidOption('The "--default-gadget-port" takes port number');
210 try: self.uGadgetPortDef = int(asArgs[iArg]);
211 except: raise base.InvalidOption('The "--default-gadget-port" value "%s" is not an integer' \
212 % (asArgs[iArg],));
213 if self.uGadgetPortDef <= 0:
214 raise base.InvalidOption('The "--default-gadget-port" value "%s" is zero or negative.' \
215 % (self.uGadgetPortDef,));
216 else:
217 return vbox.TestDriver.parseOption(self, asArgs, iArg);
218 return iArg + 1;
219
220 def completeOptions(self):
221 # Remove skipped VMs from the test list.
222 for sVM in self.asSkipVMs:
223 try: self.asTestVMs.remove(sVM);
224 except: pass;
225
226 return vbox.TestDriver.completeOptions(self);
227
228 def getResourceSet(self):
229 # Construct the resource list the first time it's queried.
230 if self.asRsrcs is None:
231 self.asRsrcs = [];
232
233 if 'tst-arch' in self.asTestVMs:
234 self.asRsrcs.append('4.2/usb/tst-arch.vdi');
235
236 return self.asRsrcs;
237
238 def actionConfig(self):
239
240 # Some stupid trickery to guess the location of the iso. ## fixme - testsuite unzip ++
241 sVBoxValidationKit_iso = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxValidationKit.iso'));
242 if not os.path.isfile(sVBoxValidationKit_iso):
243 sVBoxValidationKit_iso = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxTestSuite.iso'));
244 if not os.path.isfile(sVBoxValidationKit_iso):
245 sVBoxValidationKit_iso = '/mnt/ramdisk/vbox/svn/trunk/validationkit/VBoxValidationKit.iso';
246 if not os.path.isfile(sVBoxValidationKit_iso):
247 sVBoxValidationKit_iso = '/mnt/ramdisk/vbox/svn/trunk/testsuite/VBoxTestSuite.iso';
248 if not os.path.isfile(sVBoxValidationKit_iso):
249 sCur = os.getcwd();
250 for i in range(0, 10):
251 sVBoxValidationKit_iso = os.path.join(sCur, 'validationkit/VBoxValidationKit.iso');
252 if os.path.isfile(sVBoxValidationKit_iso):
253 break;
254 sVBoxValidationKit_iso = os.path.join(sCur, 'testsuite/VBoxTestSuite.iso');
255 if os.path.isfile(sVBoxValidationKit_iso):
256 break;
257 sCur = os.path.abspath(os.path.join(sCur, '..'));
258 if i is None: pass; # shut up pychecker/pylint.
259 if not os.path.isfile(sVBoxValidationKit_iso):
260 sVBoxValidationKit_iso = '/home/bird/validationkit/VBoxValidationKit.iso';
261 if not os.path.isfile(sVBoxValidationKit_iso):
262 sVBoxValidationKit_iso = '/home/bird/testsuite/VBoxTestSuite.iso';
263
264 # Make sure vboxapi has been imported so we can use the constants.
265 if not self.importVBoxApi():
266 return False;
267
268 #
269 # Configure the VMs we're going to use.
270 #
271
272 # Linux VMs
273 if 'tst-arch' in self.asTestVMs:
274 oVM = self.createTestVM('tst-arch', 1, '4.2/usb/tst-arch.vdi', sKind = 'ArchLinux_64', fIoApic = True, \
275 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
276 sDvdImage = sVBoxValidationKit_iso);
277 if oVM is None:
278 return False;
279
280 return True;
281
282 def actionExecute(self):
283 """
284 Execute the testcase.
285 """
286 fRc = self.testUsb();
287 return fRc;
288
289 def getGadgetParams(self, sHostname, sSpeed):
290 """
291 Returns the gadget hostname and port from the
292 given hostname the test is running on and device speed we want to test.
293 """
294 kdGadgetsConfigured = self.kdGadgetParams.get(sHostname);
295 if kdGadgetsConfigured is not None:
296 return kdGadgetsConfigured.get(sSpeed);
297
298 return (self.sGadgetHostnameDef, self.uGadgetPortDef);
299
300 #
301 # Test execution helpers.
302 #
303 def testUsbCompliance(self, oSession, oTxsSession, sUsbCtrl, sSpeed):
304 """
305 Test VirtualBoxs USB stack in a VM.
306 """
307 # Get configured USB test devices from hostname we are running on
308 sGadgetHost, uGadgetPort = self.getGadgetParams(self.sHostname, sSpeed);
309
310 oUsbGadget = usbgadget.UsbGadget();
311 reporter.log('Connecting to UTS: ' + sGadgetHost);
312 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost, uPort = uGadgetPort);
313 if fRc is True:
314 reporter.log('Connect succeeded');
315 self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost + (':%s' % oUsbGadget.getUsbIpPort()), [], []);
316
317 # Create test device gadget and a filter to attach the device automatically.
318 fRc = oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest);
319 if fRc is True:
320 iBusId, _ = oUsbGadget.getGadgetBusAndDevId();
321 fRc = oSession.addUsbDeviceFilter('Compliance device', sVendorId = '0525', sProductId = 'a4a0', \
322 sPort = format(iBusId, 'x'));
323 if fRc is True:
324
325 # Wait a moment to let the USB device appear
326 self.sleep(3);
327
328 tupCmdLine = ('UsbTest', );
329 # Exclude a few tests which hang and cause a timeout, need investigation.
330 if sUsbCtrl is 'XHCI':
331 tupCmdLine = tupCmdLine + ('--exclude', '10', '--exclude', '24');
332
333 fRc = self.txsRunTest(oTxsSession, 'UsbTest', 3600 * 1000, \
334 '${CDROM}/${OS/ARCH}/UsbTest${EXESUFF}', tupCmdLine);
335 if not fRc:
336 reporter.testFailure('Running USB test utility failed');
337
338 else:
339 reporter.testFailure('Failed to impersonate test device');
340
341 oUsbGadget.disconnectFrom();
342 else:
343 reporter.testFailure('Failed to create USB device filter');
344
345 self.oVBox.host.removeUSBDeviceSource(sGadgetHost);
346 else:
347 reporter.testFailure('Failed to connect to USB gadget');
348
349 return fRc;
350
351 def testUsbReattach(self, oSession, oTxsSession, sUsbCtrl, sSpeed): # pylint: disable=W0613
352 """
353 Tests that rapid connect/disconnect cycles work.
354 """
355 # Get configured USB test devices from hostname we are running on
356 sGadgetHost, uGadgetPort = self.getGadgetParams(self.sHostname, sSpeed);
357
358 oUsbGadget = usbgadget.UsbGadget();
359 reporter.log('Connecting to UTS: ' + sGadgetHost);
360 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost, uPort = uGadgetPort);
361 if fRc is True:
362 self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost + (':%s' % oUsbGadget.getUsbIpPort()), [], []);
363
364 # Create test device gadget and a filter to attach the device automatically.
365 fRc = oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest);
366 if fRc is True:
367 iBusId, _ = oUsbGadget.getGadgetBusAndDevId();
368 fRc = oSession.addUsbDeviceFilter('Compliance device', sVendorId = '0525', sProductId = 'a4a0', \
369 sPort = str(iBusId));
370 if fRc is True:
371
372 # Wait a moment to let the USB device appear
373 self.sleep(3);
374
375 # Do a rapid disconnect reconnect cycle. Wait a second before disconnecting
376 # again or it will happen so fast that the VM can't attach the new device.
377 # @todo: Get rid of the constant wait and use an event to get notified when
378 # the device was attached.
379 for iCycle in xrange (0, self.cUsbReattachCycles):
380 fRc = oUsbGadget.disconnectUsb();
381 fRc = fRc and oUsbGadget.connectUsb();
382 if not fRc:
383 reporter.testFailure('Reattach cycle %s failed on the gadget device' % (iCycle));
384 break;
385 self.sleep(1);
386
387 else:
388 reporter.testFailure('Failed to impersonate test device');
389
390 oUsbGadget.disconnectFrom();
391 else:
392 reporter.testFailure('Failed to connect to USB gadget');
393 else:
394 reporter.testFailure('Failed to create USB device filter');
395
396 return fRc;
397
398 def testUsbOneCfg(self, sVmName, sUsbCtrl, sSpeed, sUsbTest):
399 """
400 Runs the specified VM thru one specified test.
401
402 Returns a success indicator on the general test execution. This is not
403 the actual test result.
404 """
405 oVM = self.getVmByName(sVmName);
406
407 # Reconfigure the VM
408 fRc = True;
409 oSession = self.openSession(oVM);
410 if oSession is not None:
411 fRc = fRc and oSession.enableVirtEx(True);
412 fRc = fRc and oSession.enableNestedPaging(True);
413
414 # Make sure controllers are disabled initially.
415 fRc = fRc and oSession.enableUsbOhci(False);
416 fRc = fRc and oSession.enableUsbEhci(False);
417 fRc = fRc and oSession.enableUsbXhci(False);
418
419 if sUsbCtrl == 'OHCI':
420 fRc = fRc and oSession.enableUsbOhci(True);
421 elif sUsbCtrl == 'EHCI':
422 fRc = fRc and oSession.enableUsbEhci(True);
423 elif sUsbCtrl == 'XHCI':
424 fRc = fRc and oSession.enableUsbXhci(True);
425 fRc = fRc and oSession.saveSettings();
426 fRc = oSession.close() and fRc and True; # pychecker hack.
427 oSession = None;
428 else:
429 fRc = False;
430
431 # Start up.
432 if fRc is True:
433 self.logVmInfo(oVM);
434 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = False);
435 if oSession is not None:
436 self.addTask(oSession);
437
438 # Fudge factor - Allow the guest to finish starting up.
439 self.sleep(5);
440
441 if sUsbTest == 'Compliance':
442 fRc = self.testUsbCompliance(oSession, oTxsSession, sUsbCtrl, sSpeed);
443 elif sUsbTest == 'Reattach':
444 fRc = self.testUsbReattach(oSession, oTxsSession, sUsbCtrl, sSpeed);
445
446 # cleanup.
447 self.removeTask(oTxsSession);
448 self.terminateVmBySession(oSession)
449 else:
450 fRc = False;
451 return fRc;
452
453 def testUsbForOneVM(self, sVmName):
454 """
455 Runs one VM thru the various configurations.
456 """
457 reporter.testStart(sVmName);
458 for sUsbCtrl in self.asUsbCtrls:
459 reporter.testStart(sUsbCtrl)
460 for sUsbSpeed in self.asUsbSpeed:
461 asSupportedSpeeds = self.kdUsbSpeedMappings.get(sUsbCtrl);
462 if sUsbSpeed in asSupportedSpeeds:
463 reporter.testStart(sUsbSpeed)
464 for sUsbTest in self.asUsbTests:
465 reporter.testStart(sUsbTest)
466 fRc = self.testUsbOneCfg(sVmName, sUsbCtrl, sUsbSpeed, sUsbTest);
467 reporter.testDone();
468 reporter.testDone();
469 reporter.testDone();
470 reporter.testDone();
471 return fRc;
472
473 def testUsb(self):
474 """
475 Executes USB test.
476 """
477
478 reporter.log("Running on host: " + self.sHostname);
479
480 # Loop thru the test VMs.
481 for sVM in self.asTestVMs:
482 # run test on the VM.
483 fRc = self.testUsbForOneVM(sVM);
484
485 return fRc;
486
487
488
489if __name__ == '__main__':
490 sys.exit(tdUsbBenchmark().main(sys.argv));
491
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette