VirtualBox

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

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

ValidationKit/tdUsb1: Make sure we use a super speed capable gadget for the tests where it is required

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdUsb1.py 60856 2016-05-06 09:04:21Z 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: 60856 $"
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 fSuperSpeed = False;
318 if sSpeed == 'Super':
319 fSuperSpeed = True;
320
321 # Create test device gadget and a filter to attach the device automatically.
322 fRc = self.oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest, fSuperSpeed);
323 if fRc is True:
324 iBusId, _ = oUsbGadget.getGadgetBusAndDevId();
325 fRc = oSession.addUsbDeviceFilter('Compliance device', sVendorId = '0525', sProductId = 'a4a0', \
326 sPort = format(iBusId, 'x'));
327 if fRc is True:
328
329 # Wait a moment to let the USB device appear
330 self.sleep(3);
331
332 tupCmdLine = ('UsbTest', );
333 # Exclude a few tests which hang and cause a timeout, need investigation.
334 if sUsbCtrl is 'XHCI':
335 tupCmdLine = tupCmdLine + ('--exclude', '10', '--exclude', '24');
336
337 fRc = self.txsRunTest(oTxsSession, 'UsbTest', 3600 * 1000, \
338 '${CDROM}/${OS/ARCH}/UsbTest${EXESUFF}', tupCmdLine);
339 if not fRc:
340 reporter.testFailure('Running USB test utility failed');
341
342 else:
343 reporter.testFailure('Failed to impersonate test device');
344
345 oUsbGadget.disconnectFrom();
346 else:
347 reporter.testFailure('Failed to create USB device filter');
348
349 self.oVBox.host.removeUSBDeviceSource(sGadgetHost);
350 else:
351 reporter.testFailure('Failed to connect to USB gadget');
352
353 return fRc;
354
355 def testUsbReattach(self, oSession, oTxsSession, sUsbCtrl, sSpeed): # pylint: disable=W0613
356 """
357 Tests that rapid connect/disconnect cycles work.
358 """
359 # Get configured USB test devices from hostname we are running on
360 sGadgetHost, uGadgetPort = self.getGadgetParams(self.sHostname, sSpeed);
361
362 oUsbGadget = usbgadget.UsbGadget();
363 reporter.log('Connecting to UTS: ' + sGadgetHost);
364 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost, uPort = uGadgetPort);
365 if fRc is True:
366 self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost + (':%s' % oUsbGadget.getUsbIpPort()), [], []);
367
368 fSuperSpeed = False;
369 if sSpeed == 'Super':
370 fSuperSpeed = True;
371
372 # Create test device gadget and a filter to attach the device automatically.
373 fRc = self.oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest, fSuperSpeed);
374 if fRc is True:
375 iBusId, _ = oUsbGadget.getGadgetBusAndDevId();
376 fRc = oSession.addUsbDeviceFilter('Compliance device', sVendorId = '0525', sProductId = 'a4a0', \
377 sPort = str(iBusId));
378 if fRc is True:
379
380 # Wait a moment to let the USB device appear
381 self.sleep(3);
382
383 # Do a rapid disconnect reconnect cycle. Wait a second before disconnecting
384 # again or it will happen so fast that the VM can't attach the new device.
385 # @todo: Get rid of the constant wait and use an event to get notified when
386 # the device was attached.
387 for iCycle in xrange (0, self.cUsbReattachCycles):
388 fRc = oUsbGadget.disconnectUsb();
389 fRc = fRc and oUsbGadget.connectUsb();
390 if not fRc:
391 reporter.testFailure('Reattach cycle %s failed on the gadget device' % (iCycle));
392 break;
393 self.sleep(1);
394
395 else:
396 reporter.testFailure('Failed to impersonate test device');
397
398 oUsbGadget.disconnectFrom();
399 else:
400 reporter.testFailure('Failed to connect to USB gadget');
401 else:
402 reporter.testFailure('Failed to create USB device filter');
403
404 return fRc;
405
406 def testUsbOneCfg(self, sVmName, sUsbCtrl, sSpeed, sUsbTest):
407 """
408 Runs the specified VM thru one specified test.
409
410 Returns a success indicator on the general test execution. This is not
411 the actual test result.
412 """
413 oVM = self.getVmByName(sVmName);
414
415 # Reconfigure the VM
416 fRc = True;
417 oSession = self.openSession(oVM);
418 if oSession is not None:
419 fRc = fRc and oSession.enableVirtEx(True);
420 fRc = fRc and oSession.enableNestedPaging(True);
421
422 # Make sure controllers are disabled initially.
423 fRc = fRc and oSession.enableUsbOhci(False);
424 fRc = fRc and oSession.enableUsbEhci(False);
425 fRc = fRc and oSession.enableUsbXhci(False);
426
427 if sUsbCtrl == 'OHCI':
428 fRc = fRc and oSession.enableUsbOhci(True);
429 elif sUsbCtrl == 'EHCI':
430 fRc = fRc and oSession.enableUsbEhci(True);
431 elif sUsbCtrl == 'XHCI':
432 fRc = fRc and oSession.enableUsbXhci(True);
433 fRc = fRc and oSession.saveSettings();
434 fRc = oSession.close() and fRc and True; # pychecker hack.
435 oSession = None;
436 else:
437 fRc = False;
438
439 # Start up.
440 if fRc is True:
441 self.logVmInfo(oVM);
442 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = False);
443 if oSession is not None:
444 self.addTask(oSession);
445
446 # Fudge factor - Allow the guest to finish starting up.
447 self.sleep(5);
448
449 if sUsbTest == 'Compliance':
450 fRc = self.testUsbCompliance(oSession, oTxsSession, sUsbCtrl, sSpeed);
451 elif sUsbTest == 'Reattach':
452 fRc = self.testUsbReattach(oSession, oTxsSession, sUsbCtrl, sSpeed);
453
454 # cleanup.
455 self.removeTask(oTxsSession);
456 self.terminateVmBySession(oSession)
457 else:
458 fRc = False;
459 return fRc;
460
461 def testUsbForOneVM(self, sVmName):
462 """
463 Runs one VM thru the various configurations.
464 """
465 reporter.testStart(sVmName);
466 for sUsbCtrl in self.asUsbCtrls:
467 reporter.testStart(sUsbCtrl)
468 for sUsbSpeed in self.asUsbSpeed:
469 asSupportedSpeeds = self.kdUsbSpeedMappings.get(sUsbCtrl);
470 if sUsbSpeed in asSupportedSpeeds:
471 reporter.testStart(sUsbSpeed)
472 for sUsbTest in self.asUsbTests:
473 reporter.testStart(sUsbTest)
474 fRc = self.testUsbOneCfg(sVmName, sUsbCtrl, sUsbSpeed, sUsbTest);
475 reporter.testDone();
476 reporter.testDone();
477 reporter.testDone();
478 reporter.testDone();
479 return fRc;
480
481 def testUsb(self):
482 """
483 Executes USB test.
484 """
485
486 reporter.log("Running on host: " + self.sHostname);
487
488 # Loop thru the test VMs.
489 for sVM in self.asTestVMs:
490 # run test on the VM.
491 fRc = self.testUsbForOneVM(sVM);
492
493 return fRc;
494
495
496
497if __name__ == '__main__':
498 sys.exit(tdUsbBenchmark().main(sys.argv));
499
Note: See TracBrowser for help on using the repository browser.

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