VirtualBox

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

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

ValidationKit/usb: Add a new testcase where the USB device is repeatedly connected and disconnected

  • 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 58937 2015-12-01 13:04:30Z vboxsync $
4
5"""
6VirtualBox Validation Kit - USB testcase and benchmark.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2014-2015 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: 58937 $"
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 # The following is for local testing and not for the test lab.
67 'adaris': {
68 'Low': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
69 'Full': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
70 'High': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
71 'Super': ('odroidxu3', usbgadget.g_ksGadgetTypeODroidXu3)
72 },
73 'archusb': {
74 'Low': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
75 'Full': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
76 'High': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone),
77 'Super': ('odroidxu3', usbgadget.g_ksGadgetTypeODroidXu3)
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('tdStorageBenchmark1 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' % (asArgs[iArg],));
194 if self.cUsbReattachCycles <= 0:
195 raise base.InvalidOption('The "--usb-reattach-cycles" value "%s" is zero or negative.' % (self.cUsbReattachCycles,));
196 else:
197 return vbox.TestDriver.parseOption(self, asArgs, iArg);
198 return iArg + 1;
199
200 def completeOptions(self):
201 # Remove skipped VMs from the test list.
202 for sVM in self.asSkipVMs:
203 try: self.asTestVMs.remove(sVM);
204 except: pass;
205
206 return vbox.TestDriver.completeOptions(self);
207
208 def getResourceSet(self):
209 # Construct the resource list the first time it's queried.
210 if self.asRsrcs is None:
211 self.asRsrcs = [];
212
213 if 'tst-arch' in self.asTestVMs:
214 self.asRsrcs.append('4.2/usb/tst-arch.vdi');
215
216 return self.asRsrcs;
217
218 def actionConfig(self):
219
220 # Some stupid trickery to guess the location of the iso. ## fixme - testsuite unzip ++
221 sVBoxValidationKit_iso = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxValidationKit.iso'));
222 if not os.path.isfile(sVBoxValidationKit_iso):
223 sVBoxValidationKit_iso = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxTestSuite.iso'));
224 if not os.path.isfile(sVBoxValidationKit_iso):
225 sVBoxValidationKit_iso = '/mnt/ramdisk/vbox/svn/trunk/validationkit/VBoxValidationKit.iso';
226 if not os.path.isfile(sVBoxValidationKit_iso):
227 sVBoxValidationKit_iso = '/mnt/ramdisk/vbox/svn/trunk/testsuite/VBoxTestSuite.iso';
228 if not os.path.isfile(sVBoxValidationKit_iso):
229 sCur = os.getcwd();
230 for i in range(0, 10):
231 sVBoxValidationKit_iso = os.path.join(sCur, 'validationkit/VBoxValidationKit.iso');
232 if os.path.isfile(sVBoxValidationKit_iso):
233 break;
234 sVBoxValidationKit_iso = os.path.join(sCur, 'testsuite/VBoxTestSuite.iso');
235 if os.path.isfile(sVBoxValidationKit_iso):
236 break;
237 sCur = os.path.abspath(os.path.join(sCur, '..'));
238 if i is None: pass; # shut up pychecker/pylint.
239 if not os.path.isfile(sVBoxValidationKit_iso):
240 sVBoxValidationKit_iso = '/home/bird/validationkit/VBoxValidationKit.iso';
241 if not os.path.isfile(sVBoxValidationKit_iso):
242 sVBoxValidationKit_iso = '/home/bird/testsuite/VBoxTestSuite.iso';
243
244 # Make sure vboxapi has been imported so we can use the constants.
245 if not self.importVBoxApi():
246 return False;
247
248 #
249 # Configure the VMs we're going to use.
250 #
251
252 # Linux VMs
253 if 'tst-arch' in self.asTestVMs:
254 oVM = self.createTestVM('tst-arch', 1, '4.2/usb/tst-arch.vdi', sKind = 'ArchLinux_64', fIoApic = True, \
255 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT, \
256 sDvdImage = sVBoxValidationKit_iso);
257 if oVM is None:
258 return False;
259
260 return True;
261
262 def actionExecute(self):
263 """
264 Execute the testcase.
265 """
266 fRc = self.testUsb();
267 return fRc;
268
269 def getGadgetParams(self, sHostname, sSpeed):
270 """
271 Returns the gadget hostname and type from the
272 given hostname the test is running on and device speed we want to test.
273 """
274 kdGadgetsConfigured = self.kdGadgetParams.get(sHostname);
275 if kdGadgetsConfigured is not None:
276 return kdGadgetsConfigured.get(sSpeed);
277
278 return (None, None);
279
280 #
281 # Test execution helpers.
282 #
283 def testUsbCompliance(self, oSession, oTxsSession, sUsbCtrl, sSpeed):
284 """
285 Test VirtualBoxs USB stack in a VM.
286 """
287 # Get configured USB test devices from hostname we are running on
288 sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed);
289
290 # Create device filter
291 fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0');
292 if fRc is True:
293 oUsbGadget = usbgadget.UsbGadget();
294 reporter.log('Connecting to gadget: ' + sGadgetType);
295 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, sGadgetHost);
296 if fRc is True:
297 reporter.log('Connect succeeded');
298 fRc = oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest);
299 if fRc is True:
300
301 # Wait a moment to let the USB device appear
302 self.sleep(3);
303
304 tupCmdLine = ('UsbTest', );
305 # Exclude a few tests which hang and cause a timeout, need investigation.
306 if sUsbCtrl is 'XHCI':
307 tupCmdLine = tupCmdLine + ('--exclude', '10', '--exclude', '24');
308
309 fRc = self.txsRunTest(oTxsSession, 'UsbTest', 3600 * 1000, \
310 '${CDROM}/${OS/ARCH}/UsbTest${EXESUFF}', tupCmdLine);
311 if not fRc:
312 reporter.testFailure('Running USB test utility failed');
313
314 else:
315 reporter.testFailure('Failed to impersonate test device');
316
317 oUsbGadget.disconnectFrom();
318 else:
319 reporter.testFailure('Failed to connect to USB gadget');
320 else:
321 reporter.testFailure('Failed to create USB device filter');
322
323 return fRc;
324
325 def testUsbReattach(self, oSession, oTxsSession, sUsbCtrl, sSpeed):
326 """
327 Tests that rapid connect/disconnect cycles work.
328 """
329 # Get configured USB test devices from hostname we are running on
330 sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed);
331
332 # Create device filter
333 fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0');
334 if fRc is True:
335 oUsbGadget = usbgadget.UsbGadget();
336 reporter.log('Connecting to gadget: ' + sGadgetType);
337 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, sGadgetHost);
338 if fRc is True:
339 reporter.log('Connect succeeded');
340 fRc = oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest);
341 if fRc is True:
342
343 self.sleep(1);
344
345 # Do a rapid disconnect reconnect cycle. Wait a second before disconnecting
346 # again or it will happen so fast that the VM can't attach the new device.
347 # @todo: Get rid of the constant wait and use an event to get notified when
348 # the device was attached.
349 for iCycle in xrange (0, self.cUsbReattachCycles):
350 fRc = oUsbGadget.disconnectUsb();
351 fRc = fRc and oUsbGadget.connectUsb();
352 if not fRc:
353 reporter.testFailure('Reattach cycle %s failed on the gadget device' % (iCycle));
354 break;
355 self.sleep(1);
356
357 else:
358 reporter.testFailure('Failed to impersonate test device');
359
360 oUsbGadget.disconnectFrom();
361 else:
362 reporter.testFailure('Failed to connect to USB gadget');
363 else:
364 reporter.testFailure('Failed to create USB device filter');
365
366 return fRc;
367
368 def testUsbOneCfg(self, sVmName, sUsbCtrl, sSpeed, sUsbTest):
369 """
370 Runs the specified VM thru one specified test.
371
372 Returns a success indicator on the general test execution. This is not
373 the actual test result.
374 """
375 oVM = self.getVmByName(sVmName);
376
377 # Reconfigure the VM
378 fRc = True;
379 oSession = self.openSession(oVM);
380 if oSession is not None:
381 fRc = fRc and oSession.enableVirtEx(True);
382 fRc = fRc and oSession.enableNestedPaging(True);
383
384 # Make sure controllers are disabled initially.
385 fRc = fRc and oSession.enableUsbOhci(False);
386 fRc = fRc and oSession.enableUsbEhci(False);
387 fRc = fRc and oSession.enableUsbXhci(False);
388
389 if sUsbCtrl == 'OHCI':
390 fRc = fRc and oSession.enableUsbOhci(True);
391 elif sUsbCtrl == 'EHCI':
392 fRc = fRc and oSession.enableUsbEhci(True);
393 elif sUsbCtrl == 'XHCI':
394 fRc = fRc and oSession.enableUsbXhci(True);
395 fRc = fRc and oSession.saveSettings();
396 fRc = oSession.close() and fRc and True; # pychecker hack.
397 oSession = None;
398 else:
399 fRc = False;
400
401 # Start up.
402 if fRc is True:
403 self.logVmInfo(oVM);
404 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(sVmName, fCdWait = False, fNatForwardingForTxs = False);
405 if oSession is not None:
406 self.addTask(oSession);
407
408 # Fudge factor - Allow the guest to finish starting up.
409 self.sleep(5);
410
411 if sUsbTest == 'Compliance':
412 fRc = self.testUsbCompliance(oSession, oTxsSession, sUsbCtrl, sSpeed);
413 elif sUsbTest == 'Reattach':
414 fRc = self.testUsbReattach(oSession, oTxsSession, sUsbCtrl, sSpeed);
415
416 # cleanup.
417 self.removeTask(oTxsSession);
418 self.terminateVmBySession(oSession)
419 else:
420 fRc = False;
421 return fRc;
422
423 def testUsbForOneVM(self, sVmName):
424 """
425 Runs one VM thru the various configurations.
426 """
427 reporter.testStart(sVmName);
428 for sUsbCtrl in self.asUsbCtrls:
429 reporter.testStart(sUsbCtrl)
430 for sUsbSpeed in self.asUsbSpeed:
431 asSupportedSpeeds = self.kdUsbSpeedMappings.get(sUsbCtrl);
432 if sUsbSpeed in asSupportedSpeeds:
433 reporter.testStart(sUsbSpeed)
434 for sUsbTest in self.asUsbTests:
435 reporter.testStart(sUsbTest)
436 fRc = self.testUsbOneCfg(sVmName, sUsbCtrl, sUsbSpeed, sUsbTest);
437 reporter.testDone();
438 reporter.testDone();
439 reporter.testDone();
440 reporter.testDone();
441 return fRc;
442
443 def testUsb(self):
444 """
445 Executes USB test.
446 """
447
448 reporter.log("Running on host: " + self.sHostname);
449
450 # Loop thru the test VMs.
451 for sVM in self.asTestVMs:
452 # run test on the VM.
453 fRc = self.testUsbForOneVM(sVM);
454
455 return fRc;
456
457
458
459if __name__ == '__main__':
460 sys.exit(tdUsbBenchmark().main(sys.argv));
461
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