VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/serial/tdSerial1.py@ 106743

Last change on this file since 106743 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 13.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdSerial1.py 106061 2024-09-16 14:03:52Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Serial port testing #1.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2018-2024 Oracle and/or its affiliates.
12
13This file is part of VirtualBox base platform packages, as
14available from https://www.virtualbox.org.
15
16This program is free software; you can redistribute it and/or
17modify it under the terms of the GNU General Public License
18as published by the Free Software Foundation, in version 3 of the
19License.
20
21This program is distributed in the hope that it will be useful, but
22WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with this program; if not, see <https://www.gnu.org/licenses>.
28
29The contents of this file may alternatively be used under the terms
30of the Common Development and Distribution License Version 1.0
31(CDDL), a copy of it is provided in the "COPYING.CDDL" file included
32in the VirtualBox distribution, in which case the provisions of the
33CDDL are applicable instead of those of the GPL.
34
35You may elect to license modified versions of this file under the
36terms and conditions of either the GPL or the CDDL or both.
37
38SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
39"""
40__version__ = "$Revision: 106061 $"
41
42
43# Standard Python imports.
44import os;
45import random;
46import string;
47import struct;
48import sys;
49
50# Only the main script needs to modify the path.
51try: __file__ # pylint: disable=used-before-assignment
52except: __file__ = sys.argv[0];
53g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
54sys.path.append(g_ksValidationKitDir);
55
56# Validation Kit imports.
57from testdriver import base;
58from testdriver import reporter;
59from testdriver import vbox;
60from testdriver import vboxcon;
61
62import loopback;
63
64# Python 3 hacks:
65if sys.version_info[0] >= 3:
66 xrange = range; # pylint: disable=redefined-builtin,invalid-name
67
68
69class tdSerial1(vbox.TestDriver):
70 """
71 VBox serial port testing #1.
72 """
73
74 def __init__(self):
75 vbox.TestDriver.__init__(self);
76 self.asRsrcs = None;
77 self.oTestVmSet = self.oTestVmManager.selectSet(self.oTestVmManager.kfGrpStdSmoke);
78 self.asSerialModesDef = ['RawFile', 'Tcp', 'TcpServ', 'NamedPipe', 'NamedPipeServ', 'HostDev'];
79 self.asSerialModes = self.asSerialModesDef;
80 self.asSerialTestsDef = ['Write', 'ReadWrite'];
81 self.asSerialTests = self.asSerialTestsDef;
82 self.asUartsDef = ['16450', '16550A', '16750'];
83 self.asUarts = self.asUartsDef;
84 self.oLoopback = None;
85 self.sLocation = None;
86 self.fVerboseTest = False;
87
88 #
89 # Overridden methods.
90 #
91 def showUsage(self):
92 rc = vbox.TestDriver.showUsage(self);
93 reporter.log('');
94 reporter.log('tdSerial1 Options:');
95 reporter.log(' --serial-modes <m1[:m2[:]]');
96 reporter.log(' Default: %s' % (':'.join(self.asSerialModesDef)));
97 reporter.log(' --serial-tests <t1[:t2[:]]');
98 reporter.log(' Default: %s' % (':'.join(self.asSerialTestsDef)));
99 reporter.log(' --uarts <u1[:u2[:]]');
100 reporter.log(' Default: %s' % (':'.join(self.asUartsDef)));
101 reporter.log(' --verbose-test');
102 reporter.log(' Whether to enable verbose output when running the');
103 reporter.log(' test utility inside the VM');
104 return rc;
105
106 def parseOption(self, asArgs, iArg):
107 if asArgs[iArg] == '--serial-modes':
108 iArg += 1;
109 if iArg >= len(asArgs):
110 raise base.InvalidOption('The "--serial-modes" takes a colon separated list of serial port modes to test');
111 self.asSerialModes = asArgs[iArg].split(':');
112 for s in self.asSerialModes:
113 if s not in self.asSerialModesDef:
114 reporter.log('warning: The "--serial-modes" value "%s" is not a valid serial port mode.' % (s));
115 elif asArgs[iArg] == '--serial-tests':
116 iArg += 1;
117 if iArg >= len(asArgs):
118 raise base.InvalidOption('The "--serial-tests" takes a colon separated list of serial port tests');
119 self.asSerialTests = asArgs[iArg].split(':');
120 for s in self.asSerialTests:
121 if s not in self.asSerialTestsDef:
122 reporter.log('warning: The "--serial-tests" value "%s" is not a valid serial port test.' % (s));
123 elif asArgs[iArg] == '--uarts':
124 iArg += 1;
125 if iArg >= len(asArgs):
126 raise base.InvalidOption('The "--uarts" takes a colon separated list of uarts to test');
127 self.asUarts = asArgs[iArg].split(':');
128 for s in self.asUarts:
129 if s not in self.asUartsDef:
130 reporter.log('warning: The "--uarts" value "%s" is not a valid uart.' % (s));
131 elif asArgs[iArg] == '--verbose-test':
132 iArg += 1;
133 self.fVerboseTest = True;
134 else:
135 return vbox.TestDriver.parseOption(self, asArgs, iArg);
136
137 return iArg + 1;
138
139 def actionVerify(self):
140 if self.sVBoxValidationKitIso is None or not os.path.isfile(self.sVBoxValidationKitIso):
141 reporter.error('Cannot find the VBoxValidationKit.iso! (%s)'
142 'Please unzip a Validation Kit build in the current directory or in some parent one.'
143 % (self.sVBoxValidationKitIso,) );
144 return False;
145 return vbox.TestDriver.actionVerify(self);
146
147 def actionConfig(self):
148 # Make sure vboxapi has been imported so we can use the constants.
149 if not self.importVBoxApi():
150 return False;
151
152 assert self.sVBoxValidationKitIso is not None;
153 return self.oTestVmSet.actionConfig(self, sDvdImage = self.sVBoxValidationKitIso);
154
155 def actionExecute(self):
156 """
157 Execute the testcase.
158 """
159 return self.oTestVmSet.actionExecute(self, self.testOneVmConfig)
160
161
162 #
163 # Test execution helpers.
164 #
165
166 def _generateRawPortFilename(self, oTestDrv, oTestVm, sInfix, sSuffix):
167 """ Generates a raw port filename. """
168 random.seed();
169 sRandom = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10));
170 return os.path.join(oTestDrv.sScratchPath, oTestVm.sVmName + sInfix + sRandom + sSuffix);
171
172 def setupSerialMode(self, oSession, oTestVm, sMode):
173 """
174 Sets up the serial mode.
175 """
176 fRc = True;
177 fServer = False;
178 sLocation = None;
179 ePortMode = vboxcon.PortMode_Disconnected;
180 if sMode == 'RawFile':
181 sLocation = self._generateRawPortFilename(self, oTestVm, '-com1-', '.out');
182 ePortMode = vboxcon.PortMode_RawFile;
183 elif sMode == 'Tcp':
184 sLocation = '127.0.0.1:1234';
185 self.oLoopback = loopback.SerialLoopback(loopback.g_ksLoopbackTcpServ, sLocation);
186 ePortMode = vboxcon.PortMode_TCP;
187 elif sMode == 'TcpServ':
188 fServer = True;
189 sLocation = '1234';
190 ePortMode = vboxcon.PortMode_TCP;
191 self.oLoopback = loopback.SerialLoopback(loopback.g_ksLoopbackTcpClient, '127.0.0.1:1234');
192 elif sMode == 'NamedPipe':
193 sLocation = self._generateRawPortFilename(self, oTestVm, '-com1-', '.out');
194 ePortMode = vboxcon.PortMode_HostPipe;
195 self.oLoopback = loopback.SerialLoopback(loopback.g_ksLoopbackNamedPipeServ, sLocation);
196 elif sMode == 'NamedPipeServ':
197 fServer = True;
198 sLocation = self._generateRawPortFilename(self, oTestVm, '-com1-', '.out');
199 ePortMode = vboxcon.PortMode_HostPipe;
200 self.oLoopback = loopback.SerialLoopback(loopback.g_ksLoopbackNamedPipeClient, sLocation);
201 elif sMode == 'HostDev':
202 sLocation = '/dev/ttyUSB0';
203 ePortMode = vboxcon.PortMode_HostDevice;
204 else:
205 reporter.log('warning, invalid mode %s given' % (sMode, ));
206 fRc = False;
207
208 if fRc:
209 fRc = oSession.changeSerialPortAttachment(0, ePortMode, sLocation, fServer);
210 if fRc and sMode in ('TcpServ', 'NamedPipeServ',):
211 self.sleep(2); # Fudge to allow the TCP server to get started.
212 fRc = self.oLoopback.connect();
213 if not fRc:
214 reporter.log('Failed to connect to %s' % (sLocation, ));
215 self.sLocation = sLocation;
216
217 return fRc;
218
219 def testWrite(self, oSession, oTxsSession, oTestVm, sMode):
220 """
221 Does a simple write test verifying the output.
222 """
223 _ = oSession;
224
225 reporter.testStart('Write');
226 tupCmdLine = ('SerialTest', '--tests', 'write', '--txbytes', '1048576');
227 if self.fVerboseTest:
228 tupCmdLine += ('--verbose',);
229 if oTestVm.isWindows():
230 tupCmdLine += ('--device', r'\\.\COM1',);
231 elif oTestVm.isLinux():
232 tupCmdLine += ('--device', r'/dev/ttyS0',);
233
234 fRc = self.txsRunTest(oTxsSession, 'SerialTest', 3600 * 1000, \
235 '${CDROM}/${OS/ARCH}/SerialTest${EXESUFF}', tupCmdLine);
236 if not fRc:
237 reporter.testFailure('Running serial test utility failed');
238 elif sMode == 'RawFile':
239 # Open serial port and verify
240 cLast = 0;
241 try:
242 with open(self.sLocation, 'rb') as oFile:
243 sFmt = '=I';
244 cBytes = 4;
245 for i in xrange(1048576 // 4):
246 _ = i;
247 sData = oFile.read(cBytes);
248 tupUnpacked = struct.unpack(sFmt, sData);
249 cLast = cLast + 1;
250 if tupUnpacked[0] != cLast:
251 reporter.testFailure('Corruption detected, expected counter value %s, got %s'
252 % (cLast + 1, tupUnpacked[0],));
253 break;
254 except:
255 reporter.logXcpt();
256 reporter.testFailure('Verifying the written data failed');
257 reporter.testDone();
258 return fRc;
259
260 def testReadWrite(self, oSession, oTxsSession, oTestVm):
261 """
262 Does a simple write test verifying the output.
263 """
264 _ = oSession;
265
266 reporter.testStart('ReadWrite');
267 tupCmdLine = ('SerialTest', '--tests', 'readwrite', '--txbytes', '1048576');
268 if self.fVerboseTest:
269 tupCmdLine += ('--verbose',);
270 if oTestVm.isWindows():
271 tupCmdLine += ('--device', r'\\.\COM1',);
272 elif oTestVm.isLinux():
273 tupCmdLine += ('--device', r'/dev/ttyS0',);
274
275 fRc = self.txsRunTest(oTxsSession, 'SerialTest', 600 * 1000, \
276 '${CDROM}/${OS/ARCH}/SerialTest${EXESUFF}', tupCmdLine);
277 if not fRc:
278 reporter.testFailure('Running serial test utility failed');
279
280 reporter.testDone();
281 return fRc;
282
283 def isModeCompatibleWithTest(self, sMode, sTest):
284 """
285 Returns whether the given port mode and test combination is
286 supported for testing.
287 """
288 if sMode == 'RawFile' and sTest == 'ReadWrite':
289 return False;
290 if sMode != 'RawFile' and sTest == 'Write':
291 return False;
292 return True;
293
294 def testOneVmConfig(self, oVM, oTestVm):
295 """
296 Runs the specified VM thru test #1.
297 """
298
299 for sUart in self.asUarts:
300 reporter.testStart(sUart);
301 # Reconfigure the VM
302 fRc = True;
303 oSession = self.openSession(oVM);
304 if oSession is not None:
305 fRc = oSession.enableSerialPort(0);
306
307 fRc = fRc and oSession.setExtraData("VBoxInternal/Devices/serial/0/Config/UartType", "string:" + sUart);
308 fRc = fRc and oSession.saveSettings();
309 fRc = oSession.close() and fRc;
310 oSession = None;
311 else:
312 fRc = False;
313
314 if fRc is True:
315 self.logVmInfo(oVM);
316 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = True);
317 if oSession is not None:
318 self.addTask(oTxsSession);
319
320 for sMode in self.asSerialModes:
321 reporter.testStart(sMode);
322 fRc = self.setupSerialMode(oSession, oTestVm, sMode);
323 if fRc:
324 for sTest in self.asSerialTests:
325 # Skip tests which don't work with the current mode.
326 if self.isModeCompatibleWithTest(sMode, sTest):
327 if sTest == 'Write':
328 fRc = self.testWrite(oSession, oTxsSession, oTestVm, sMode);
329 if sTest == 'ReadWrite':
330 fRc = self.testReadWrite(oSession, oTxsSession, oTestVm);
331 if self.oLoopback is not None:
332 self.oLoopback.shutdown();
333 self.oLoopback = None;
334
335 reporter.testDone();
336
337 self.removeTask(oTxsSession);
338 self.terminateVmBySession(oSession);
339 reporter.testDone();
340
341 return fRc;
342
343if __name__ == '__main__':
344 sys.exit(tdSerial1().main(sys.argv));
345
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