VirtualBox

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

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

ValidationKit/usb: More fixes for the server and client side

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 19.7 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdUsb1.py 60493 2016-04-14 13:45:31Z 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: 60493 $"
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 usbgadget2;
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 # The following is for local testing and not for the test lab.
67 #'adaris': {
68 # 'Low': ('beaglebone',),
69 # 'Full': ('beaglebone',),
70 # 'High': ('beaglebone',),
71 # 'Super': ('odroidxu3',)
72 #},
73 'adaris': {
74 'Low': ('127.0.0.1', 0),
75 'Full': ('127.0.0.1', 0),
76 'High': ('127.0.0.1', 0),
77 'Super': ('127.0.0.1', 0)
78 },
79 };
80
81 # Mappings of USB controllers to supported USB device speeds.
82 kdUsbSpeedMappings = {
83 'OHCI': ['Low', 'Full'],
84 'EHCI': ['High'],
85 'XHCI': ['Low', 'Full', 'High', 'Super']
86 };
87
88 def __init__(self):
89 vbox.TestDriver.__init__(self);
90 self.asRsrcs = None;
91 self.asTestVMsDef = ['tst-arch'];
92 self.asTestVMs = self.asTestVMsDef;
93 self.asSkipVMs = [];
94 self.asVirtModesDef = ['hwvirt', 'hwvirt-np', 'raw'];
95 self.asVirtModes = self.asVirtModesDef;
96 self.acCpusDef = [1, 2,];
97 self.acCpus = self.acCpusDef;
98 self.asUsbCtrlsDef = ['OHCI', 'EHCI', 'XHCI'];
99 self.asUsbCtrls = self.asUsbCtrlsDef;
100 self.asUsbSpeedDef = ['Low', 'Full', 'High', 'Super'];
101 self.asUsbSpeed = self.asUsbSpeedDef;
102 self.asUsbTestsDef = ['Compliance', 'Reattach'];
103 self.asUsbTests = self.asUsbTestsDef;
104 self.cUsbReattachCyclesDef = 100;
105 self.cUsbReattachCycles = self.cUsbReattachCyclesDef;
106 self.sHostname = socket.gethostname().lower();
107
108 #
109 # Overridden methods.
110 #
111 def showUsage(self):
112 rc = vbox.TestDriver.showUsage(self);
113 reporter.log('');
114 reporter.log('tdUsb1 Options:');
115 reporter.log(' --virt-modes <m1[:m2[:]]');
116 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
117 reporter.log(' --cpu-counts <c1[:c2[:]]');
118 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
119 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
120 reporter.log(' Test the specified VMs in the given order. Use this to change');
121 reporter.log(' the execution order or limit the choice of VMs');
122 reporter.log(' Default: %s (all)' % (':'.join(self.asTestVMsDef)));
123 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
124 reporter.log(' Skip the specified VMs when testing.');
125 reporter.log(' --usb-ctrls <u1[:u2[:]]');
126 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.asUsbCtrlsDef)));
127 reporter.log(' --usb-speed <s1[:s2[:]]');
128 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.asUsbSpeedDef)));
129 reporter.log(' --usb-tests <s1[:s2[:]]');
130 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.asUsbTestsDef)));
131 reporter.log(' --usb-reattach-cycles <cycles>');
132 reporter.log(' Default: %s' % (self.cUsbReattachCyclesDef));
133 return rc;
134
135 def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
136 if asArgs[iArg] == '--virt-modes':
137 iArg += 1;
138 if iArg >= len(asArgs): raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
139 self.asVirtModes = asArgs[iArg].split(':');
140 for s in self.asVirtModes:
141 if s not in self.asVirtModesDef:
142 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
143 % (s, ' '.join(self.asVirtModesDef)));
144 elif asArgs[iArg] == '--cpu-counts':
145 iArg += 1;
146 if iArg >= len(asArgs): raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
147 self.acCpus = [];
148 for s in asArgs[iArg].split(':'):
149 try: c = int(s);
150 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
151 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
152 self.acCpus.append(c);
153 elif asArgs[iArg] == '--test-vms':
154 iArg += 1;
155 if iArg >= len(asArgs): raise base.InvalidOption('The "--test-vms" takes colon separated list');
156 self.asTestVMs = asArgs[iArg].split(':');
157 for s in self.asTestVMs:
158 if s not in self.asTestVMsDef:
159 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
160 % (s, ' '.join(self.asTestVMsDef)));
161 elif asArgs[iArg] == '--skip-vms':
162 iArg += 1;
163 if iArg >= len(asArgs): raise base.InvalidOption('The "--skip-vms" takes colon separated list');
164 self.asSkipVMs = asArgs[iArg].split(':');
165 for s in self.asSkipVMs:
166 if s not in self.asTestVMsDef:
167 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s));
168 elif asArgs[iArg] == '--usb-ctrls':
169 iArg += 1;
170 if iArg >= len(asArgs): raise base.InvalidOption('The "--usb-ctrls" takes a colon separated list of USB controllers');
171 self.asUsbCtrls = asArgs[iArg].split(':');
172 for s in self.asUsbCtrls:
173 if s not in self.asUsbCtrlsDef:
174 reporter.log('warning: The "--usb-ctrls" value "%s" is not a valid USB controller.' % (s));
175 elif asArgs[iArg] == '--usb-speed':
176 iArg += 1;
177 if iArg >= len(asArgs): raise base.InvalidOption('The "--usb-speed" takes a colon separated list of USB speeds');
178 self.asUsbSpeed = asArgs[iArg].split(':');
179 for s in self.asUsbSpeed:
180 if s not in self.asUsbSpeedDef:
181 reporter.log('warning: The "--usb-speed" value "%s" is not a valid USB speed.' % (s));
182 elif asArgs[iArg] == '--usb-tests':
183 iArg += 1;
184 if iArg >= len(asArgs): raise base.InvalidOption('The "--usb-tests" takes a colon separated list of USB tests');
185 self.asUsbTests = asArgs[iArg].split(':');
186 for s in self.asUsbTests:
187 if s not in self.asUsbTestsDef:
188 reporter.log('warning: The "--usb-tests" value "%s" is not a valid USB test.' % (s));
189 elif asArgs[iArg] == '--usb-reattach-cycles':
190 iArg += 1;
191 if iArg >= len(asArgs): raise base.InvalidOption('The "--usb-reattach-cycles" takes cycle count');
192 try: self.cUsbReattachCycles = int(asArgs[iArg]);
193 except: raise base.InvalidOption('The "--usb-reattach-cycles" value "%s" is not an integer' \
194 % (asArgs[iArg],));
195 if self.cUsbReattachCycles <= 0:
196 raise base.InvalidOption('The "--usb-reattach-cycles" value "%s" is zero or negative.' \
197 % (self.cUsbReattachCycles,));
198 else:
199 return vbox.TestDriver.parseOption(self, asArgs, iArg);
200 return iArg + 1;
201
202 def completeOptions(self):
203 # Remove skipped VMs from the test list.
204 for sVM in self.asSkipVMs:
205 try: self.asTestVMs.remove(sVM);
206 except: pass;
207
208 return vbox.TestDriver.completeOptions(self);
209
210 def getResourceSet(self):
211 # Construct the resource list the first time it's queried.
212 if self.asRsrcs is None:
213 self.asRsrcs = [];
214
215 if 'tst-arch' in self.asTestVMs:
216 self.asRsrcs.append('4.2/usb/tst-arch.vdi');
217
218 return self.asRsrcs;
219
220 def actionConfig(self):
221
222 # Some stupid trickery to guess the location of the iso. ## fixme - testsuite unzip ++
223 sVBoxValidationKit_iso = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxValidationKit.iso'));
224 if not os.path.isfile(sVBoxValidationKit_iso):
225 sVBoxValidationKit_iso = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxTestSuite.iso'));
226 if not os.path.isfile(sVBoxValidationKit_iso):
227 sVBoxValidationKit_iso = '/mnt/ramdisk/vbox/svn/trunk/validationkit/VBoxValidationKit.iso';
228 if not os.path.isfile(sVBoxValidationKit_iso):
229 sVBoxValidationKit_iso = '/mnt/ramdisk/vbox/svn/trunk/testsuite/VBoxTestSuite.iso';
230 if not os.path.isfile(sVBoxValidationKit_iso):
231 sCur = os.getcwd();
232 for i in range(0, 10):
233 sVBoxValidationKit_iso = os.path.join(sCur, 'validationkit/VBoxValidationKit.iso');
234 if os.path.isfile(sVBoxValidationKit_iso):
235 break;
236 sVBoxValidationKit_iso = os.path.join(sCur, 'testsuite/VBoxTestSuite.iso');
237 if os.path.isfile(sVBoxValidationKit_iso):
238 break;
239 sCur = os.path.abspath(os.path.join(sCur, '..'));
240 if i is None: pass; # shut up pychecker/pylint.
241 if not os.path.isfile(sVBoxValidationKit_iso):
242 sVBoxValidationKit_iso = '/home/bird/validationkit/VBoxValidationKit.iso';
243 if not os.path.isfile(sVBoxValidationKit_iso):
244 sVBoxValidationKit_iso = '/home/bird/testsuite/VBoxTestSuite.iso';
245
246 # Make sure vboxapi has been imported so we can use the constants.
247 if not self.importVBoxApi():
248 return False;
249
250 #
251 # Configure the VMs we're going to use.
252 #
253
254 # Linux VMs
255 if 'tst-arch' in self.asTestVMs:
256 oVM = self.createTestVM('tst-arch', 1, '4.2/usb/tst-arch.vdi', sKind = 'ArchLinux_64', fIoApic = True, \
257 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
258 sDvdImage = sVBoxValidationKit_iso);
259 if oVM is None:
260 return False;
261
262 return True;
263
264 def actionExecute(self):
265 """
266 Execute the testcase.
267 """
268 fRc = self.testUsb();
269 return fRc;
270
271 def getGadgetParams(self, sHostname, sSpeed):
272 """
273 Returns the gadget hostname and type from the
274 given hostname the test is running on and device speed we want to test.
275 """
276 kdGadgetsConfigured = self.kdGadgetParams.get(sHostname);
277 if kdGadgetsConfigured is not None:
278 return kdGadgetsConfigured.get(sSpeed);
279
280 return (None, None);
281
282 #
283 # Test execution helpers.
284 #
285 def testUsbCompliance(self, oSession, oTxsSession, sUsbCtrl, sSpeed):
286 """
287 Test VirtualBoxs USB stack in a VM.
288 """
289 # Get configured USB test devices from hostname we are running on
290 sGadgetHost, _ = self.getGadgetParams(self.sHostname, sSpeed);
291
292 oUsbGadget = usbgadget2.UsbGadget();
293 reporter.log('Connecting to UTS: ' + sGadgetHost);
294 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost);
295 if fRc is True:
296 reporter.log('Connect succeeded');
297 self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost + (':%s' % oUsbGadget.getUsbIpPort()), [], []);
298
299 # Create device filter
300 fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0');
301 if fRc is True:
302 fRc = oUsbGadget.impersonate(usbgadget2.g_ksGadgetImpersonationTest);
303 if fRc is True:
304
305 # Wait a moment to let the USB device appear
306 self.sleep(10);
307
308 tupCmdLine = ('UsbTest', );
309 # Exclude a few tests which hang and cause a timeout, need investigation.
310 if sUsbCtrl is 'XHCI':
311 tupCmdLine = tupCmdLine + ('--exclude', '10', '--exclude', '24');
312
313 fRc = self.txsRunTest(oTxsSession, 'UsbTest', 3600 * 1000, \
314 '${CDROM}/${OS/ARCH}/UsbTest${EXESUFF}', tupCmdLine);
315 if not fRc:
316 reporter.testFailure('Running USB test utility failed');
317
318 else:
319 reporter.testFailure('Failed to impersonate test device');
320
321 oUsbGadget.disconnectFrom();
322 else:
323 reporter.testFailure('Failed to create USB device filter');
324
325 self.oVBox.host.removeUSBDeviceSource(sGadgetHost);
326 else:
327 reporter.testFailure('Failed to connect to USB gadget');
328
329 return fRc;
330
331 def testUsbReattach(self, oSession, oTxsSession, sUsbCtrl, sSpeed): # pylint: disable=W0613
332 """
333 Tests that rapid connect/disconnect cycles work.
334 """
335 # Get configured USB test devices from hostname we are running on
336 sGadgetHost, _ = self.getGadgetParams(self.sHostname, sSpeed);
337
338 oUsbGadget = usbgadget2.UsbGadget();
339 reporter.log('Connecting to UTS: ' + sGadgetHost);
340 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost);
341 if fRc is True:
342 reporter.log('Connect succeeded');
343 self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost + ':' + oUsbGadget.getUsbIpPort(), [], []);
344
345 # Create device filter
346 fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0');
347 if fRc is True:
348 fRc = oUsbGadget.impersonate(usbgadget2.g_ksGadgetImpersonationTest);
349 if fRc is True:
350
351 self.sleep(1);
352
353 # Do a rapid disconnect reconnect cycle. Wait a second before disconnecting
354 # again or it will happen so fast that the VM can't attach the new device.
355 # @todo: Get rid of the constant wait and use an event to get notified when
356 # the device was attached.
357 for iCycle in xrange (0, self.cUsbReattachCycles):
358 fRc = oUsbGadget.disconnectUsb();
359 fRc = fRc and oUsbGadget.connectUsb();
360 if not fRc:
361 reporter.testFailure('Reattach cycle %s failed on the gadget device' % (iCycle));
362 break;
363 self.sleep(1);
364
365 else:
366 reporter.testFailure('Failed to impersonate test device');
367
368 oUsbGadget.disconnectFrom();
369 else:
370 reporter.testFailure('Failed to connect to USB gadget');
371 else:
372 reporter.testFailure('Failed to create USB device filter');
373
374 return fRc;
375
376 def testUsbOneCfg(self, sVmName, sUsbCtrl, sSpeed, sUsbTest):
377 """
378 Runs the specified VM thru one specified test.
379
380 Returns a success indicator on the general test execution. This is not
381 the actual test result.
382 """
383 oVM = self.getVmByName(sVmName);
384
385 # Reconfigure the VM
386 fRc = True;
387 oSession = self.openSession(oVM);
388 if oSession is not None:
389 fRc = fRc and oSession.enableVirtEx(True);
390 fRc = fRc and oSession.enableNestedPaging(True);
391
392 # Make sure controllers are disabled initially.
393 fRc = fRc and oSession.enableUsbOhci(False);
394 fRc = fRc and oSession.enableUsbEhci(False);
395 fRc = fRc and oSession.enableUsbXhci(False);
396
397 if sUsbCtrl == 'OHCI':
398 fRc = fRc and oSession.enableUsbOhci(True);
399 elif sUsbCtrl == 'EHCI':
400 fRc = fRc and oSession.enableUsbEhci(True);
401 elif sUsbCtrl == 'XHCI':
402 fRc = fRc and oSession.enableUsbXhci(True);
403 fRc = fRc and oSession.saveSettings();
404 fRc = oSession.close() and fRc and True; # pychecker hack.
405 oSession = None;
406 else:
407 fRc = False;
408
409 # Start up.
410 if fRc is True:
411 self.logVmInfo(oVM);
412 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = False);
413 if oSession is not None:
414 self.addTask(oSession);
415
416 # Fudge factor - Allow the guest to finish starting up.
417 self.sleep(5);
418
419 if sUsbTest == 'Compliance':
420 fRc = self.testUsbCompliance(oSession, oTxsSession, sUsbCtrl, sSpeed);
421 elif sUsbTest == 'Reattach':
422 fRc = self.testUsbReattach(oSession, oTxsSession, sUsbCtrl, sSpeed);
423
424 # cleanup.
425 self.removeTask(oTxsSession);
426 self.terminateVmBySession(oSession)
427 else:
428 fRc = False;
429 return fRc;
430
431 def testUsbForOneVM(self, sVmName):
432 """
433 Runs one VM thru the various configurations.
434 """
435 reporter.testStart(sVmName);
436 for sUsbCtrl in self.asUsbCtrls:
437 reporter.testStart(sUsbCtrl)
438 for sUsbSpeed in self.asUsbSpeed:
439 asSupportedSpeeds = self.kdUsbSpeedMappings.get(sUsbCtrl);
440 if sUsbSpeed in asSupportedSpeeds:
441 reporter.testStart(sUsbSpeed)
442 for sUsbTest in self.asUsbTests:
443 reporter.testStart(sUsbTest)
444 fRc = self.testUsbOneCfg(sVmName, sUsbCtrl, sUsbSpeed, sUsbTest);
445 reporter.testDone();
446 reporter.testDone();
447 reporter.testDone();
448 reporter.testDone();
449 return fRc;
450
451 def testUsb(self):
452 """
453 Executes USB test.
454 """
455
456 reporter.log("Running on host: " + self.sHostname);
457
458 # Loop thru the test VMs.
459 for sVM in self.asTestVMs:
460 # run test on the VM.
461 fRc = self.testUsbForOneVM(sVM);
462
463 return fRc;
464
465
466
467if __name__ == '__main__':
468 sys.exit(tdUsbBenchmark().main(sys.argv));
469
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