VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/audio/tdAudioTest.py@ 91183

Last change on this file since 91183 was 91183, checked in by vboxsync, 3 years ago

Audio/Validation Kit: Only launch VKAT on the guest using "su" on OL 8.1. ​bugref:10008

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.5 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: tdAudioTest.py 91183 2021-09-09 15:53:45Z vboxsync $
3
4"""
5AudioTest test driver which invokes the VKAT (Validation Kit Audio Test)
6binary to perform the actual audio tests.
7
8The generated test set archive on the guest will be downloaded by TXS
9to the host for later audio comparison / verification.
10"""
11
12__copyright__ = \
13"""
14Copyright (C) 2021 Oracle Corporation
15
16This file is part of VirtualBox Open Source Edition (OSE), as
17available from http://www.virtualbox.org. This file is free software;
18you can redistribute it and/or modify it under the terms of the GNU
19General Public License (GPL) as published by the Free Software
20Foundation, in version 2 as it comes in the "COPYING" file of the
21VirtualBox OSE distribution. VirtualBox OSE is distributed in the
22hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
23
24The contents of this file may alternatively be used under the terms
25of the Common Development and Distribution License Version 1.0
26(CDDL) only, as it comes in the "COPYING.CDDL" file of the
27VirtualBox OSE distribution, in which case the provisions of the
28CDDL are applicable instead of those of the GPL.
29
30You may elect to license modified versions of this file under the
31terms and conditions of either the GPL or the CDDL or both.
32"""
33__version__ = "$Revision: 91183 $"
34
35# Standard Python imports.
36from datetime import datetime
37import os
38import sys
39import signal
40import subprocess
41
42# Only the main script needs to modify the path.
43try: __file__
44except: __file__ = sys.argv[0];
45g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
46sys.path.append(g_ksValidationKitDir);
47
48# Validation Kit imports.
49from testdriver import reporter
50from testdriver import base
51from testdriver import vbox
52from testdriver import vboxtestvms
53from common import utils;
54
55# pylint: disable=unnecessary-semicolon
56
57class tdAudioTest(vbox.TestDriver):
58 """
59 Runs various audio tests.
60 """
61 def __init__(self):
62 vbox.TestDriver.__init__(self);
63 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
64 self.asGstVkatPaths = [
65 # Debugging stuff (SCP'd over to the guest).
66 '/tmp/vkat',
67 '/tmp/VBoxAudioTest',
68 'C:\\Temp\\vkat',
69 'C:\\Temp\\VBoxAudioTest',
70 # Validation Kit .ISO.
71 '${CDROM}/vboxvalidationkit/${OS/ARCH}/vkat${EXESUFF}',
72 '${CDROM}/${OS/ARCH}/vkat${EXESUFF}',
73 # Test VMs.
74 '/opt/apps/vkat',
75 '/opt/apps/VBoxAudioTest',
76 '/apps/vkat',
77 '/apps/VBoxAudioTest',
78 'C:\\Apps\\vkat${EXESUFF}',
79 'C:\\Apps\\VBoxAudioTest${EXESUFF}',
80 ## @odo VBoxAudioTest on Guest Additions?
81 ];
82 self.asTestsDef = [
83 'guest_tone_playback', 'guest_tone_recording'
84 ];
85 self.asTests = self.asTestsDef;
86
87 # Optional arguments passing to VKAT when verifying audio test sets.
88 self.asVkatVerifyArgs = [];
89
90 # Enable audio debug mode.
91 #
92 # This is needed in order to load and use the Validation Kit audio driver,
93 # which in turn is being used in conjunction with the guest side to record
94 # output (guest is playing back) and injecting input (guest is recording).
95 self.asOptExtraData = [
96 'VBoxInternal2/Audio/Debug/Enabled:true',
97 ];
98
99 # Name of the running VM to use for running the test driver. Optional, and None if not being used.
100 self.sRunningVmName = None;
101
102 def showUsage(self):
103 """
104 Shows the audio test driver-specific command line options.
105 """
106 fRc = vbox.TestDriver.showUsage(self);
107 reporter.log('');
108 reporter.log('tdAudioTest Options:');
109 reporter.log(' --runningvmname <vmname>');
110 reporter.log(' --audio-tests <s1[:s2[:]]>');
111 reporter.log(' Default: %s (all)' % (':'.join(self.asTestsDef)));
112 reporter.log(' --audio-verify-max-diff-count <number>');
113 reporter.log(' Default: 0 (strict)');
114 reporter.log(' --audio-verify-max-diff-percent <0-100>');
115 reporter.log(' Default: 0 (strict)');
116 reporter.log(' --audio-verify-max-size-percent <0-100>');
117 reporter.log(' Default: 0 (strict)');
118 return fRc;
119
120 def parseOption(self, asArgs, iArg):
121 """
122 Parses the audio test driver-specific command line options.
123 """
124 if asArgs[iArg] == '--runningvmname':
125 iArg += 1;
126 if iArg >= len(asArgs):
127 raise base.InvalidOption('The "--runningvmname" needs VM name');
128
129 self.sRunningVmName = asArgs[iArg];
130 elif asArgs[iArg] == '--audio-tests':
131 iArg += 1;
132 if asArgs[iArg] == 'all': # Nice for debugging scripts.
133 self.asTests = self.asTestsDef;
134 else:
135 self.asTests = asArgs[iArg].split(':');
136 for s in self.asTests:
137 if s not in self.asTestsDef:
138 raise base.InvalidOption('The "--audio-tests" value "%s" is not valid; valid values are: %s'
139 % (s, ' '.join(self.asTestsDef)));
140 elif asArgs[iArg] == '--audio-verify-max-diff-count' \
141 or asArgs[iArg] == '--audio-verify-max-diff-percent' \
142 or asArgs[iArg] == '--audio-verify-max-size-percent':
143 # Strip the "--audio-verify-" prefix and keep the options as defined in VKAT,
144 # e.g. "--audio-verify-max-diff-count" -> "--max-diff-count". That way we don't
145 # need to do any special argument translation and whatnot.
146 self.asVkatVerifyArgs.extend(['--' + asArgs[iArg][len('--audio-verify-'):]]);
147 iArg += 1;
148 if iArg >= len(asArgs):
149 raise base.InvalidOption('Option "%s" needs a value' % (asArgs[iArg - 1]));
150 self.asVkatVerifyArgs.extend([asArgs[iArg]]);
151 else:
152 return vbox.TestDriver.parseOption(self, asArgs, iArg);
153 return iArg + 1;
154
155 def actionVerify(self):
156 """
157 Verifies the test driver before running.
158 """
159 if self.sVBoxValidationKitIso is None or not os.path.isfile(self.sVBoxValidationKitIso):
160 reporter.error('Cannot find the VBoxValidationKit.iso! (%s)'
161 'Please unzip a Validation Kit build in the current directory or in some parent one.'
162 % (self.sVBoxValidationKitIso,) );
163 return False;
164 return vbox.TestDriver.actionVerify(self);
165
166 def actionConfig(self):
167 """
168 Configures the test driver before running.
169 """
170 if not self.importVBoxApi(): # So we can use the constant below.
171 return False;
172
173 # Make sure that the Validation Kit .ISO is mounted
174 # to find the VKAT (Validation Kit Audio Test) binary on it.
175 assert self.sVBoxValidationKitIso is not None;
176 return self.oTestVmSet.actionConfig(self, sDvdImage = self.sVBoxValidationKitIso);
177
178 def actionExecute(self):
179 """
180 Executes the test driver.
181 """
182 if self.sRunningVmName is None:
183 return self.oTestVmSet.actionExecute(self, self.testOneVmConfig);
184 return self.actionExecuteOnRunnigVM();
185
186 def actionExecuteOnRunnigVM(self):
187 """
188 Executes the tests in an already configured + running VM.
189 """
190 if not self.importVBoxApi():
191 return False;
192
193 fRc = True;
194
195 oVirtualBox = self.oVBoxMgr.getVirtualBox();
196 try:
197 oVM = oVirtualBox.findMachine(self.sRunningVmName);
198 if oVM.state != self.oVBoxMgr.constants.MachineState_Running:
199 reporter.error("Machine '%s' is not in Running state" % (self.sRunningVmName));
200 fRc = False;
201 except:
202 reporter.errorXcpt("Machine '%s' not found" % (self.sRunningVmName));
203 fRc = False;
204
205 if fRc:
206 oSession = self.openSession(oVM);
207 if oSession:
208 # Tweak this to your likings.
209 oTestVm = vboxtestvms.TestVm('runningvm', sKind = 'WindowsXP'); #sKind = 'WindowsXP' # sKind = 'Ubuntu_64'
210 (fRc, oTxsSession) = self.txsDoConnectViaTcp(oSession, 30 * 1000);
211 if fRc:
212 self.doTest(oTestVm, oSession, oTxsSession);
213 else:
214 reporter.error("Unable to open session for machine '%s'" % (self.sRunningVmName));
215 fRc = False;
216
217 del oVM;
218 del oVirtualBox;
219 return fRc;
220
221 def getGstVkatLogFilePath(self, oTestVm):
222 """
223 Returns the log file path of VKAT running on the guest (daemonized).
224 """
225 return oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'vkat-guest.log');
226
227 def locateGstBinary(self, oSession, oTxsSession, asPaths):
228 """
229 Locates a guest binary on the guest by checking the paths in \a asPaths.
230 """
231 for sCurPath in asPaths:
232 reporter.log2('Checking for \"%s\" ...' % (sCurPath));
233 if self.txsIsFile(oSession, oTxsSession, sCurPath, fIgnoreErrors = True):
234 return (True, sCurPath);
235 reporter.error('Unable to find guest binary in any of these places:\n%s' % ('\n'.join(asPaths),));
236 return (False, "");
237
238 def executeHstLoop(self, sWhat, asArgs, asEnv = None, fAsAdmin = False):
239 """
240 Inner loop which handles the execution of a host binary.
241 """
242 fRc = False;
243
244 asEnvTmp = os.environ.copy();
245 if asEnv:
246 for sEnv in asEnv:
247 sKey, sValue = sEnv.split('=');
248 reporter.log2('Setting env var \"%s\" -> \"%s\"' % (sKey, sValue));
249 os.environ[sKey] = sValue; # Also apply it to the current environment.
250 asEnvTmp[sKey] = sValue;
251
252 if fAsAdmin \
253 and utils.getHostOs() != 'win':
254 oProcess = utils.sudoProcessPopen(asArgs,
255 env = asEnvTmp,
256 stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = False,
257 close_fds = False);
258 else:
259 oProcess = utils.processPopenSafe(asArgs,
260 env = asEnvTmp,
261 stdout = subprocess.PIPE, stderr = subprocess.PIPE);
262 if oProcess:
263 for line in iter(oProcess.stdout.readline, b''):
264 reporter.log('[' + sWhat + '] ' + line.decode('utf-8'));
265 oProcess.communicate();
266 if oProcess.returncode == 0:
267 fRc = True;
268 else:
269 reporter.log2('Executing \"%s\" on host returned exit code error %d' % (sWhat, oProcess.returncode));
270
271 return fRc;
272
273 def executeHst(self, sWhat, asArgs, asEnv = None, fAsync = False, fAsAdmin = False):
274 """
275 Runs a binary (image) with optional admin (root) rights on the host and
276 waits until it terminates.
277
278 Windows currently is not supported yet running stuff as Administrator.
279
280 Returns success status (exit code is 0).
281 """
282 reporter.log('Executing \"%s\" on host (as admin = %s, async = %s)' % (sWhat, fAsAdmin, fAsync));
283
284 reporter.testStart(sWhat);
285
286 fRc = self.executeHstLoop(sWhat, asArgs, asEnv);
287 if fRc:
288 reporter.log('Executing \"%s\" on host done' % (sWhat,));
289 else:
290 reporter.log('Executing \"%s\" on host failed' % (sWhat,));
291
292 reporter.testDone();
293
294 return fRc;
295
296 def killHstProcessByName(self, sProcName):
297 """
298 Kills processes by their name.
299 """
300 reporter.log('Trying to kill processes named "%s"' % (sProcName,));
301 if sys.platform == 'win32':
302 sArgProcName = '\"%s.exe\"' % sProcName;
303 asArgs = [ 'taskkill', '/IM', sArgProcName, '/F' ];
304 self.executeHst('Killing process', asArgs);
305 else: # Note: killall is not available on older Debians (requires psmisc).
306 # Using the BSD syntax here; MacOS also should understand this.
307 procPs = subprocess.Popen(['ps', 'ax'], stdout=subprocess.PIPE);
308 out, err = procPs.communicate();
309 if err:
310 reporter.log('PS stderr:');
311 for sLine in err.decode('utf-8').splitlines():
312 reporter.log(sLine);
313 if out:
314 reporter.log4('PS stdout:');
315 for sLine in out.decode('utf-8').splitlines():
316 reporter.log4(sLine);
317 if sProcName in sLine:
318 pid = int(sLine.split(None, 1)[0]);
319 reporter.log('Killing PID %d' % (pid,));
320 os.kill(pid, signal.SIGKILL); # pylint: disable=no-member
321
322 def killHstVkat(self):
323 """
324 Kills VKAT (VBoxAudioTest) on the host side.
325 """
326 reporter.log('Killing stale/old VKAT processes ...');
327 self.killHstProcessByName("vkat");
328 self.killHstProcessByName("VBoxAudioTest");
329
330 def getWinFirewallArgsDisable(self, sOsType):
331 """
332 Returns the command line arguments for Windows OSes
333 to disable the built-in firewall (if any).
334
335 If not supported, returns an empty array.
336 """
337 if sOsType == 'vista': # pylint: disable=no-else-return
338 # Vista and up.
339 return (['netsh.exe', 'advfirewall', 'set', 'allprofiles', 'state', 'off']);
340 elif sOsType == 'xp': # Older stuff (XP / 2003).
341 return(['netsh.exe', 'firewall', 'set', 'opmode', 'mode=DISABLE']);
342 # Not supported / available.
343 return [];
344
345 def disableGstFirewall(self, oTestVm, oTxsSession):
346 """
347 Disables the firewall on a guest (if any).
348
349 Needs elevated / admin / root privileges.
350
351 Returns success status, not logged.
352 """
353 fRc = False;
354
355 asArgs = [];
356 sOsType = '';
357 if oTestVm.isWindows():
358 if oTestVm.sKind in ['WindowsNT4', 'WindowsNT3x']:
359 sOsType = 'nt3x'; # Not supported, but define it anyway.
360 elif oTestVm.sKind in ('Windows2000', 'WindowsXP', 'Windows2003'):
361 sOsType = 'xp';
362 else:
363 sOsType = 'vista';
364 asArgs = self.getWinFirewallArgsDisable(sOsType);
365 else:
366 sOsType = 'unsupported';
367
368 reporter.log('Disabling firewall on guest (type: %s) ...' % (sOsType,));
369
370 if asArgs:
371 fRc = self.txsRunTest(oTxsSession, 'Disabling guest firewall', 3 * 60 * 1000, \
372 oTestVm.pathJoin(self.getGuestSystemDir(oTestVm), asArgs[0]), asArgs);
373 if not fRc:
374 reporter.error('Disabling firewall on guest returned exit code error %d' % (self.getLastRcFromTxs(oTxsSession)));
375 else:
376 reporter.log('Firewall not available on guest, skipping');
377 fRc = True; # Not available, just skip.
378
379 return fRc;
380
381 def disableHstFirewall(self):
382 """
383 Disables the firewall on the host (if any).
384
385 Needs elevated / admin / root privileges.
386
387 Returns success status, not logged.
388 """
389 fRc = False;
390
391 asArgs = [];
392 sOsType = sys.platform;
393
394 if sOsType == 'win32':
395 reporter.log('Disabling firewall on host (type: %s) ...' % (sOsType));
396
397 ## @todo For now we ASSUME that we don't run (and don't support even) on old(er)
398 # Windows hosts than Vista.
399 asArgs = self.getWinFirewallArgsDisable('vista');
400 if asArgs:
401 fRc = self.executeHst('Disabling host firewall', asArgs, fAsAdmin = True);
402 else:
403 reporter.log('Firewall not available on host, skipping');
404 fRc = True; # Not available, just skip.
405
406 return fRc;
407
408 def getLastRcFromTxs(self, oTxsSession):
409 """
410 Extracts the last exit code reported by TXS from a run before.
411 Assumes that nothing else has been run on the same TXS session in the meantime.
412 """
413 iRc = 0;
414 (_, sOpcode, abPayload) = oTxsSession.getLastReply();
415 if sOpcode.startswith('PROC NOK '): # Extract process rc
416 iRc = abPayload[0]; # ASSUMES 8-bit rc for now.
417 return iRc;
418
419 def startVkatOnGuest(self, oTestVm, oSession, oTxsSession, sTag):
420 """
421 Starts VKAT on the guest (running in background).
422 """
423 sPathTemp = self.getGuestTempDir(oTestVm);
424 sPathAudioOut = oTestVm.pathJoin(sPathTemp, 'vkat-guest-out');
425 sPathAudioTemp = oTestVm.pathJoin(sPathTemp, 'vkat-guest-temp');
426
427 reporter.log('Guest audio test temp path is \"%s\"' % (sPathAudioOut));
428 reporter.log('Guest audio test output path is \"%s\"' % (sPathAudioTemp));
429 reporter.log('Guest audio test tag is \"%s\"' % (sTag));
430
431 fRc, sVkatExe = self.locateGstBinary(oSession, oTxsSession, self.asGstVkatPaths);
432 if fRc:
433 reporter.log('Using VKAT on guest at \"%s\"' % (sVkatExe));
434
435 sCmd = '';
436 asArgs = [];
437
438 asArgsVkat = [ sVkatExe, 'test', '--mode', 'guest', '--probe-backends', \
439 '--tempdir', sPathAudioTemp, '--outdir', sPathAudioOut, \
440 '--tag', sTag ];
441
442 asArgs.extend(asArgsVkat);
443
444 for _ in range(1, reporter.getVerbosity()): # Verbosity always is initialized at 1.
445 asArgs.extend([ '-v' ]);
446
447 # Needed for NATed VMs.
448 asArgs.extend(['--tcp-connect-addr', '10.0.2.2' ]);
449
450 if oTestVm.sKind in 'Oracle_64':
451 #
452 # Some Linux distros have a bug / are configured (?) so that processes started by init system
453 # cannot access the PulseAudio server ("Connection refused"), for example OL 8.1.
454 #
455 # To work around this, we use the (hopefully) configured user "vbox" and run it under its behalf,
456 # as the Test Execution Service (TxS) currently does not implement impersonation yet.
457 #
458 asSU = [ '/bin/su',
459 '/usr/bin/su',
460 '/usr/local/bin/su' ];
461 fRc, sCmd = self.locateGstBinary(oSession, oTxsSession, asSU);
462 if fRc:
463 sCmdArgs = '';
464 for sArg in asArgs:
465 sCmdArgs += sArg + " ";
466 asArgs = [ sCmd, oTestVm.getTestUser(), '-c', sCmdArgs ];
467 else:
468 reporter.log('Unable to find SU on guest, falling back to regular starting ...')
469
470 if not sCmd: # Just start it with the same privileges as TxS.
471 sCmd = sVkatExe;
472
473 reporter.log2('startVkatOnGuest: sCmd=%s' % (sCmd,));
474 reporter.log2('startVkatOnGuest: asArgs=%s' % (asArgs,));
475
476 #
477 # Add own environment stuff.
478 #
479 asEnv = [];
480
481 # Write the log file to some deterministic place so TxS can retrieve it later.
482 sVkatLogFile = 'VKAT_RELEASE_LOG_DEST=file=' + self.getGstVkatLogFilePath(oTestVm);
483 asEnv.extend([ sVkatLogFile ]);
484
485 #
486 # Execute asynchronously on the guest.
487 #
488 fRc = oTxsSession.asyncExec(sCmd, asArgs, asEnv, cMsTimeout = 15 * 60 * 1000, sPrefix = '[VKAT Guest] ');
489 if fRc:
490 self.addTask(oTxsSession);
491
492 if not fRc:
493 reporter.error('VKAT on guest returned exit code error %d' % (self.getLastRcFromTxs(oTxsSession)));
494 else:
495 reporter.error('VKAT on guest not found');
496
497 return fRc;
498
499 def runTests(self, oTestVm, oSession, oTxsSession, sDesc, sTag, asTests):
500 """
501 Runs one or more tests using VKAT on the host, which in turn will
502 communicate with VKAT running on the guest and the Validation Kit
503 audio driver ATS (Audio Testing Service).
504 """
505 _ = oTestVm, oSession, oTxsSession;
506
507 sPathTemp = self.sScratchPath;
508 sPathAudioOut = os.path.join(sPathTemp, 'vkat-host-out-%s' % (sTag));
509 sPathAudioTemp = os.path.join(sPathTemp, 'vkat-host-temp-%s' % (sTag));
510
511 reporter.log('Host audio test temp path is \"%s\"' % (sPathAudioOut));
512 reporter.log('Host audio test output path is \"%s\"' % (sPathAudioTemp));
513 reporter.log('Host audio test tag is \"%s\"' % (sTag));
514
515 reporter.testStart(sDesc);
516
517 sVkatExe = self.getBinTool('vkat');
518
519 reporter.log('Using VKAT on host at: \"%s\"' % (sVkatExe));
520
521 # Build the base command line, exclude all tests by default.
522 asArgs = [ sVkatExe, 'test', '--mode', 'host', '--probe-backends', \
523 '--tempdir', sPathAudioTemp, '--outdir', sPathAudioOut, '-a', \
524 '--tag', sTag, \
525 '--no-verify' ]; # We do the verification separately in the step below.
526
527 for _ in range(1, reporter.getVerbosity()): # Verbosity always is initialized at 1.
528 asArgs.extend([ '-v' ]);
529
530 # ... and extend it with wanted tests.
531 asArgs.extend(asTests);
532
533 #
534 # Let VKAT on the host run synchronously.
535 #
536 fRc = self.executeHst("VKAT Host", asArgs);
537
538 reporter.testDone();
539
540 if fRc:
541 #
542 # When running the test(s) above were successful, do the verification step next.
543 # This gives us a bit more fine-grained test results in the test manager.
544 #
545 reporter.testStart('Verifying audio data');
546
547 sNameSetHst = '%s-host.tar.gz' % (sTag);
548 sPathSetHst = os.path.join(sPathAudioOut, sNameSetHst);
549 sNameSetGst = '%s-guest.tar.gz' % (sTag);
550 sPathSetGst = os.path.join(sPathAudioOut, sNameSetGst);
551
552 asArgs = [ sVkatExe, 'verify', sPathSetHst, sPathSetGst ];
553
554 for _ in range(1, reporter.getVerbosity()): # Verbosity always is initialized at 1.
555 asArgs.extend([ '-v' ]);
556
557 if self.asVkatVerifyArgs:
558 asArgs += self.asVkatVerifyArgs;
559
560 fRc = self.executeHst("VKAT Host Verify", asArgs);
561 if fRc:
562 reporter.log("Verification audio data successful");
563 else:
564 #
565 # Add the test sets to the test manager for later (manual) diagnosis.
566 #
567 reporter.addLogFile(sPathSetGst, 'misc/other', 'Guest audio test set');
568 reporter.addLogFile(sPathSetHst, 'misc/other', 'Host audio test set');
569
570 reporter.error("Verification of audio data failed");
571
572 reporter.testDone();
573
574 return fRc;
575
576 def doTest(self, oTestVm, oSession, oTxsSession):
577 """
578 Executes the specified audio tests.
579 """
580
581 # Disable any OS-specific firewalls preventing VKAT / ATS to run.
582 fRc = self.disableHstFirewall();
583 fRc = self.disableGstFirewall(oTestVm, oTxsSession) and fRc;
584
585 if not fRc:
586 return False;
587
588 # First try to kill any old VKAT / VBoxAudioTest processes lurking around on the host.
589 # Might happen because of former (aborted) runs.
590 self.killHstVkat();
591
592 reporter.log("Active tests: %s" % (self.asTests,));
593
594 # Define a tag for the whole run.
595 sTag = oTestVm.sVmName + "_" + datetime.now().strftime("%Y%m%d_%H%M%S");
596
597 fRc = self.startVkatOnGuest(oTestVm, oSession, oTxsSession, sTag);
598 if fRc:
599 #
600 # Execute the tests using VKAT on the guest side (in guest mode).
601 #
602 if "guest_tone_playback" in self.asTests:
603 fRc = self.runTests(oTestVm, oSession, oTxsSession, \
604 'Guest audio playback', sTag + "_test_playback", \
605 asTests = [ '-i0' ]);
606 if "guest_tone_recording" in self.asTests:
607 fRc = fRc and self.runTests(oTestVm, oSession, oTxsSession, \
608 'Guest audio recording', sTag + "_test_recording", \
609 asTests = [ '-i1' ]);
610
611 # Cancel guest VKAT execution task summoned by startVkatOnGuest().
612 oTxsSession.cancelTask();
613
614 #
615 # Retrieve log files for diagnosis.
616 #
617 self.txsDownloadFiles(oSession, oTxsSession,
618 [ ( self.getGstVkatLogFilePath(oTestVm),
619 'vkat-guest-%s.log' % (oTestVm.sVmName,),),
620 ],
621 fIgnoreErrors = True);
622 return fRc;
623
624 def testOneVmConfig(self, oVM, oTestVm):
625 """
626 Runs tests using one specific VM config.
627 """
628
629 self.logVmInfo(oVM);
630
631 reporter.testStart("Audio Testing");
632
633 fSkip = False;
634
635 if oTestVm.isWindows() \
636 and oTestVm.sKind in ('WindowsNT4', 'Windows2000'): # Too old for DirectSound and WASAPI backends.
637 reporter.log('Audio testing skipped, not implemented/available for that OS yet.');
638 fSkip = True;
639
640 if not fSkip \
641 and self.fpApiVer < 7.0:
642 reporter.log('Audio testing for non-trunk builds skipped.');
643 fSkip = True;
644
645 sVkatExe = self.getBinTool('vkat');
646 asArgs = [ sVkatExe, 'enum', '--probe-backends' ];
647 fRc = self.executeHst("VKAT Host Audio Probing", asArgs);
648 if not fSkip \
649 and not fRc:
650 reporter.log('Audio not available on host, skipping audio tests.');
651 fSkip = True;
652
653 if fSkip:
654 reporter.testDone(fSkipped = True);
655 return True;
656
657 # Reconfigure the VM.
658 oSession = self.openSession(oVM);
659 if oSession is not None:
660 # Set extra data.
661 for sExtraData in self.asOptExtraData:
662 sKey, sValue = sExtraData.split(':');
663 reporter.log('Set extradata: %s => %s' % (sKey, sValue));
664 fRc = oSession.setExtraData(sKey, sValue) and fRc;
665
666 # Make sure that the VM's audio adapter is configured the way we need it to.
667 if self.fpApiVer >= 4.0:
668 oOsType = oSession.getOsType();
669 ## @ŧdoo Make this configurable via driver opts (to use as a variant)?
670 oSession.setupAudio(oOsType.recommendedAudioController,
671 fEnable = True, fEnableIn = True, fEnableOut = True);
672
673 # Save the settings.
674 fRc = fRc and oSession.saveSettings();
675 fRc = oSession.close() and fRc;
676
677 reporter.testStart('Waiting for TXS');
678 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName,
679 fCdWait = True,
680 cMsTimeout = 3 * 60 * 1000,
681 sFileCdWait = '${OS/ARCH}/vkat${EXESUFF}');
682 reporter.testDone();
683
684 if oSession is not None:
685 self.addTask(oTxsSession);
686
687 fRc = self.doTest(oTestVm, oSession, oTxsSession);
688
689 # Cleanup.
690 self.removeTask(oTxsSession);
691 self.terminateVmBySession(oSession);
692
693 reporter.testDone();
694 return fRc;
695
696 def onExit(self, iRc):
697 """
698 Exit handler for this test driver.
699 """
700 return vbox.TestDriver.onExit(self, iRc);
701
702if __name__ == '__main__':
703 sys.exit(tdAudioTest().main(sys.argv))
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