VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/audio/tdGuestHostTimings.py@ 94125

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

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: tdGuestHostTimings.py 93115 2022-01-01 11:31:46Z vboxsync $
3
4"""
5????????
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2022 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 93115 $"
30
31
32import os
33import sys
34import time
35import subprocess
36import re
37import time
38
39# Only the main script needs to modify the path.
40try: __file__
41except: __file__ = sys.argv[0];
42g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
43sys.path.append(g_ksValidationKitDir);
44
45# Validation Kit imports.
46from testdriver import reporter
47from testdriver import base
48from testdriver import vbox
49from testdriver import vboxcon
50from testdriver import vboxtestvms
51
52class tdGuestHostTimings(vbox.TestDriver): # pylint: disable=too-many-instance-attributes
53
54 def __init__(self):
55 vbox.TestDriver.__init__(self);
56 self.sSessionTypeDef = 'gui';
57
58 self.oTestVmSet = self.oTestVmManager.getStandardVmSet('nat') ## ???
59
60 # Use the command line "--test-vms mw7x64 execute" to run the only "mw7x64" VM
61 oTestVm = vboxtestvms.TestVm('mw7x64', oSet = self.oTestVmSet, sHd = 'mw7x64.vdi',
62 sKind = 'Windows7', acCpusSup = range(1, 2), fIoApic = True, sFirmwareType = 'bios',
63 asParavirtModesSup = ['hyperv'], asVirtModesSup = ['hwvirt-np'],
64 sHddControllerType = 'SATA Controller');
65
66 self.oTestVmSet.aoTestVms.append(oTestVm);
67
68 self.sVMname = None
69
70 def showUsage(self):
71 rc = vbox.TestDriver.showUsage(self);
72 reporter.log('');
73 reporter.log('tdGuestHostTimings Options:');
74 reporter.log(' --runningvmname <vmname>');
75 return rc;
76
77 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
78 if asArgs[iArg] == '--runningvmname':
79 iArg += 1
80 if iArg >= len(asArgs):
81 raise base.InvalidOption('The "----runningvmname" needs VM name')
82
83 self.sVMname = asArgs[iArg]
84 else:
85 return vbox.TestDriver.parseOption(self, asArgs, iArg)
86 return iArg + 1
87
88 def actionConfig(self):
89 return True
90
91 def actionExecute(self):
92 #self.sTempPathHost = os.environ.get("IPRT_TMPDIR")
93 self.sTempPathHost = os.path.normpath(os.environ.get("TEMP") + "/VBoxAudioValKit")
94
95 if self.sVMname is None:
96 return self.oTestVmSet.actionExecute(self, self.testOneVmConfig)
97 else:
98 return self.actionExecuteOnRunnigVM()
99
100 def doTest(self, oSession):
101 oConsole = oSession.console
102 oGuest = oConsole.guest
103
104 sOSTypeId = oGuest.OSTypeId.lower()
105 if sOSTypeId.find("win") == -1 :
106 reporter.log("Only Windows guests are currently supported")
107 reporter.testDone()
108 return True
109
110 oGuestSession = oGuest.createSession("Administrator", "password", "", "Audio Validation Kit")
111 guestSessionWaitResult = oGuestSession.waitFor(self.oVBoxMgr.constants.GuestSessionWaitResult_Start, 2000)
112 reporter.log("guestSessionWaitResult = %d" % guestSessionWaitResult)
113
114 for duration in range(3, 6):
115 reporter.testStart("Checking for duration of " + str(duration) + " seconds")
116 sPathToPlayer = "D:\\win\\" + ("amd64" if (sOSTypeId.find('_64') >= 0) else "x86") + "\\ntPlayToneWaveX.exe"
117 oProcess = oGuestSession.processCreate(sPathToPlayer, ["xxx0", "--total-duration-in-secs", str(duration)], [], [], 0)
118 processWaitResult = oProcess.waitFor(self.oVBoxMgr.constants.ProcessWaitForFlag_Start, 1000)
119 reporter.log("Started: pid %d, waitResult %d" % (oProcess.PID, processWaitResult))
120
121 processWaitResult = oProcess.waitFor(self.oVBoxMgr.constants.ProcessWaitForFlag_Terminate, 2 * duration * 1000)
122 reporter.log("Terminated: pid %d, waitResult %d" % (oProcess.PID, processWaitResult))
123 time.sleep(1) # Give audio backend sometime to save a stream to .wav file
124
125 absFileName = self.seekLatestAudioFileName(oGuestSession, duration)
126
127 if absFileName is None:
128 reporter.testFailure("Unable to find audio file")
129 continue
130
131 reporter.log("Checking audio file '" + absFileName + "'")
132
133 diff = self.checkGuestHostTimings(absFileName + ".timing")
134 if diff is not None:
135 if diff > 0.0: # Guest sends data quicker than a host can play
136 if diff > 0.01: # 1% is probably good threshold here
137 reporter.testFailure("Guest sends audio buffers too quickly")
138 else:
139 diff = -diff; # Much worse case: guest sends data very slow, host feels starvation
140 if diff > 0.005: # 0.5% is probably good threshold here
141 reporter.testFailure("Guest sends audio buffers too slowly")
142
143 reporter.testDone()
144 else:
145 reporter.testFailure("Unable to parse a file with timings")
146
147 oGuestSession.close()
148
149 del oGuest
150 del oConsole
151
152 return True
153
154 def testOneVmConfig(self, oVM, oTestVm):
155 #self.logVmInfo(oVM)
156 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName,
157 fCdWait = True,
158 cMsTimeout = 60 * 1000)
159 if oSession is not None and oTxsSession is not None:
160 # Wait until guest reported success
161 reporter.log('Guest started. Connection to TXS service established.')
162 self.doTest(oSessionWrapper.o)
163
164 return True
165
166 def actionExecuteOnRunnigVM(self):
167 if not self.importVBoxApi():
168 return False;
169
170 oVirtualBox = self.oVBoxMgr.getVirtualBox()
171 oMachine = oVirtualBox.findMachine(self.sVMname)
172
173 if oMachine == None:
174 reporter.log("Machine '%s' is unknown" % (oMachine.name))
175 return False
176
177 if oMachine.state != self.oVBoxMgr.constants.MachineState_Running:
178 reporter.log("Machine '%s' is not Running" % (oMachine.name))
179 return False
180
181 oSession = self.oVBoxMgr.mgr.getSessionObject(oVirtualBox)
182 oMachine.lockMachine(oSession, self.oVBoxMgr.constants.LockType_Shared)
183
184 self.doTest(oSession);
185
186 oSession.unlockMachine()
187
188 del oSession
189 del oMachine
190 del oVirtualBox
191 return True
192
193 def seekLatestAudioFileName(self, guestSession, duration):
194
195 listOfFiles = os.listdir(self.sTempPathHost)
196 # Assuming that .wav files are named like 2016-11-15T12_08_27.669573100Z.wav by VBOX audio backend
197 # So that sorting by name = sorting by creation date
198 listOfFiles.sort(reverse = True)
199
200 for fileName in listOfFiles:
201 if not fileName.endswith(".wav"):
202 continue
203
204 absFileName = os.path.join(self.sTempPathHost, fileName)
205
206 # Ignore too small wav files (usually uncompleted audio streams)
207 statInfo = os.stat(absFileName)
208 if statInfo.st_size > 100:
209 return absFileName
210
211 return
212
213 def checkGuestHostTimings(self, absFileName):
214 with open(absFileName) as f:
215 for line_terminated in f:
216 line = line_terminated.rstrip('\n')
217
218 reporter.log("Last line is: " + line)
219 matchObj = re.match( r'(\d+) (\d+)', line, re.I)
220 if matchObj:
221 hostTime = int(matchObj.group(1))
222 guestTime = int(matchObj.group(2))
223
224 diff = float(guestTime - hostTime) / hostTime
225 return diff
226
227 return
228
229if __name__ == '__main__':
230 sys.exit(tdGuestHostTimings().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