VirtualBox

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

Last change on this file since 71710 was 70796, checked in by vboxsync, 7 years ago

ValidationKit/serial/tdSerial1: Add loopback module for TCP/named pipe modes to relay sent data back to the guest. Named pipe support for Windows is missing

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdSerial1.py 70796 2018-01-29 18:01:27Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Serial port testing #1.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2018 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: 70796 $"
31
32
33# Standard Python imports.
34import os;
35import random;
36import string;
37import struct;
38import sys;
39
40# Only the main script needs to modify the path.
41try: __file__
42except: __file__ = sys.argv[0];
43g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
44sys.path.append(g_ksValidationKitDir);
45
46# Validation Kit imports.
47from testdriver import base;
48from testdriver import reporter;
49from testdriver import vbox;
50from testdriver import vboxcon;
51
52import loopback;
53
54class tdSerial1(vbox.TestDriver):
55 """
56 VBox serial port testing #1.
57 """
58
59 def __init__(self):
60 vbox.TestDriver.__init__(self);
61 self.asRsrcs = None;
62 self.oTestVmSet = self.oTestVmManager.selectSet(self.oTestVmManager.kfGrpStdSmoke);
63 self.asSerialModesDef = ['RawFile', 'Tcp', 'TcpServ', 'NamedPipe', 'NamedPipeServ', 'HostDev'];
64 self.asSerialModes = self.asSerialModesDef;
65 self.asSerialTestsDef = ['Write', 'ReadWrite'];
66 self.asSerialTests = self.asSerialTestsDef;
67 self.oLoopback = None;
68 self.sLocation = None;
69
70 #
71 # Overridden methods.
72 #
73 def showUsage(self):
74 rc = vbox.TestDriver.showUsage(self);
75 reporter.log('');
76 reporter.log('tdSerial1 Options:');
77 reporter.log(' --serial-modes <m1[:m2[:]]');
78 reporter.log(' Default: %s' % (':'.join(self.asSerialModesDef)));
79 reporter.log(' --serial-tests <t1[:t2[:]]');
80 reporter.log(' Default: %s' % (':'.join(self.asSerialTestsDef)));
81 return rc;
82
83 def parseOption(self, asArgs, iArg):
84 if asArgs[iArg] == '--serial-modes':
85 iArg += 1;
86 if iArg >= len(asArgs):
87 raise base.InvalidOption('The "--serial-modes" takes a colon separated list of serial port modes to test');
88 self.asSerialModes = asArgs[iArg].split(':');
89 for s in self.asSerialModes:
90 if s not in self.asSerialModesDef:
91 reporter.log('warning: The "--serial-modes" value "%s" is not a valid serial port mode.' % (s));
92 elif asArgs[iArg] == '--serial-tests':
93 iArg += 1;
94 if iArg >= len(asArgs):
95 raise base.InvalidOption('The "--serial-tests" takes a colon separated list of serial port tests');
96 self.asSerialTests = asArgs[iArg].split(':');
97 for s in self.asSerialTests:
98 if s not in self.asSerialTestsDef:
99 reporter.log('warning: The "--serial-tests" value "%s" is not a valid serial port test.' % (s));
100 else:
101 return vbox.TestDriver.parseOption(self, asArgs, iArg);
102
103 return iArg + 1;
104
105 def actionVerify(self):
106 if self.sVBoxValidationKitIso is None or not os.path.isfile(self.sVBoxValidationKitIso):
107 reporter.error('Cannot find the VBoxValidationKit.iso! (%s)'
108 'Please unzip a Validation Kit build in the current directory or in some parent one.'
109 % (self.sVBoxValidationKitIso,) );
110 return False;
111 return vbox.TestDriver.actionVerify(self);
112
113 def actionConfig(self):
114 # Make sure vboxapi has been imported so we can use the constants.
115 if not self.importVBoxApi():
116 return False;
117
118 assert self.sVBoxValidationKitIso is not None;
119 return self.oTestVmSet.actionConfig(self, sDvdImage = self.sVBoxValidationKitIso);
120
121 def actionExecute(self):
122 """
123 Execute the testcase.
124 """
125 return self.oTestVmSet.actionExecute(self, self.testOneVmConfig)
126
127
128 #
129 # Test execution helpers.
130 #
131
132 def _generateRawPortFilename(self, oTestDrv, oTestVm, sInfix, sSuffix):
133 """ Generates a raw port filename. """
134 random.seed();
135 sRandom = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10));
136 return os.path.join(oTestDrv.sScratchPath, oTestVm.sVmName + sInfix + sRandom + sSuffix);
137
138 def setupSerialMode(self, oSession, oTestVm, sMode):
139 """
140 Sets up the serial mode.
141 """
142 fRc = True;
143 fServer = False;
144 sLocation = None;
145 ePortMode = vboxcon.PortMode_Disconnected;
146 if sMode == 'RawFile':
147 sLocation = self._generateRawPortFilename(self, oTestVm, '-com1-', '.out');
148 ePortMode = vboxcon.PortMode_RawFile;
149 elif sMode == 'Tcp':
150 sLocation = '127.0.0.1:1234';
151 self.oLoopback = loopback.SerialLoopback(loopback.g_ksLoopbackTcpServ, sLocation);
152 ePortMode = vboxcon.PortMode_TCP;
153 elif sMode == 'TcpServ':
154 fServer = True;
155 sLocation = '1234';
156 ePortMode = vboxcon.PortMode_TCP;
157 self.oLoopback = loopback.SerialLoopback(loopback.g_ksLoopbackTcpClient, '127.0.0.1:1234');
158 elif sMode == 'NamedPipe':
159 sLocation = self._generateRawPortFilename(self, oTestVm, '-com1-', '.out');
160 ePortMode = vboxcon.PortMode_HostPipe;
161 self.oLoopback = loopback.SerialLoopback(loopback.g_ksLoopbackNamedPipeServ, sLocation);
162 elif sMode == 'NamedPipeServ':
163 fServer = True;
164 sLocation = self._generateRawPortFilename(self, oTestVm, '-com1-', '.out');
165 ePortMode = vboxcon.PortMode_HostPipe;
166 self.oLoopback = loopback.SerialLoopback(loopback.g_ksLoopbackNamedPipeClient, sLocation);
167 elif sMode == 'HostDev':
168 sLocation = '/dev/ttyUSB0';
169 ePortMode = vboxcon.PortMode_HostDevice;
170 else:
171 reporter.log('warning, invalid mode %s given' % (sMode, ));
172 fRc = False;
173
174 if fRc:
175 fRc = oSession.changeSerialPortAttachment(0, ePortMode, sLocation, fServer);
176 if fRc and (sMode == 'TcpServ' or sMode == 'NamedPipeServ'):
177 self.sleep(2); # Fudge to allow the TCP server to get started.
178 fRc = self.oLoopback.connect();
179 if not fRc:
180 reporter.log('Failed to connect to %s' % (sLocation, ));
181 self.sLocation = sLocation;
182
183 return fRc;
184
185 def testWrite(self, oSession, oTxsSession, oTestVm, sMode):
186 """
187 Does a simple write test verifying the output.
188 """
189 _ = oSession;
190
191 reporter.testStart('Write');
192 tupCmdLine = ('SerialTest', '--tests', 'write', '--txbytes', '1048576', '--device');
193 if oTestVm.isWindows():
194 tupCmdLine += (r'\\.\COM1',);
195 elif oTestVm.isLinux():
196 tupCmdLine += (r'/dev/ttyS0',);
197
198 fRc = self.txsRunTest(oTxsSession, 'SerialTest', 3600 * 1000, \
199 '${CDROM}/${OS/ARCH}/SerialTest${EXESUFF}', tupCmdLine);
200 if not fRc:
201 reporter.testFailure('Running serial test utility failed');
202 elif sMode == 'RawFile':
203 # Open serial port and verify
204 cLast = 0;
205 try:
206 oFile = open(self.sLocation, 'rb');
207 sFmt = '=I';
208 cBytes = 4;
209 for i in xrange(1048576 / 4):
210 _ = i;
211 sData = oFile.read(cBytes);
212 tupUnpacked = struct.unpack(sFmt, sData);
213 cLast = cLast + 1;
214 if tupUnpacked[0] != cLast:
215 reporter.testFailure('Corruption detected, expected counter value %s, got %s'
216 % (cLast + 1, tupUnpacked[0]));
217 break;
218 oFile.close();
219 except:
220 reporter.testFailure('Verifying the written data failed');
221 reporter.testDone();
222 return fRc;
223
224 def testReadWrite(self, oSession, oTxsSession, oTestVm):
225 """
226 Does a simple write test verifying the output.
227 """
228 _ = oSession;
229
230 reporter.testStart('ReadWrite');
231 tupCmdLine = ('SerialTest', '--tests', 'readwrite', '--txbytes', '1048576', '--device');
232 if oTestVm.isWindows():
233 tupCmdLine += (r'\\.\COM1',);
234 elif oTestVm.isLinux():
235 tupCmdLine += (r'/dev/ttyS0',);
236
237 fRc = self.txsRunTest(oTxsSession, 'SerialTest', 600 * 1000, \
238 '${CDROM}/${OS/ARCH}/SerialTest${EXESUFF}', tupCmdLine);
239 if not fRc:
240 reporter.testFailure('Running serial test utility failed');
241
242 reporter.testDone();
243 return fRc;
244
245 def isModeCompatibleWithTest(self, sMode, sTest):
246 """
247 Returns whether the given port mode and test combination is
248 supported for testing.
249 """
250 if sMode == 'RawFile' and sTest == 'ReadWrite':
251 return False;
252 elif sMode != 'RawFile' and sTest == 'Write':
253 return False;
254
255 return True;
256
257 def testOneVmConfig(self, oVM, oTestVm):
258 """
259 Runs the specified VM thru test #1.
260 """
261
262 # Reconfigure the VM
263 fRc = True;
264 oSession = self.openSession(oVM);
265 if oSession is not None:
266 fRc = oSession.enableSerialPort(0);
267
268 fRc = fRc and oSession.saveSettings();
269 fRc = oSession.close() and fRc;
270 oSession = None;
271 else:
272 fRc = False;
273
274 if fRc is True:
275 self.logVmInfo(oVM);
276 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = True);
277 if oSession is not None:
278 self.addTask(oTxsSession);
279
280 for sMode in self.asSerialModes:
281 reporter.testStart(sMode);
282 fRc = self.setupSerialMode(oSession, oTestVm, sMode);
283 if fRc:
284 for sTest in self.asSerialTests:
285 # Skip tests which don't work with the current mode.
286 if self.isModeCompatibleWithTest(sMode, sTest):
287 if sTest == 'Write':
288 fRc = self.testWrite(oSession, oTxsSession, oTestVm, sMode);
289 if sTest == 'ReadWrite':
290 fRc = self.testReadWrite(oSession, oTxsSession, oTestVm);
291 if self.oLoopback is not None:
292 self.oLoopback.shutdown();
293 self.oLoopback = None;
294
295 reporter.testDone();
296
297 self.removeTask(oTxsSession);
298 self.terminateVmBySession(oSession);
299 return fRc;
300
301if __name__ == '__main__':
302 sys.exit(tdSerial1().main(sys.argv));
303
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