VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py@ 79208

Last change on this file since 79208 was 79208, checked in by vboxsync, 5 years ago

ValKit/tdAddGuestCtrl.py: More cleanups in the copyto area. bugref:9320

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 200.1 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# pylint: disable=too-many-lines
4
5"""
6VirtualBox Validation Kit - Guest Control Tests.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2019 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: 79208 $"
31
32# Standard Python imports.
33from array import array
34import errno
35import os
36import random
37import struct
38import sys
39import threading
40import time
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 testfileset;
52from testdriver import vbox;
53from testdriver import vboxcon;
54from testdriver import vboxtestfileset;
55from testdriver import vboxwrappers;
56from common import utils;
57
58# Python 3 hacks:
59if sys.version_info[0] >= 3:
60 long = int # pylint: disable=redefined-builtin,invalid-name
61 xrange = range; # pylint: disable=redefined-builtin,invalid-name
62
63
64class GuestStream(bytearray):
65 """
66 Class for handling a guest process input/output stream.
67 """
68 def appendStream(self, stream, convertTo = '<b'):
69 """
70 Appends and converts a byte sequence to this object;
71 handy for displaying a guest stream.
72 """
73 self.extend(struct.pack(convertTo, stream));
74
75class tdCtxTest(object):
76 """
77 Provides the actual test environment.
78 Should be kept as generic as possible.
79 """
80 def __init__(self, oSession, oTxsSession, oTestVm): # pylint: disable=unused-argument
81 ## The desired Main API result.
82 self.fRc = False;
83 ## IGuest reference.
84 self.oGuest = oSession.o.console.guest; ## @todo may throw shit
85 self.oSesison = oSession;
86 self.oTxsSesison = oTxsSession;
87 self.oTestVm = oTestVm;
88
89class tdCtxCreds(object):
90 """
91 Provides credentials to pass to the guest.
92 """
93 def __init__(self, sUser = None, sPassword = None, sDomain = None):
94 self.oTestVm = None;
95 self.sUser = sUser;
96 self.sPassword = sPassword;
97 self.sDomain = sDomain;
98
99 def applyDefaultsIfNotSet(self, oTestVm):
100 """
101 Applies credential defaults, based on the test VM (guest OS), if
102 no credentials were set yet.
103 """
104 self.oTestVm = oTestVm;
105 assert self.oTestVm is not None;
106
107 if self.sUser is None:
108 self.sUser = self.oTestVm.getTestUser();
109
110 if self.sPassword is None:
111 self.sPassword = self.oTestVm.getTestUserPassword(self.sUser);
112
113 if self.sDomain is None:
114 self.sDomain = '';
115
116class tdTestGuestCtrlBase(object):
117 """
118 Base class for all guest control tests.
119
120 Note: This test ASSUMES that working Guest Additions
121 were installed and running on the guest to be tested.
122 """
123 def __init__(self):
124 self.oTest = None;
125 self.oCreds = None;
126 self.timeoutMS = 30 * 1000; # 30s timeout
127 ## IGuestSession reference or None.
128 self.oGuestSession = None;
129
130 def setEnvironment(self, oSession, oTxsSession, oTestVm):
131 """
132 Sets the test environment required for this test.
133 """
134 self.oTest = tdCtxTest(oSession, oTxsSession, oTestVm);
135 self.oCreds.applyDefaultsIfNotSet(oTestVm);
136 return self.oTest;
137
138 def uploadLogData(self, oTstDrv, aData, sFileName, sDesc):
139 """
140 Uploads (binary) data to a log file for manual (later) inspection.
141 """
142 reporter.log('Creating + uploading log data file "%s"' % sFileName);
143 sHstFileName = os.path.join(oTstDrv.sScratchPath, sFileName);
144 try:
145 oCurTestFile = open(sHstFileName, "wb");
146 oCurTestFile.write(aData);
147 oCurTestFile.close();
148 except:
149 return reporter.error('Unable to create temporary file for "%s"' % (sDesc,));
150 return reporter.addLogFile(sHstFileName, 'misc/other', sDesc);
151
152 def createSession(self, sName, fIsError = False):
153 """
154 Creates (opens) a guest session.
155 Returns (True, IGuestSession) on success or (False, None) on failure.
156 """
157 if self.oGuestSession is None:
158 if sName is None:
159 sName = "<untitled>";
160
161 reporter.log('Creating session "%s" ...' % (sName,));
162 try:
163 self.oGuestSession = self.oTest.oGuest.createSession(self.oCreds.sUser,
164 self.oCreds.sPassword,
165 self.oCreds.sDomain,
166 sName);
167 except:
168 # Just log, don't assume an error here (will be done in the main loop then).
169 reporter.maybeErrXcpt(fIsError, 'Creating a guest session "%s" failed; sUser="%s", pw="%s", sDomain="%s":'
170 % (sName, self.oCreds.sUser, self.oCreds.sPassword, self.oCreds.sDomain));
171 return (False, None);
172
173 reporter.log('Waiting for session "%s" to start within %dms...' % (sName, self.timeoutMS));
174 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
175 try:
176 waitResult = self.oGuestSession.waitForArray(aeWaitFor, self.timeoutMS);
177
178 #
179 # Be nice to Guest Additions < 4.3: They don't support session handling and
180 # therefore return WaitFlagNotSupported.
181 #
182 if waitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
183 # Just log, don't assume an error here (will be done in the main loop then).
184 reporter.maybeErr(fIsError, 'Session did not start successfully, returned wait result: %d' % (waitResult,));
185 return (False, None);
186 reporter.log('Session "%s" successfully started' % (sName,));
187 except:
188 # Just log, don't assume an error here (will be done in the main loop then).
189 reporter.maybeErrXcpt(fIsError, 'Waiting for guest session "%s" (usr=%s;pw=%s;dom=%s) to start failed:'
190 % (sName, self.oCreds.sUser, self.oCreds.sPassword, self.oCreds.sDomain,));
191 return (False, None);
192 else:
193 reporter.log('Warning: Session already set; this is probably not what you want');
194 return (True, self.oGuestSession);
195
196 def setSession(self, oGuestSession):
197 """
198 Sets the current guest session and closes
199 an old one if necessary.
200 """
201 if self.oGuestSession is not None:
202 self.closeSession();
203 self.oGuestSession = oGuestSession;
204 return self.oGuestSession;
205
206 def closeSession(self, fIsError = False):
207 """
208 Closes the guest session.
209 """
210 if self.oGuestSession is not None:
211 try:
212 sName = self.oGuestSession.name;
213 except:
214 return reporter.errorXcpt();
215
216 reporter.log('Closing session "%s" ...' % (sName,));
217 try:
218 self.oGuestSession.close();
219 self.oGuestSession = None;
220 except:
221 # Just log, don't assume an error here (will be done in the main loop then).
222 reporter.maybeErrXcpt(fIsError, 'Closing guest session "%s" failed:' % (sName,));
223 return False;
224 return True;
225
226class tdTestCopyFrom(tdTestGuestCtrlBase):
227 """
228 Test for copying files from the guest to the host.
229 """
230 def __init__(self, sSrc = "", sDst = "", sUser = None, sPassword = None, fFlags = None, oSrc = None):
231 tdTestGuestCtrlBase.__init__(self);
232 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
233 self.sSrc = sSrc;
234 self.sDst = sDst;
235 self.fFlags = fFlags;
236 self.oSrc = oSrc # type: testfileset.TestFsObj
237 if oSrc and not sSrc:
238 self.sSrc = oSrc.sPath;
239
240class tdTestCopyFromDir(tdTestCopyFrom):
241
242 def __init__(self, sSrc = "", sDst = "", sUser = None, sPassword = None, fFlags = None, oSrc = None, fIntoDst = False):
243 tdTestCopyFrom.__init__(self, sSrc, sDst, sUser, sPassword, fFlags, oSrc);
244 self.fIntoDst = fIntoDst; # hint to the verification code that sDst == oSrc, rather than sDst+oSrc.sNAme == oSrc.
245
246class tdTestCopyFromFile(tdTestCopyFrom):
247 pass;
248
249class tdTestRemoveHostDir(object):
250 """
251 Test step that removes a host directory tree.
252 """
253 def __init__(self, sDir):
254 self.sDir = sDir;
255
256 def execute(self, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
257 _ = oTstDrv; _ = oVmSession; _ = oTxsSession; _ = oTestVm; _ = sMsgPrefix;
258 if os.path.exists(self.sDir):
259 if base.wipeDirectory(self.sDir) != 0:
260 return False;
261 try:
262 os.rmdir(self.sDir);
263 except:
264 return reporter.errorXcpt('%s: sDir=%s' % (sMsgPrefix, self.sDir,));
265 return True;
266
267
268
269class tdTestCopyTo(tdTestGuestCtrlBase):
270 """
271 Test for copying files from the host to the guest.
272 """
273 def __init__(self, sSrc = "", sDst = "", sUser = None, sPassword = None, fFlags = None):
274 tdTestGuestCtrlBase.__init__(self);
275 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
276 self.sSrc = sSrc;
277 self.sDst = sDst;
278 self.fFlags = fFlags;
279
280class tdTestCopyToFile(tdTestCopyTo):
281 pass;
282
283class tdTestCopyToDir(tdTestCopyTo):
284 pass;
285
286class tdTestDirCreate(tdTestGuestCtrlBase):
287 """
288 Test for directoryCreate call.
289 """
290 def __init__(self, sDirectory = "", sUser = None, sPassword = None, fMode = 0, fFlags = None):
291 tdTestGuestCtrlBase.__init__(self);
292 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
293 self.sDirectory = sDirectory;
294 self.fMode = fMode;
295 self.fFlags = fFlags;
296
297class tdTestDirCreateTemp(tdTestGuestCtrlBase):
298 """
299 Test for the directoryCreateTemp call.
300 """
301 def __init__(self, sDirectory = "", sTemplate = "", sUser = None, sPassword = None, fMode = 0, fSecure = False):
302 tdTestGuestCtrlBase.__init__(self);
303 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
304 self.sDirectory = sDirectory;
305 self.sTemplate = sTemplate;
306 self.fMode = fMode;
307 self.fSecure = fSecure;
308
309class tdTestDirOpen(tdTestGuestCtrlBase):
310 """
311 Test for the directoryOpen call.
312 """
313 def __init__(self, sDirectory = "", sUser = None, sPassword = None, sFilter = "", fFlags = None):
314 tdTestGuestCtrlBase.__init__(self);
315 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
316 self.sDirectory = sDirectory;
317 self.sFilter = sFilter;
318 self.fFlags = fFlags or [];
319
320class tdTestDirRead(tdTestDirOpen):
321 """
322 Test for the opening, reading and closing a certain directory.
323 """
324 def __init__(self, sDirectory = "", sUser = None, sPassword = None,
325 sFilter = "", fFlags = None):
326 tdTestDirOpen.__init__(self, sDirectory, sUser, sPassword, sFilter, fFlags);
327
328class tdTestExec(tdTestGuestCtrlBase):
329 """
330 Specifies exactly one guest control execution test.
331 Has a default timeout of 5 minutes (for safety).
332 """
333 def __init__(self, sCmd = "", asArgs = None, aEnv = None, fFlags = None, # pylint: disable=too-many-arguments
334 timeoutMS = 5 * 60 * 1000, sUser = None, sPassword = None, sDomain = None, fWaitForExit = True):
335 tdTestGuestCtrlBase.__init__(self);
336 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain);
337 self.sCmd = sCmd;
338 self.asArgs = asArgs if asArgs is not None else [sCmd,];
339 self.aEnv = aEnv;
340 self.fFlags = fFlags or [];
341 self.timeoutMS = timeoutMS;
342 self.fWaitForExit = fWaitForExit;
343 self.uExitStatus = 0;
344 self.iExitCode = 0;
345 self.cbStdOut = 0;
346 self.cbStdErr = 0;
347 self.sBuf = '';
348
349class tdTestFileExists(tdTestGuestCtrlBase):
350 """
351 Test for the file exists API call (fileExists).
352 """
353 def __init__(self, sFile = "", sUser = None, sPassword = None):
354 tdTestGuestCtrlBase.__init__(self);
355 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
356 self.sFile = sFile;
357
358class tdTestFileRemove(tdTestGuestCtrlBase):
359 """
360 Test querying guest file information.
361 """
362 def __init__(self, sFile = "", sUser = None, sPassword = None):
363 tdTestGuestCtrlBase.__init__(self);
364 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
365 self.sFile = sFile;
366
367class tdTestFileStat(tdTestGuestCtrlBase):
368 """
369 Test querying guest file information.
370 """
371 def __init__(self, sFile = "", sUser = None, sPassword = None, cbSize = 0, eFileType = 0):
372 tdTestGuestCtrlBase.__init__(self);
373 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
374 self.sFile = sFile;
375 self.cbSize = cbSize;
376 self.eFileType = eFileType;
377
378class tdTestFileIO(tdTestGuestCtrlBase):
379 """
380 Test for the IGuestFile object.
381 """
382 def __init__(self, sFile = "", sUser = None, sPassword = None):
383 tdTestGuestCtrlBase.__init__(self);
384 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
385 self.sFile = sFile;
386
387class tdTestFileQuerySize(tdTestGuestCtrlBase):
388 """
389 Test for the file size query API call (fileQuerySize).
390 """
391 def __init__(self, sFile = "", sUser = None, sPassword = None):
392 tdTestGuestCtrlBase.__init__(self);
393 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
394 self.sFile = sFile;
395
396class tdTestFileReadWrite(tdTestGuestCtrlBase):
397 """
398 Tests reading from guest files.
399 """
400 def __init__(self, sFile = "", sUser = None, sPassword = None, sOpenMode = "r", # pylint: disable=too-many-arguments
401 sDisposition = "", sSharingMode = "", fCreationMode = 0, offFile = 0, cbToReadWrite = 0, abBuf = None):
402 tdTestGuestCtrlBase.__init__(self);
403 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
404 self.sFile = sFile;
405 self.sOpenMode = sOpenMode;
406 self.sDisposition = sDisposition;
407 self.sSharingMode = sSharingMode;
408 self.fCreationMode = fCreationMode;
409 self.offFile = offFile;
410 self.cbToReadWrite = cbToReadWrite;
411 self.abBuf = abBuf;
412
413 def getOpenAction(self):
414 """ Converts string disposition to open action enum. """
415 if self.sDisposition == 'oe': return vboxcon.FileOpenAction_OpenExisting;
416 if self.sDisposition == 'oc': return vboxcon.FileOpenAction_OpenOrCreate;
417 if self.sDisposition == 'ce': return vboxcon.FileOpenAction_CreateNew;
418 if self.sDisposition == 'ca': return vboxcon.FileOpenAction_CreateOrReplace;
419 if self.sDisposition == 'ot': return vboxcon.FileOpenAction_OpenExistingTruncated;
420 if self.sDisposition == 'oa': return vboxcon.FileOpenAction_AppendOrCreate;
421 raise base.GenError(self.sDisposition);
422
423 def getAccessMode(self):
424 """ Converts open mode to access mode enum. """
425 if self.sOpenMode == 'r': return vboxcon.FileAccessMode_ReadOnly;
426 if self.sOpenMode == 'w': return vboxcon.FileAccessMode_WriteOnly;
427 if self.sOpenMode == 'w+': return vboxcon.FileAccessMode_ReadWrite;
428 if self.sOpenMode == 'r+': return vboxcon.FileAccessMode_ReadWrite;
429 raise base.GenError(self.sOpenMode);
430
431 def getSharingMode(self):
432 """ Converts the sharing mode. """
433 return vboxcon.FileSharingMode_All;
434
435class tdTestSession(tdTestGuestCtrlBase):
436 """
437 Test the guest session handling.
438 """
439 def __init__(self, sUser = None, sPassword = None, sDomain = None, sSessionName = ""):
440 tdTestGuestCtrlBase.__init__(self);
441 self.sSessionName = sSessionName;
442 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain);
443
444 def getSessionCount(self, oVBoxMgr):
445 """
446 Helper for returning the number of currently
447 opened guest sessions of a VM.
448 """
449 if self.oTest.oGuest is None:
450 return 0;
451 try:
452 aoSession = oVBoxMgr.getArray(self.oTest.oGuest, 'sessions')
453 except:
454 reporter.errorXcpt('sSessionName: %s' % (self.sSessionName,));
455 return 0;
456 return len(aoSession);
457
458class tdTestSessionEx(tdTestGuestCtrlBase):
459 """
460 Test the guest session.
461 """
462 def __init__(self, aoSteps = None, enmUser = None):
463 tdTestGuestCtrlBase.__init__(self);
464 assert enmUser is None; # For later.
465 self.enmUser = enmUser;
466 self.aoSteps = aoSteps if aoSteps is not None else [];
467
468 def execute(self, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
469 """
470 Executes the test.
471 """
472 #
473 # Create a session.
474 #
475 assert self.enmUser is None; # For later.
476 self.oCreds = tdCtxCreds();
477 self.setEnvironment(oVmSession, oTxsSession, oTestVm);
478 reporter.log2('%s: %s steps' % (sMsgPrefix, len(self.aoSteps),));
479 fRc, oCurSession = self.createSession(sMsgPrefix);
480 if fRc is True:
481 #
482 # Execute the tests.
483 #
484 try:
485 fRc = self.executeSteps(oTstDrv, oCurSession, sMsgPrefix);
486 except:
487 fRc = reporter.errorXcpt('%s: Unexpected exception executing test steps' % (sMsgPrefix,));
488
489 #
490 # Close the session.
491 #
492 fRc2 = self.closeSession(True);
493 if fRc2 is False:
494 fRc = reporter.error('%s: Session could not be closed' % (sMsgPrefix,));
495 else:
496 fRc = reporter.error('%s: Session creation failed' % (sMsgPrefix,));
497 return fRc;
498
499 def executeSteps(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
500 """
501 Executes just the steps.
502 Returns True on success, False on test failure.
503 """
504 fRc = True;
505 for (i, oStep) in enumerate(self.aoSteps):
506 fRc2 = oStep.execute(oTstDrv, oGstCtrlSession, sMsgPrefix + ', step #%d' % i);
507 if fRc2 is True:
508 pass;
509 elif fRc2 is None:
510 reporter.log('%s: skipping remaining %d steps' % (sMsgPrefix, len(self.aoSteps) - i - 1,));
511 break;
512 else:
513 fRc = False;
514 return fRc;
515
516 @staticmethod
517 def executeListTestSessions(aoTests, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
518 """
519 Works thru a list of tdTestSessionEx object.
520 """
521 fRc = True;
522 for (i, oCurTest) in enumerate(aoTests):
523 try:
524 fRc2 = oCurTest.execute(oTstDrv, oVmSession, oTxsSession, oTestVm, '%s / %#d' % (sMsgPrefix, i,));
525 if fRc2 is not True:
526 fRc = False;
527 except:
528 fRc = reporter.errorXcpt('%s: Unexpected exception executing test #%d' % (sMsgPrefix, i ,));
529
530 return (fRc, oTxsSession);
531
532
533class tdSessionStepBase(object):
534 """
535 Base class for the guest control session test steps.
536 """
537
538 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
539 """
540 Executes the test step.
541
542 Returns True on success.
543 Returns False on failure (must be reported as error).
544 Returns None if to skip the remaining steps.
545 """
546 _ = oTstDrv;
547 _ = oGstCtrlSession;
548 return reporter.error('%s: Missing execute implementation: %s' % (sMsgPrefix, self,));
549
550
551class tdStepRequireMinimumApiVer(tdSessionStepBase):
552 """
553 Special test step which will cause executeSteps to skip the remaining step
554 if the VBox API is too old:
555 """
556 def __init__(self, fpMinApiVer):
557 self.fpMinApiVer = fpMinApiVer;
558
559 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
560 """ Returns None if API version is too old, otherwise True. """
561 if oTstDrv.fpApiVer >= self.fpMinApiVer:
562 return True;
563 _ = oGstCtrlSession;
564 _ = sMsgPrefix;
565 return None; # Special return value. Don't use elsewhere.
566
567
568#
569# Scheduling Environment Changes with the Guest Control Session.
570#
571
572class tdStepSessionSetEnv(tdSessionStepBase):
573 """
574 Guest session environment: schedule putenv
575 """
576 def __init__(self, sVar, sValue, hrcExpected = 0):
577 self.sVar = sVar;
578 self.sValue = sValue;
579 self.hrcExpected = hrcExpected;
580
581 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
582 """
583 Executes the step.
584 Returns True on success, False on test failure.
585 """
586 reporter.log2('tdStepSessionSetEnv: sVar=%s sValue=%s hrcExpected=%#x' % (self.sVar, self.sValue, self.hrcExpected,));
587 try:
588 if oTstDrv.fpApiVer >= 5.0:
589 oGstCtrlSession.environmentScheduleSet(self.sVar, self.sValue);
590 else:
591 oGstCtrlSession.environmentSet(self.sVar, self.sValue);
592 except vbox.ComException as oXcpt:
593 # Is this an expected failure?
594 if vbox.ComError.equal(oXcpt, self.hrcExpected):
595 return True;
596 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (setenv %s=%s)'
597 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
598 vbox.ComError.getXcptResult(oXcpt),
599 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
600 self.sVar, self.sValue,));
601 except:
602 return reporter.errorXcpt('%s: Unexpected exception in tdStepSessionSetEnv::execute (%s=%s)'
603 % (sMsgPrefix, self.sVar, self.sValue,));
604
605 # Should we succeed?
606 if self.hrcExpected != 0:
607 return reporter.error('%s: Expected hrcExpected=%#x, got S_OK (putenv %s=%s)'
608 % (sMsgPrefix, self.hrcExpected, self.sVar, self.sValue,));
609 return True;
610
611class tdStepSessionUnsetEnv(tdSessionStepBase):
612 """
613 Guest session environment: schedule unset.
614 """
615 def __init__(self, sVar, hrcExpected = 0):
616 self.sVar = sVar;
617 self.hrcExpected = hrcExpected;
618
619 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
620 """
621 Executes the step.
622 Returns True on success, False on test failure.
623 """
624 reporter.log2('tdStepSessionUnsetEnv: sVar=%s hrcExpected=%#x' % (self.sVar, self.hrcExpected,));
625 try:
626 if oTstDrv.fpApiVer >= 5.0:
627 oGstCtrlSession.environmentScheduleUnset(self.sVar);
628 else:
629 oGstCtrlSession.environmentUnset(self.sVar);
630 except vbox.ComException as oXcpt:
631 # Is this an expected failure?
632 if vbox.ComError.equal(oXcpt, self.hrcExpected):
633 return True;
634 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (unsetenv %s)'
635 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
636 vbox.ComError.getXcptResult(oXcpt),
637 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
638 self.sVar,));
639 except:
640 return reporter.errorXcpt('%s: Unexpected exception in tdStepSessionUnsetEnv::execute (%s)'
641 % (sMsgPrefix, self.sVar,));
642
643 # Should we succeed?
644 if self.hrcExpected != 0:
645 return reporter.error('%s: Expected hrcExpected=%#x, got S_OK (unsetenv %s)'
646 % (sMsgPrefix, self.hrcExpected, self.sVar,));
647 return True;
648
649class tdStepSessionBulkEnv(tdSessionStepBase):
650 """
651 Guest session environment: Bulk environment changes.
652 """
653 def __init__(self, asEnv = None, hrcExpected = 0):
654 self.asEnv = asEnv if asEnv is not None else [];
655 self.hrcExpected = hrcExpected;
656
657 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
658 """
659 Executes the step.
660 Returns True on success, False on test failure.
661 """
662 reporter.log2('tdStepSessionBulkEnv: asEnv=%s hrcExpected=%#x' % (self.asEnv, self.hrcExpected,));
663 try:
664 if oTstDrv.fpApiVer >= 5.0:
665 oTstDrv.oVBoxMgr.setArray(oGstCtrlSession, 'environmentChanges', self.asEnv);
666 else:
667 oTstDrv.oVBoxMgr.setArray(oGstCtrlSession, 'environment', self.asEnv);
668 except vbox.ComException as oXcpt:
669 # Is this an expected failure?
670 if vbox.ComError.equal(oXcpt, self.hrcExpected):
671 return True;
672 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (asEnv=%s)'
673 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
674 vbox.ComError.getXcptResult(oXcpt),
675 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
676 self.asEnv,));
677 except:
678 return reporter.errorXcpt('%s: Unexpected exception writing the environmentChanges property (asEnv=%s).'
679 % (sMsgPrefix, self.asEnv));
680 return True;
681
682class tdStepSessionClearEnv(tdStepSessionBulkEnv):
683 """
684 Guest session environment: clears the scheduled environment changes.
685 """
686 def __init__(self):
687 tdStepSessionBulkEnv.__init__(self);
688
689
690class tdStepSessionCheckEnv(tdSessionStepBase):
691 """
692 Check the currently scheduled environment changes of a guest control session.
693 """
694 def __init__(self, asEnv = None):
695 self.asEnv = asEnv if asEnv is not None else [];
696
697 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
698 """
699 Executes the step.
700 Returns True on success, False on test failure.
701 """
702 reporter.log2('tdStepSessionCheckEnv: asEnv=%s' % (self.asEnv,));
703
704 #
705 # Get the environment change list.
706 #
707 try:
708 if oTstDrv.fpApiVer >= 5.0:
709 asCurEnv = oTstDrv.oVBoxMgr.getArray(oGstCtrlSession, 'environmentChanges');
710 else:
711 asCurEnv = oTstDrv.oVBoxMgr.getArray(oGstCtrlSession, 'environment');
712 except:
713 return reporter.errorXcpt('%s: Unexpected exception reading the environmentChanges property.' % (sMsgPrefix,));
714
715 #
716 # Compare it with the expected one by trying to remove each expected value
717 # and the list anything unexpected.
718 #
719 fRc = True;
720 asCopy = list(asCurEnv); # just in case asCurEnv is immutable
721 for sExpected in self.asEnv:
722 try:
723 asCopy.remove(sExpected);
724 except:
725 fRc = reporter.error('%s: Expected "%s" to be in the resulting environment' % (sMsgPrefix, sExpected,));
726 for sUnexpected in asCopy:
727 fRc = reporter.error('%s: Unexpected "%s" in the resulting environment' % (sMsgPrefix, sUnexpected,));
728
729 if fRc is not True:
730 reporter.log2('%s: Current environment: %s' % (sMsgPrefix, asCurEnv));
731 return fRc;
732
733
734#
735# File system object statistics (i.e. stat()).
736#
737
738class tdStepStat(tdSessionStepBase):
739 """
740 Stats a file system object.
741 """
742 def __init__(self, sPath, hrcExpected = 0, fFound = True, fFollowLinks = True, enmType = None):
743 self.sPath = sPath;
744 self.hrcExpected = hrcExpected;
745 self.fFound = fFound;
746 self.fFollowLinks = fFollowLinks;
747 self.enmType = enmType if enmType is not None else vboxcon.FsObjType_File;
748 self.cbExactSize = None;
749 self.cbMinSize = None;
750
751 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
752 """
753 Execute the test step.
754 """
755 reporter.log2('tdStepStat: sPath=%s enmType=%s hrcExpected=%s fFound=%s fFollowLinks=%s'
756 % (self.sPath, self.enmType, self.hrcExpected, self.fFound, self.fFollowLinks,));
757
758 # Don't execute non-file tests on older VBox version.
759 if oTstDrv.fpApiVer >= 5.0 or self.enmType == vboxcon.FsObjType_File or not self.fFound:
760 #
761 # Call the API.
762 #
763 try:
764 if oTstDrv.fpApiVer >= 5.0:
765 oFsInfo = oGstCtrlSession.fsObjQueryInfo(self.sPath, self.fFollowLinks);
766 else:
767 oFsInfo = oGstCtrlSession.fileQueryInfo(self.sPath);
768 except vbox.ComException as oXcpt:
769 ## @todo: The error reporting in the API just plain sucks! Most of the errors are
770 ## VBOX_E_IPRT_ERROR and there seems to be no way to distinguish between
771 ## non-existing files/path and a lot of other errors. Fix API and test!
772 if not self.fFound:
773 return True;
774 if vbox.ComError.equal(oXcpt, self.hrcExpected): # Is this an expected failure?
775 return True;
776 return reporter.errorXcpt('%s: Unexpected exception for exiting path "%s" (enmType=%s, hrcExpected=%s):'
777 % (sMsgPrefix, self.sPath, self.enmType, self.hrcExpected,));
778 except:
779 return reporter.errorXcpt('%s: Unexpected exception in tdStepStat::execute (%s)'
780 % (sMsgPrefix, self.sPath,));
781 if oFsInfo is None:
782 return reporter.error('%s: "%s" got None instead of IFsObjInfo instance!' % (sMsgPrefix, self.sPath,));
783
784 #
785 # Check type expectations.
786 #
787 try:
788 enmType = oFsInfo.type;
789 except:
790 return reporter.errorXcpt('%s: Unexpected exception in reading "IFsObjInfo::type"' % (sMsgPrefix,));
791 if enmType != self.enmType:
792 return reporter.error('%s: "%s" has type %s, expected %s'
793 % (sMsgPrefix, self.sPath, enmType, self.enmType));
794
795 #
796 # Check size expectations.
797 # Note! This is unicode string here on windows, for some reason.
798 # long long mapping perhaps?
799 #
800 try:
801 cbObject = long(oFsInfo.objectSize);
802 except:
803 return reporter.errorXcpt('%s: Unexpected exception in reading "IFsObjInfo::objectSize"'
804 % (sMsgPrefix,));
805 if self.cbExactSize is not None \
806 and cbObject != self.cbExactSize:
807 return reporter.error('%s: "%s" has size %s bytes, expected %s bytes'
808 % (sMsgPrefix, self.sPath, cbObject, self.cbExactSize));
809 if self.cbMinSize is not None \
810 and cbObject < self.cbMinSize:
811 return reporter.error('%s: "%s" has size %s bytes, expected as least %s bytes'
812 % (sMsgPrefix, self.sPath, cbObject, self.cbMinSize));
813 return True;
814
815class tdStepStatDir(tdStepStat):
816 """ Checks for an existing directory. """
817 def __init__(self, sDirPath):
818 tdStepStat.__init__(self, sPath = sDirPath, enmType = vboxcon.FsObjType_Directory);
819
820class tdStepStatFile(tdStepStat):
821 """ Checks for an existing file """
822 def __init__(self, sFilePath):
823 tdStepStat.__init__(self, sPath = sFilePath, enmType = vboxcon.FsObjType_File);
824
825class tdStepStatFileSize(tdStepStat):
826 """ Checks for an existing file of a given expected size.. """
827 def __init__(self, sFilePath, cbExactSize = 0):
828 tdStepStat.__init__(self, sPath = sFilePath, enmType = vboxcon.FsObjType_File);
829 self.cbExactSize = cbExactSize;
830
831class tdStepStatFileNotFound(tdStepStat):
832 """ Checks for an existing directory. """
833 def __init__(self, sPath):
834 tdStepStat.__init__(self, sPath = sPath, fFound = False);
835
836class tdStepStatPathNotFound(tdStepStat):
837 """ Checks for an existing directory. """
838 def __init__(self, sPath):
839 tdStepStat.__init__(self, sPath = sPath, fFound = False);
840
841
842#
843#
844#
845
846class tdTestSessionFileRefs(tdTestGuestCtrlBase):
847 """
848 Tests session file (IGuestFile) reference counting.
849 """
850 def __init__(self, cRefs = 0):
851 tdTestGuestCtrlBase.__init__(self);
852 self.cRefs = cRefs;
853
854class tdTestSessionDirRefs(tdTestGuestCtrlBase):
855 """
856 Tests session directory (IGuestDirectory) reference counting.
857 """
858 def __init__(self, cRefs = 0):
859 tdTestGuestCtrlBase.__init__(self);
860 self.cRefs = cRefs;
861
862class tdTestSessionProcRefs(tdTestGuestCtrlBase):
863 """
864 Tests session process (IGuestProcess) reference counting.
865 """
866 def __init__(self, cRefs = 0):
867 tdTestGuestCtrlBase.__init__(self);
868 self.cRefs = cRefs;
869
870class tdTestUpdateAdditions(tdTestGuestCtrlBase):
871 """
872 Test updating the Guest Additions inside the guest.
873 """
874 def __init__(self, sSrc = "", asArgs = None, fFlags = None,
875 sUser = None, sPassword = None, sDomain = None):
876 tdTestGuestCtrlBase.__init__(self);
877 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain);
878 self.sSrc = sSrc;
879 self.asArgs = asArgs;
880 self.fFlags = fFlags;
881
882class tdTestResult(object):
883 """
884 Base class for test results.
885 """
886 def __init__(self, fRc = False):
887 ## The overall test result.
888 self.fRc = fRc;
889
890class tdTestResultFailure(tdTestResult):
891 """
892 Base class for test results.
893 """
894 def __init__(self):
895 tdTestResult.__init__(self, fRc = False);
896
897class tdTestResultSuccess(tdTestResult):
898 """
899 Base class for test results.
900 """
901 def __init__(self):
902 tdTestResult.__init__(self, fRc = True);
903
904class tdTestResultDirRead(tdTestResult):
905 """
906 Test result for reading guest directories.
907 """
908 def __init__(self, fRc = False, cFiles = 0, cDirs = 0, cOthers = None):
909 tdTestResult.__init__(self, fRc = fRc);
910 self.cFiles = cFiles;
911 self.cDirs = cDirs;
912 self.cOthers = cOthers;
913
914class tdTestResultExec(tdTestResult):
915 """
916 Holds a guest process execution test result,
917 including the exit code, status + fFlags.
918 """
919 def __init__(self, fRc = False, uExitStatus = 500, iExitCode = 0, sBuf = None, cbBuf = 0, cbStdOut = None, cbStdErr = None):
920 tdTestResult.__init__(self);
921 ## The overall test result.
922 self.fRc = fRc;
923 ## Process exit stuff.
924 self.uExitStatus = uExitStatus;
925 self.iExitCode = iExitCode;
926 ## Desired buffer length returned back from stdout/stderr.
927 self.cbBuf = cbBuf;
928 ## Desired buffer result from stdout/stderr. Use with caution!
929 self.sBuf = sBuf;
930 self.cbStdOut = cbStdOut;
931 self.cbStdErr = cbStdErr;
932
933class tdTestResultFileStat(tdTestResult):
934 """
935 Test result for stat'ing guest files.
936 """
937 def __init__(self, fRc = False,
938 cbSize = 0, eFileType = 0):
939 tdTestResult.__init__(self, fRc = fRc);
940 self.cbSize = cbSize;
941 self.eFileType = eFileType;
942 ## @todo Add more information.
943
944class tdTestResultFileReadWrite(tdTestResult):
945 """
946 Test result for reading + writing guest directories.
947 """
948 def __init__(self, fRc = False,
949 cbProcessed = 0, offFile = 0, abBuf = None):
950 tdTestResult.__init__(self, fRc = fRc);
951 self.cbProcessed = cbProcessed;
952 self.offFile = offFile;
953 self.abBuf = abBuf;
954
955class tdTestResultSession(tdTestResult):
956 """
957 Test result for guest session counts.
958 """
959 def __init__(self, fRc = False, cNumSessions = 0):
960 tdTestResult.__init__(self, fRc = fRc);
961 self.cNumSessions = cNumSessions;
962
963
964class SubTstDrvAddGuestCtrl(base.SubTestDriverBase):
965 """
966 Sub-test driver for executing guest control (VBoxService, IGuest) tests.
967 """
968
969 def __init__(self, oTstDrv):
970 base.SubTestDriverBase.__init__(self, oTstDrv, 'add-guest-ctrl', 'Guest Control');
971
972 ## @todo base.TestBase.
973 self.asTestsDef = [
974 'session_basic', 'session_env', 'session_file_ref', 'session_dir_ref', 'session_proc_ref', 'session_reboot',
975 'exec_basic', 'exec_timeout',
976 'dir_create', 'dir_create_temp', 'dir_read',
977 'file_remove', 'file_stat', 'file_read', 'file_write',
978 'copy_to', 'copy_from',
979 'update_additions'
980 ];
981 self.asTests = self.asTestsDef;
982 self.fSkipKnownBugs = False;
983 self.oTestFiles = None # type: vboxtestfileset.TestFileSet
984
985 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
986 if asArgs[iArg] == '--add-guest-ctrl-tests':
987 iArg += 1;
988 iNext = self.oTstDrv.requireMoreArgs(1, asArgs, iArg);
989 if asArgs[iArg] == 'all': # Nice for debugging scripts.
990 self.asTests = self.asTestsDef;
991 else:
992 self.asTests = asArgs[iArg].split(':');
993 for s in self.asTests:
994 if s not in self.asTestsDef:
995 raise base.InvalidOption('The "--add-guest-ctrl-tests" value "%s" is not valid; valid values are: %s'
996 % (s, ' '.join(self.asTestsDef)));
997 return iNext;
998 if asArgs[iArg] == '--add-guest-ctrl-skip-known-bugs':
999 self.fSkipKnownBugs = True;
1000 return iArg + 1;
1001 if asArgs[iArg] == '--no-add-guest-ctrl-skip-known-bugs':
1002 self.fSkipKnownBugs = False;
1003 return iArg + 1;
1004 return iArg;
1005
1006 def showUsage(self):
1007 base.SubTestDriverBase.showUsage(self);
1008 reporter.log(' --add-guest-ctrl-tests <s1[:s2[:]]>');
1009 reporter.log(' Default: %s (all)' % (':'.join(self.asTestsDef)));
1010 reporter.log(' --add-guest-ctrl-skip-known-bugs');
1011 reporter.log(' Skips known bugs. Default: --no-add-guest-ctrl-skip-known-bugs');
1012 return True;
1013
1014 def testIt(self, oTestVm, oSession, oTxsSession):
1015 """
1016 Executes the test.
1017
1018 Returns fRc, oTxsSession. The latter may have changed.
1019 """
1020 reporter.log("Active tests: %s" % (self.asTests,));
1021
1022 # The tests. Must-succeed tests should be first.
1023 atTests = [
1024 ( True, self.prepareGuestForTesting, None, 'Preparations',),
1025 #( True, self.testGuestCtrlSession, 'session_basic', 'Session Basics',),
1026 #( True, self.testGuestCtrlExec, 'exec_basic', 'Execution',),
1027 #( False, self.testGuestCtrlExecTimeout, 'exec_timeout', 'Execution Timeouts',),
1028 #( False, self.testGuestCtrlSessionEnvironment, 'session_env', 'Session Environment',),
1029 #( False, self.testGuestCtrlSessionFileRefs, 'session_file_ref', 'Session File References',),
1030 ##( False, self.testGuestCtrlSessionDirRefs, 'session_dir_ref', 'Session Directory References',),
1031 #( False, self.testGuestCtrlSessionProcRefs, 'session_proc_ref', 'Session Process References',),
1032 #( False, self.testGuestCtrlDirCreate, 'dir_create', 'Creating directories',),
1033 #( False, self.testGuestCtrlDirCreateTemp, 'dir_create_temp', 'Creating temporary directories',),
1034 #( False, self.testGuestCtrlDirRead, 'dir_read', 'Reading directories',),
1035 ( False, self.testGuestCtrlCopyTo, 'copy_to', 'Copy to guest',),
1036 #( False, self.testGuestCtrlCopyFrom, 'copy_from', 'Copy from guest',),
1037 #( False, self.testGuestCtrlFileStat, 'file_stat', 'Querying file information (stat)',),
1038 #( False, self.testGuestCtrlFileRead, 'file_read', 'File read',),
1039 #( False, self.testGuestCtrlFileWrite, 'file_write', 'File write',),
1040 #( False, self.testGuestCtrlFileRemove, 'file_remove', 'Removing files',), # Destroys prepped files.
1041 #( False, self.testGuestCtrlSessionReboot, 'session_reboot', 'Session w/ Guest Reboot',), # May zap /tmp.
1042 #( False, self.testGuestCtrlUpdateAdditions, 'update_additions', 'Updating Guest Additions',),
1043 ];
1044
1045 fRc = True;
1046 for fMustSucceed, fnHandler, sShortNm, sTestNm in atTests:
1047 reporter.testStart(sTestNm);
1048
1049 if sShortNm is None or sShortNm in self.asTests:
1050 # Returns (fRc, oTxsSession, oSession) - but only the first one is mandatory.
1051 aoResult = fnHandler(oSession, oTxsSession, oTestVm);
1052 if aoResult is None or isinstance(aoResult, bool):
1053 fRcTest = aoResult;
1054 else:
1055 fRcTest = aoResult[0];
1056 if len(aoResult) > 1:
1057 oTxsSession = aoResult[1];
1058 if len(aoResult) > 2:
1059 oSession = aoResult[2];
1060 assert len(aoResult) == 3;
1061 else:
1062 fRcTest = None;
1063
1064 if fRcTest is False and reporter.testErrorCount() == 0:
1065 fRcTest = reporter.error('Buggy test! Returned False w/o logging the error!');
1066 if reporter.testDone(fRcTest is None)[1] != 0:
1067 fRcTest = False;
1068 fRc = False;
1069
1070 # Stop execution if this is a must-succeed test and it failed.
1071 if fRcTest is False and fMustSucceed is True:
1072 reporter.log('Skipping any remaining tests since the previous one failed.');
1073 break;
1074
1075 return (fRc, oTxsSession);
1076
1077 #
1078 # Guest locations.
1079 #
1080
1081 @staticmethod
1082 def getGuestTempDir(oTestVm):
1083 """
1084 Helper for finding a temporary directory in the test VM.
1085
1086 Note! It may be necessary to create it!
1087 """
1088 if oTestVm.isWindows():
1089 return "C:\\Temp";
1090 if oTestVm.isOS2():
1091 return "C:\\Temp";
1092 return '/var/tmp';
1093
1094 @staticmethod
1095 def getGuestSystemDir(oTestVm):
1096 """
1097 Helper for finding a system directory in the test VM that we can play around with.
1098
1099 On Windows this is always the System32 directory, so this function can be used as
1100 basis for locating other files in or under that directory.
1101 """
1102 if oTestVm.isWindows():
1103 if oTestVm.sKind in ['WindowsNT4', 'WindowsNT3x',]:
1104 return 'C:\\Winnt\\System32';
1105 return 'C:\\Windows\\System32';
1106 if oTestVm.isOS2():
1107 return 'C:\\OS2\\DLL';
1108 return "/bin";
1109
1110 @staticmethod
1111 def getGuestSystemShell(oTestVm):
1112 """
1113 Helper for finding the default system shell in the test VM.
1114 """
1115 if oTestVm.isWindows():
1116 return SubTstDrvAddGuestCtrl.getGuestSystemDir(oTestVm) + '\\cmd.exe';
1117 if oTestVm.isOS2():
1118 return SubTstDrvAddGuestCtrl.getGuestSystemDir(oTestVm) + '\\..\\CMD.EXE';
1119 return "/bin/sh";
1120
1121 @staticmethod
1122 def getGuestSystemFileForReading(oTestVm):
1123 """
1124 Helper for finding a file in the test VM that we can read.
1125 """
1126 if oTestVm.isWindows():
1127 return SubTstDrvAddGuestCtrl.getGuestSystemDir(oTestVm) + '\\ntdll.dll';
1128 if oTestVm.isOS2():
1129 return SubTstDrvAddGuestCtrl.getGuestSystemDir(oTestVm) + '\\DOSCALL1.DLL';
1130 return "/bin/sh";
1131
1132 #
1133 # Guest test files.
1134 #
1135
1136 def prepareGuestForTesting(self, oSession, oTxsSession, oTestVm):
1137 """
1138 Prepares the VM for testing, uploading a bunch of files and stuff via TXS.
1139 Returns success indicator.
1140 """
1141 _ = oSession;
1142
1143 # Make sure the temporary directory exists.
1144 for sDir in [self.getGuestTempDir(oTestVm), ]:
1145 if oTxsSession.syncMkDirPath(sDir, 0o777) is not True:
1146 return reporter.error('Failed to create directory "%s"!' % (sDir,));
1147
1148 # Generate and upload some random files and dirs to the guest:
1149 self.oTestFiles = vboxtestfileset.TestFileSet(oTestVm, self.getGuestTempDir(oTestVm), 'addgst-1');
1150 return self.oTestFiles.upload(oTxsSession, self.oTstDrv);
1151
1152
1153 #
1154 # gctrlXxxx stuff.
1155 #
1156
1157 def gctrlCopyFileFrom(self, oGuestSession, oTest, fExpected):
1158 """
1159 Helper function to copy a single file from the guest to the host.
1160 """
1161 #
1162 # Do the copying.
1163 #
1164 reporter.log2('Copying guest file "%s" to host "%s"' % (oTest.sSrc, oTest.sDst));
1165 try:
1166 if self.oTstDrv.fpApiVer >= 5.0:
1167 oCurProgress = oGuestSession.fileCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.fFlags);
1168 else:
1169 oCurProgress = oGuestSession.copyFrom(oTest.sSrc, oTest.sDst, oTest.fFlags);
1170 except:
1171 reporter.maybeErrXcpt(fExpected, 'Copy from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1172 return False;
1173 if oCurProgress is None:
1174 return reporter.error('No progress object returned');
1175 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlFileCopyFrom");
1176 oProgress.wait();
1177 if not oProgress.isSuccess():
1178 oProgress.logResult(fIgnoreErrors = not fExpected);
1179 return False;
1180
1181 #
1182 # Check the result if we can.
1183 #
1184 if oTest.oSrc:
1185 assert isinstance(oTest.oSrc, testfileset.TestFile);
1186 sDst = oTest.sDst;
1187 if os.path.isdir(sDst):
1188 sDst = os.path.join(sDst, oTest.oSrc.sName);
1189 try:
1190 oFile = open(sDst, 'rb');
1191 except:
1192 return reporter.errorXcpt('open(%s) failed during verfication' % (sDst,));
1193 fEqual = oTest.oSrc.equalFile(oFile);
1194 oFile.close();
1195 if not fEqual:
1196 return reporter.error('Content differs for "%s"' % (sDst,));
1197
1198 return True;
1199
1200 def __compareTestDir(self, oDir, sHostPath): # type: (testfileset.TestDir, str) -> bool
1201 """
1202 Recursively compare the content of oDir and sHostPath.
1203
1204 Returns True on success, False + error logging on failure.
1205
1206 Note! This ASSUMES that nothing else was copied to sHostPath!
1207 """
1208 #
1209 # First check out all the entries and files in the directory.
1210 #
1211 dLeftUpper = dict(oDir.dChildrenUpper);
1212 try:
1213 asEntries = os.listdir(sHostPath);
1214 except:
1215 return reporter.errorXcpt('os.listdir(%s) failed' % (sHostPath,));
1216
1217 fRc = True;
1218 for sEntry in asEntries:
1219 sEntryUpper = sEntry.upper();
1220 if sEntryUpper not in dLeftUpper:
1221 fRc = reporter.error('Unexpected entry "%s" in "%s"' % (sEntry, sHostPath,));
1222 else:
1223 oFsObj = dLeftUpper[sEntryUpper];
1224 del dLeftUpper[sEntryUpper];
1225
1226 if isinstance(oFsObj, testfileset.TestFile):
1227 sFilePath = os.path.join(sHostPath, oFsObj.sName);
1228 try:
1229 oFile = open(sFilePath, 'rb');
1230 except:
1231 fRc = reporter.errorXcpt('open(%s) failed during verfication' % (sFilePath,));
1232 else:
1233 fEqual = oFsObj.equalFile(oFile);
1234 oFile.close();
1235 if not fEqual:
1236 fRc = reporter.error('Content differs for "%s"' % (sFilePath,));
1237
1238 # List missing entries:
1239 for sKey in dLeftUpper:
1240 oEntry = dLeftUpper[sKey];
1241 fRc = reporter.error('%s: Missing %s "%s" (src path: %s)'
1242 % (sHostPath, oEntry.sName,
1243 'file' if isinstance(oEntry, testfileset.TestFile) else 'directory', oEntry.sPath));
1244
1245 #
1246 # Recurse into subdirectories.
1247 #
1248 for oFsObj in oDir.aoChildren:
1249 if isinstance(oFsObj, testfileset.TestDir):
1250 fRc = self.__compareTestDir(oFsObj, os.path.join(sHostPath, oFsObj.sName)) and fRc;
1251 return fRc;
1252
1253 def gctrlCopyDirFrom(self, oGuestSession, oTest, fExpected):
1254 """
1255 Helper function to copy a directory from the guest to the host.
1256 """
1257 #
1258 # Do the copying.
1259 #
1260 reporter.log2('Copying guest dir "%s" to host "%s"' % (oTest.sSrc, oTest.sDst));
1261 try:
1262 oCurProgress = oGuestSession.directoryCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.fFlags);
1263 except:
1264 reporter.maybeErrXcpt(fExpected, 'Copy dir from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1265 return False;
1266 if oCurProgress is None:
1267 return reporter.error('No progress object returned');
1268
1269 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlDirCopyFrom");
1270 oProgress.wait();
1271 if not oProgress.isSuccess():
1272 oProgress.logResult(fIgnoreErrors = not fExpected);
1273 return False;
1274
1275 #
1276 # Check the result if we can.
1277 #
1278 if oTest.oSrc:
1279 assert isinstance(oTest.oSrc, testfileset.TestDir);
1280 sDst = oTest.sDst;
1281 if oTest.fIntoDst:
1282 return self.__compareTestDir(oTest.oSrc, os.path.join(sDst, oTest.oSrc.sName));
1283 oDummy = testfileset.TestDir(None, 'dummy');
1284 oDummy.aoChildren = [oTest.oSrc,]
1285 oDummy.dChildrenUpper = { oTest.oSrc.sName.upper(): oTest.oSrc, };
1286 return self.__compareTestDir(oDummy, sDst);
1287 return True;
1288
1289 def gctrlCopyFileTo(self, oGuestSession, sSrc, sDst, fFlags, fIsError):
1290 """
1291 Helper function to copy a single file from the host to the guest.
1292 """
1293 reporter.log2('Copying host file "%s" to guest "%s" (flags %s)' % (sSrc, sDst, fFlags));
1294 try:
1295 if self.oTstDrv.fpApiVer >= 5.0:
1296 oCurProgress = oGuestSession.fileCopyToGuest(sSrc, sDst, fFlags);
1297 else:
1298 oCurProgress = oGuestSession.copyTo(sSrc, sDst, fFlags);
1299 except:
1300 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1301 return False;
1302
1303 if oCurProgress is None:
1304 return reporter.error('No progress object returned');
1305 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1306
1307 try:
1308 oProgress.wait();
1309 if not oProgress.isSuccess():
1310 oProgress.logResult(fIgnoreErrors = not fIsError);
1311 return False;
1312 except:
1313 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1314 return False;
1315 return True;
1316
1317 def gctrlCopyDirTo(self, oGuestSession, sSrc, sDst, fFlags, fIsError):
1318 """
1319 Helper function to copy a directory tree from the host to the guest.
1320 """
1321 reporter.log2('Copying host directory "%s" to guest "%s" (flags %s)' % (sSrc, sDst, fFlags));
1322 try:
1323 oCurProgress = oGuestSession.directoryCopyToGuest(sSrc, sDst, fFlags);
1324 except:
1325 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1326 return False;
1327
1328 if oCurProgress is None:
1329 return reporter.error('No progress object returned');
1330 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1331
1332 try:
1333 oProgress.wait();
1334 if not oProgress.isSuccess():
1335 oProgress.logResult(fIgnoreErrors = not fIsError);
1336 return False;
1337 except:
1338 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1339 return False;
1340 return True;
1341
1342 def gctrlCreateDir(self, oTest, oRes, oGuestSession):
1343 """
1344 Helper function to create a guest directory specified in the current test.
1345 """
1346 reporter.log2('Creating directory "%s"' % (oTest.sDirectory,));
1347 try:
1348 oGuestSession.directoryCreate(oTest.sDirectory, oTest.fMode, oTest.fFlags);
1349 except:
1350 reporter.maybeErrXcpt(oRes.fRc, 'Failed to create "%s" fMode=%o fFlags=%s'
1351 % (oTest.sDirectory, oTest.fMode, oTest.fFlags,));
1352 return not oRes.fRc;
1353 if oRes.fRc is not True:
1354 return reporter.error('Did not expect to create directory "%s"!' % (oTest.sDirectory,));
1355
1356 # Check if the directory now exists.
1357 try:
1358 if self.oTstDrv.fpApiVer >= 5.0:
1359 fDirExists = oGuestSession.directoryExists(oTest.sDirectory, False);
1360 else:
1361 fDirExists = oGuestSession.directoryExists(oTest.sDirectory);
1362 except:
1363 return reporter.errorXcpt('directoryExists failed on "%s"!' % (oTest.sDirectory,));
1364 if not fDirExists:
1365 return reporter.errorXcpt('directoryExists returned False on "%s" after directoryCreate succeeded!'
1366 % (oTest.sDirectory,));
1367 return True;
1368
1369 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, sSubDir = None):
1370 """
1371 Helper function to recursively read a guest directory tree specified in the current test.
1372 """
1373 sDir = oTest.sDirectory;
1374 sFilter = oTest.sFilter;
1375 fFlags = oTest.fFlags;
1376 oTestVm = oTest.oCreds.oTestVm;
1377 sCurDir = oTestVm.pathJoin(sDir, sSubDir) if sSubDir else sDir;
1378
1379 fRc = True; # Be optimistic.
1380 cDirs = 0; # Number of directories read.
1381 cFiles = 0; # Number of files read.
1382 cOthers = 0; # Other files.
1383
1384 ##
1385 ## @todo r=bird: Unlike fileOpen, directoryOpen will not fail if the directory does not exist.
1386 ## This is of course a bug in the implementation, as it is documented to return
1387 ## VBOX_E_OBJECT_NOT_FOUND or VBOX_E_IPRT_ERROR!
1388 ##
1389
1390 # Open the directory:
1391 #reporter.log2('Directory="%s", filter="%s", fFlags="%s"' % (sCurDir, sFilter, fFlags));
1392 try:
1393 oCurDir = oGuestSession.directoryOpen(sCurDir, sFilter, fFlags);
1394 except:
1395 reporter.maybeErrXcpt(fIsError, 'sCurDir=%s sFilter=%s fFlags=%s' % (sCurDir, sFilter, fFlags,))
1396 return (False, 0, 0, 0);
1397
1398 # Read the directory.
1399 while fRc is True:
1400 try:
1401 oFsObjInfo = oCurDir.read();
1402 except Exception as oXcpt:
1403 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1404 ##
1405 ## @todo r=bird: Change this to reporter.errorXcpt() once directoryOpen() starts
1406 ## working the way it is documented.
1407 ##
1408 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,)); # See above why 'maybe'.
1409 fRc = False;
1410 #else: reporter.log2('\tNo more directory entries for "%s"' % (sCurDir,));
1411 break;
1412
1413 try:
1414 sName = oFsObjInfo.name;
1415 eType = oFsObjInfo.type;
1416 except:
1417 fRc = reporter.errorXcpt();
1418 break;
1419
1420 if sName in ('.', '..', ):
1421 if eType != vboxcon.FsObjType_Directory:
1422 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1423 % (sName, eType, vboxcon.FsObjType_Directory));
1424 elif eType == vboxcon.FsObjType_Directory:
1425 #reporter.log2(' Directory "%s"' % oFsObjInfo.name);
1426 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError,
1427 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName);
1428 fRc = aSubResult[0];
1429 cDirs += aSubResult[1] + 1;
1430 cFiles += aSubResult[2];
1431 cOthers += aSubResult[3];
1432 elif eType is vboxcon.FsObjType_File:
1433 #reporter.log2(' File "%s"' % oFsObjInfo.name);
1434 cFiles += 1;
1435 elif eType is vboxcon.FsObjType_Symlink:
1436 #reporter.log2(' Symlink "%s" -- not tested yet' % oFsObjInfo.name);
1437 cOthers += 1;
1438 elif oTestVm.isWindows() \
1439 or oTestVm.isOS2() \
1440 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock,
1441 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut):
1442 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' %
1443 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,));
1444 else:
1445 cOthers += 1;
1446
1447 # Close the directory
1448 try:
1449 oCurDir.close();
1450 except:
1451 fRc = reporter.errorXcpt('sCurDir=%s' % (sCurDir));
1452
1453 return (fRc, cDirs, cFiles, cOthers);
1454
1455 def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (testfileset.TestDir) -> bool
1456 """
1457 Helper function to recursively read a guest directory tree specified in the current test.
1458 """
1459
1460 #
1461 # Process the directory.
1462 #
1463
1464 # Open the directory:
1465 try:
1466 oCurDir = oGuestSession.directoryOpen(oDir.sPath, '', None);
1467 except:
1468 return reporter.errorXcpt('sPath=%s' % (oDir.sPath,));
1469
1470 # Read the directory.
1471 dLeftUpper = dict(oDir.dChildrenUpper);
1472 cDot = 0;
1473 cDotDot = 0;
1474 fRc = True;
1475 while True:
1476 try:
1477 oFsObjInfo = oCurDir.read();
1478 except Exception as oXcpt:
1479 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1480 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath,));
1481 break;
1482
1483 try:
1484 sName = oFsObjInfo.name;
1485 eType = oFsObjInfo.type;
1486 cbFile = oFsObjInfo.objectSize;
1487 ## @todo check further attributes.
1488 except:
1489 fRc = reporter.errorXcpt();
1490 break;
1491
1492 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment:
1493 if sName in ('.', '..', ):
1494 if eType != vboxcon.FsObjType_Directory:
1495 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1496 % (sName, eType, vboxcon.FsObjType_Directory));
1497 if sName == '.': cDot += 1;
1498 else: cDotDot += 1;
1499 else:
1500 # Find the child and remove it from the dictionary.
1501 sNameUpper = sName.upper();
1502 oFsObj = dLeftUpper.get(sNameUpper);
1503 if oFsObj is None:
1504 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!'
1505 % (sName, oDir.sPath, eType, cbFile,));
1506 else:
1507 del dLeftUpper[sNameUpper];
1508
1509 # Check type
1510 if isinstance(oFsObj, testfileset.TestDir):
1511 if eType != vboxcon.FsObjType_Directory:
1512 fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
1513 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
1514 elif isinstance(oFsObj, testfileset.TestFile):
1515 if eType != vboxcon.FsObjType_File:
1516 fRc = reporter.error('%s: expected file (%d), got eType=%d!'
1517 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,));
1518 else:
1519 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),));
1520
1521 # Check the name.
1522 if oFsObj.sName != sName:
1523 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,));
1524
1525 # Check the size if a file.
1526 if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent:
1527 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,));
1528
1529 ## @todo check timestamps and attributes.
1530
1531 # Close the directory
1532 try:
1533 oCurDir.close();
1534 except:
1535 fRc = reporter.errorXcpt('oDir.sPath=%s' % (oDir.sPath,));
1536
1537 # Any files left over?
1538 for sKey in dLeftUpper:
1539 oFsObj = dLeftUpper[sKey];
1540 fRc = reporter.error('%s: Was not returned! (%s)' % (oFsObj.sPath, type(oFsObj),));
1541
1542 # Check the dot and dot-dot counts.
1543 if cDot != 1:
1544 fRc = reporter.error('%s: Found %s "." entries, expected exactly 1!' % (oDir.sPath, cDot,));
1545 if cDotDot != 1:
1546 fRc = reporter.error('%s: Found %s ".." entries, expected exactly 1!' % (oDir.sPath, cDotDot,));
1547
1548 #
1549 # Recurse into subdirectories using info from oDir.
1550 #
1551 for oFsObj in oDir.aoChildren:
1552 if isinstance(oFsObj, testfileset.TestDir):
1553 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc;
1554
1555 return fRc;
1556
1557 def gctrlExecDoTest(self, i, oTest, oRes, oGuestSession):
1558 """
1559 Wrapper function around gctrlExecute to provide more sanity checking
1560 when needed in actual execution tests.
1561 """
1562 reporter.log('Testing #%d, cmd="%s" ...' % (i, oTest.sCmd));
1563 fRcExec = self.gctrlExecute(oTest, oGuestSession, oRes.fRc);
1564 if fRcExec == oRes.fRc:
1565 fRc = True;
1566 if fRcExec is True:
1567 # Compare exit status / code on successful process execution.
1568 if oTest.uExitStatus != oRes.uExitStatus \
1569 or oTest.iExitCode != oRes.iExitCode:
1570 fRc = reporter.error('Test #%d (%s) failed: Got exit status + code %d,%d, expected %d,%d'
1571 % (i, oTest.asArgs, oTest.uExitStatus, oTest.iExitCode,
1572 oRes.uExitStatus, oRes.iExitCode));
1573
1574 # Compare test / result buffers on successful process execution.
1575 if oTest.sBuf is not None and oRes.sBuf is not None:
1576 if not utils.areBytesEqual(oTest.sBuf, oRes.sBuf):
1577 fRc = reporter.error('Test #%d (%s) failed: Got buffer\n%s (%d bytes), expected\n%s (%d bytes)'
1578 % (i, oTest.asArgs,
1579 map(hex, map(ord, oTest.sBuf)), len(oTest.sBuf),
1580 map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf)));
1581 reporter.log2('Test #%d passed: Buffers match (%d bytes)' % (i, len(oRes.sBuf)));
1582 elif oRes.sBuf and not oTest.sBuf:
1583 fRc = reporter.error('Test #%d (%s) failed: Got no buffer data, expected\n%s (%dbytes)' %
1584 (i, oTest.asArgs, map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf),));
1585
1586 if oRes.cbStdOut is not None and oRes.cbStdOut != oTest.cbStdOut:
1587 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stdout data, expected %d'
1588 % (i, oTest.asArgs, oTest.cbStdOut, oRes.cbStdOut));
1589 if oRes.cbStdErr is not None and oRes.cbStdErr != oTest.cbStdErr:
1590 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stderr data, expected %d'
1591 % (i, oTest.asArgs, oTest.cbStdErr, oRes.cbStdErr));
1592 else:
1593 fRc = reporter.error('Test #%d (%s) failed: Got %s, expected %s' % (i, oTest.asArgs, fRcExec, oRes.fRc));
1594 return fRc;
1595
1596 def gctrlExecute(self, oTest, oGuestSession, fIsError):
1597 """
1598 Helper function to execute a program on a guest, specified in the current test.
1599
1600 Note! This weirdo returns results (process exitcode and status) in oTest.
1601 """
1602 fRc = True; # Be optimistic.
1603
1604 # Reset the weird result stuff:
1605 oTest.cbStdOut = 0;
1606 oTest.cbStdErr = 0;
1607 oTest.sBuf = '';
1608 oTest.uExitStatus = 0;
1609 oTest.iExitCode = 0;
1610
1611 ## @todo Compare execution timeouts!
1612 #tsStart = base.timestampMilli();
1613
1614 try:
1615 reporter.log2('Using session user=%s, sDomain=%s, name=%s, timeout=%d'
1616 % (oGuestSession.user, oGuestSession.domain, oGuestSession.name, oGuestSession.timeout,));
1617 except:
1618 return reporter.errorXcpt();
1619
1620 #
1621 # Start the process:
1622 #
1623 reporter.log2('Executing sCmd=%s, fFlags=%s, timeoutMS=%d, asArgs=%s, asEnv=%s'
1624 % (oTest.sCmd, oTest.fFlags, oTest.timeoutMS, oTest.asArgs, oTest.aEnv,));
1625 try:
1626 oProcess = oGuestSession.processCreate(oTest.sCmd,
1627 oTest.asArgs if self.oTstDrv.fpApiVer >= 5.0 else oTest.asArgs[1:],
1628 oTest.aEnv, oTest.fFlags, oTest.timeoutMS);
1629 except:
1630 reporter.maybeErrXcpt(fIsError, 'asArgs=%s' % (oTest.asArgs,));
1631 return False;
1632 if oProcess is None:
1633 return reporter.error('oProcess is None! (%s)' % (oTest.asArgs,));
1634
1635 #time.sleep(5); # try this if you want to see races here.
1636
1637 # Wait for the process to start properly:
1638 reporter.log2('Process start requested, waiting for start (%dms) ...' % (oTest.timeoutMS,));
1639 iPid = -1;
1640 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Start, ];
1641 try:
1642 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
1643 except:
1644 reporter.maybeErrXcpt(fIsError, 'waitforArray failed for asArgs=%s' % (oTest.asArgs,));
1645 fRc = False;
1646 else:
1647 try:
1648 eStatus = oProcess.status;
1649 iPid = oProcess.PID;
1650 except:
1651 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1652 else:
1653 reporter.log2('Wait result returned: %d, current process status is: %d' % (eWaitResult, eStatus,));
1654
1655 #
1656 # Wait for the process to run to completion if necessary.
1657 #
1658 # Note! The above eWaitResult return value can be ignored as it will
1659 # (mostly) reflect the process status anyway.
1660 #
1661 if eStatus == vboxcon.ProcessStatus_Started:
1662
1663 # What to wait for:
1664 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate, ];
1665 if vboxcon.ProcessCreateFlag_WaitForStdOut in oTest.fFlags:
1666 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdOut);
1667 if vboxcon.ProcessCreateFlag_WaitForStdErr in oTest.fFlags:
1668 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdErr);
1669 ## @todo Add vboxcon.ProcessWaitForFlag_StdIn.
1670
1671 reporter.log2('Process (PID %d) started, waiting for termination (%dms), aeWaitFor=%s ...'
1672 % (iPid, oTest.timeoutMS, aeWaitFor));
1673 acbFdOut = [0,0,0];
1674 while True:
1675 try:
1676 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
1677 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
1678 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
1679 try: oProcess.close();
1680 except: pass;
1681 break;
1682 except:
1683 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1684 break;
1685 reporter.log2('Wait returned: %d' % (eWaitResult,));
1686
1687 # Process output:
1688 for eFdResult, iFd, sFdNm in [ (vboxcon.ProcessWaitResult_StdOut, 1, 'stdout'),
1689 (vboxcon.ProcessWaitResult_StdErr, 2, 'stderr'), ]:
1690 if eWaitResult in (eFdResult, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
1691 reporter.log2('Reading %s ...' % (sFdNm,));
1692 try:
1693 abBuf = oProcess.Read(1, 64 * 1024, oTest.timeoutMS);
1694 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
1695 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
1696 try: oProcess.close();
1697 except: pass;
1698 except:
1699 pass; ## @todo test for timeouts and fail on anything else!
1700 else:
1701 if abBuf:
1702 reporter.log2('Process (PID %d) got %d bytes of %s data' % (iPid, len(abBuf), sFdNm,));
1703 acbFdOut[iFd] += len(abBuf);
1704 oTest.sBuf = abBuf; ## @todo Figure out how to uniform + append!
1705
1706 ## Process input (todo):
1707 #if eWaitResult in (vboxcon.ProcessWaitResult_StdIn, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
1708 # reporter.log2('Process (PID %d) needs stdin data' % (iPid,));
1709
1710 # Termination or error?
1711 if eWaitResult in (vboxcon.ProcessWaitResult_Terminate,
1712 vboxcon.ProcessWaitResult_Error,
1713 vboxcon.ProcessWaitResult_Timeout,):
1714 try: eStatus = oProcess.status;
1715 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1716 reporter.log2('Process (PID %d) reported terminate/error/timeout: %d, status: %d'
1717 % (iPid, eWaitResult, eStatus,));
1718 break;
1719
1720 # End of the wait loop.
1721 _, oTest.cbStdOut, oTest.cbStdErr = acbFdOut;
1722
1723 try: eStatus = oProcess.status;
1724 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1725 reporter.log2('Final process status (PID %d) is: %d' % (iPid, eStatus));
1726 reporter.log2('Process (PID %d) %d stdout, %d stderr' % (iPid, oTest.cbStdOut, oTest.cbStdErr));
1727
1728 #
1729 # Get the final status and exit code of the process.
1730 #
1731 try:
1732 oTest.uExitStatus = oProcess.status;
1733 oTest.iExitCode = oProcess.exitCode;
1734 except:
1735 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1736 reporter.log2('Process (PID %d) has exit code: %d; status: %d ' % (iPid, oTest.iExitCode, oTest.uExitStatus));
1737 return fRc;
1738
1739 def testGuestCtrlSessionEnvironment(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
1740 """
1741 Tests the guest session environment changes.
1742 """
1743 aoTests = [
1744 # Check basic operations.
1745 tdTestSessionEx([ # Initial environment is empty.
1746 tdStepSessionCheckEnv(),
1747 # Check clearing empty env.
1748 tdStepSessionClearEnv(),
1749 tdStepSessionCheckEnv(),
1750 # Check set.
1751 tdStepSessionSetEnv('FOO', 'BAR'),
1752 tdStepSessionCheckEnv(['FOO=BAR',]),
1753 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
1754 tdStepSessionClearEnv(),
1755 tdStepSessionCheckEnv(),
1756 # Check unset.
1757 tdStepSessionUnsetEnv('BAR'),
1758 tdStepSessionCheckEnv(['BAR']),
1759 tdStepSessionClearEnv(),
1760 tdStepSessionCheckEnv(),
1761 # Set + unset.
1762 tdStepSessionSetEnv('FOO', 'BAR'),
1763 tdStepSessionCheckEnv(['FOO=BAR',]),
1764 tdStepSessionUnsetEnv('FOO'),
1765 tdStepSessionCheckEnv(['FOO']),
1766 # Bulk environment changes (via attrib) (shall replace existing 'FOO').
1767 tdStepSessionBulkEnv( ['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
1768 tdStepSessionCheckEnv(['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
1769 ]),
1770 tdTestSessionEx([ # Check that setting the same value several times works.
1771 tdStepSessionSetEnv('FOO','BAR'),
1772 tdStepSessionCheckEnv([ 'FOO=BAR',]),
1773 tdStepSessionSetEnv('FOO','BAR2'),
1774 tdStepSessionCheckEnv([ 'FOO=BAR2',]),
1775 tdStepSessionSetEnv('FOO','BAR3'),
1776 tdStepSessionCheckEnv([ 'FOO=BAR3',]),
1777 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
1778 # Add a little unsetting to the mix.
1779 tdStepSessionSetEnv('BAR', 'BEAR'),
1780 tdStepSessionCheckEnv([ 'FOO=BAR3', 'BAR=BEAR',]),
1781 tdStepSessionUnsetEnv('FOO'),
1782 tdStepSessionCheckEnv([ 'FOO', 'BAR=BEAR',]),
1783 tdStepSessionSetEnv('FOO','BAR4'),
1784 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR',]),
1785 # The environment is case sensitive.
1786 tdStepSessionSetEnv('foo','BAR5'),
1787 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo=BAR5']),
1788 tdStepSessionUnsetEnv('foo'),
1789 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo']),
1790 ]),
1791 tdTestSessionEx([ # Bulk settings merges stuff, last entry standing.
1792 tdStepSessionBulkEnv(['FOO=bar', 'foo=bar', 'FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
1793 tdStepSessionCheckEnv(['FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
1794 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
1795 tdStepSessionBulkEnv(['2=1+1', 'FOO=doofus2', ]),
1796 tdStepSessionCheckEnv(['2=1+1', 'FOO=doofus2' ]),
1797 ]),
1798 # Invalid variable names.
1799 tdTestSessionEx([
1800 tdStepSessionSetEnv('', 'FOO', vbox.ComError.E_INVALIDARG),
1801 tdStepSessionCheckEnv(),
1802 tdStepRequireMinimumApiVer(5.0), # 4.3 is too relaxed checking input!
1803 tdStepSessionSetEnv('=', '===', vbox.ComError.E_INVALIDARG),
1804 tdStepSessionCheckEnv(),
1805 tdStepSessionSetEnv('FOO=', 'BAR', vbox.ComError.E_INVALIDARG),
1806 tdStepSessionCheckEnv(),
1807 tdStepSessionSetEnv('=FOO', 'BAR', vbox.ComError.E_INVALIDARG),
1808 tdStepSessionCheckEnv(),
1809 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy and too relaxed!
1810 tdStepSessionBulkEnv(['', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1811 tdStepSessionCheckEnv(),
1812 tdStepSessionBulkEnv(['=', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1813 tdStepSessionCheckEnv(),
1814 tdStepSessionBulkEnv(['=FOO', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1815 tdStepSessionCheckEnv(),
1816 ]),
1817 # A bit more weird keys/values.
1818 tdTestSessionEx([ tdStepSessionSetEnv('$$$', ''),
1819 tdStepSessionCheckEnv([ '$$$=',]), ]),
1820 tdTestSessionEx([ tdStepSessionSetEnv('$$$', '%%%'),
1821 tdStepSessionCheckEnv([ '$$$=%%%',]),
1822 ]),
1823 tdTestSessionEx([ tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
1824 tdStepSessionSetEnv(u'ß$%ß&', ''),
1825 tdStepSessionCheckEnv([ u'ß$%ß&=',]),
1826 ]),
1827 # Misc stuff.
1828 tdTestSessionEx([ tdStepSessionSetEnv('FOO', ''),
1829 tdStepSessionCheckEnv(['FOO=',]),
1830 ]),
1831 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
1832 tdStepSessionCheckEnv(['FOO=BAR',])
1833 ],),
1834 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
1835 tdStepSessionSetEnv('BAR', 'BAZ'),
1836 tdStepSessionCheckEnv([ 'FOO=BAR', 'BAR=BAZ',]),
1837 ]),
1838 ];
1839 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'SessionEnv');
1840
1841 def testGuestCtrlSession(self, oSession, oTxsSession, oTestVm):
1842 """
1843 Tests the guest session handling.
1844 """
1845
1846 #
1847 # Parameters.
1848 #
1849 atTests = [
1850 # Invalid parameters.
1851 [ tdTestSession(sUser = ''), tdTestResultSession() ],
1852 [ tdTestSession(sPassword = 'bar'), tdTestResultSession() ],
1853 [ tdTestSession(sDomain = 'boo'),tdTestResultSession() ],
1854 [ tdTestSession(sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
1855 # User account without a passwort - forbidden.
1856 [ tdTestSession(sPassword = "" ), tdTestResultSession() ],
1857 # Wrong credentials.
1858 # Note: On Guest Additions < 4.3 this always succeeds because these don't
1859 # support creating dedicated sessions. Instead, guest process creation
1860 # then will fail. See note below.
1861 [ tdTestSession(sUser = 'foo', sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
1862 # Correct credentials.
1863 [ tdTestSession(), tdTestResultSession(fRc = True, cNumSessions = 1) ]
1864 ];
1865
1866 fRc = True;
1867 for (i, tTest) in enumerate(atTests):
1868 oCurTest = tTest[0] # type: tdTestSession
1869 oCurRes = tTest[1] # type: tdTestResult
1870
1871 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
1872 reporter.log('Testing #%d, user="%s", sPassword="%s", sDomain="%s" ...'
1873 % (i, oCurTest.oCreds.sUser, oCurTest.oCreds.sPassword, oCurTest.oCreds.sDomain));
1874 sCurGuestSessionName = 'testGuestCtrlSession: Test #%d' % (i,);
1875 fRc2, oCurGuestSession = oCurTest.createSession(sCurGuestSessionName, fIsError = oCurRes.fRc);
1876
1877 # See note about < 4.3 Guest Additions above.
1878 uProtocolVersion = 2;
1879 if oCurGuestSession is not None:
1880 try:
1881 uProtocolVersion = oCurGuestSession.protocolVersion;
1882 except:
1883 fRc = reporter.errorXcpt('Test #%d' % (i,));
1884
1885 if uProtocolVersion >= 2 and fRc2 is not oCurRes.fRc:
1886 fRc = reporter.error('Test #%d failed: Session creation failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
1887
1888 if fRc2 and oCurGuestSession is None:
1889 fRc = reporter.error('Test #%d failed: no session object' % (i,));
1890 fRc2 = False;
1891
1892 if fRc2:
1893 if uProtocolVersion >= 2: # For Guest Additions < 4.3 getSessionCount() always will return 1.
1894 cCurSessions = oCurTest.getSessionCount(self.oTstDrv.oVBoxMgr);
1895 if cCurSessions != oCurRes.cNumSessions:
1896 fRc = reporter.error('Test #%d failed: Session count does not match: Got %d, expected %d'
1897 % (i, cCurSessions, oCurRes.cNumSessions));
1898 try:
1899 sObjName = oCurGuestSession.name;
1900 except:
1901 fRc = reporter.errorXcpt('Test #%d' % (i,));
1902 else:
1903 if sObjName != sCurGuestSessionName:
1904 fRc = reporter.error('Test #%d failed: Session name does not match: Got "%s", expected "%s"'
1905 % (i, sObjName, sCurGuestSessionName));
1906 fRc2 = oCurTest.closeSession(True);
1907 if fRc2 is False:
1908 fRc = reporter.error('Test #%d failed: Session could not be closed' % (i,));
1909
1910 if fRc is False:
1911 return (False, oTxsSession);
1912
1913 #
1914 # Multiple sessions.
1915 #
1916 cMaxGuestSessions = 31; # Maximum number of concurrent guest session allowed.
1917 # Actually, this is 32, but we don't test session 0.
1918 aoMultiSessions = {};
1919 reporter.log2('Opening multiple guest tsessions at once ...');
1920 for i in xrange(cMaxGuestSessions + 1):
1921 aoMultiSessions[i] = tdTestSession(sSessionName = 'MultiSession #%d' % (i,));
1922 aoMultiSessions[i].setEnvironment(oSession, oTxsSession, oTestVm);
1923
1924 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
1925 reporter.log2('MultiSession test #%d count is %d' % (i, cCurSessions));
1926 if cCurSessions != i:
1927 return (reporter.error('MultiSession count is %d, expected %d' % (cCurSessions, i)), oTxsSession);
1928 fRc2, _ = aoMultiSessions[i].createSession('MultiSession #%d' % (i,), i < cMaxGuestSessions);
1929 if fRc2 is not True:
1930 if i < cMaxGuestSessions:
1931 return (reporter.error('MultiSession #%d test failed' % (i,)), oTxsSession);
1932 reporter.log('MultiSession #%d exceeded concurrent guest session count, good' % (i,));
1933 break;
1934
1935 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
1936 if cCurSessions is not cMaxGuestSessions:
1937 return (reporter.error('Final session count %d, expected %d ' % (cCurSessions, cMaxGuestSessions,)), oTxsSession);
1938
1939 reporter.log2('Closing MultiSessions ...');
1940 for i in xrange(cMaxGuestSessions):
1941 # Close this session:
1942 oClosedGuestSession = aoMultiSessions[i].oGuestSession;
1943 fRc2 = aoMultiSessions[i].closeSession(True);
1944 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr)
1945 reporter.log2('MultiSession #%d count is %d' % (i, cCurSessions,));
1946 if fRc2 is False:
1947 fRc = reporter.error('Closing MultiSession #%d failed' % (i,));
1948 elif cCurSessions != cMaxGuestSessions - (i + 1):
1949 fRc = reporter.error('Expected %d session after closing #%d, got %d instead'
1950 % (cMaxGuestSessions - (i + 1), cCurSessions, i,));
1951 assert aoMultiSessions[i].oGuestSession is None or not fRc2;
1952 ## @todo any way to check that the session is closed other than the 'sessions' attribute?
1953
1954 # Try check that none of the remaining sessions got closed.
1955 try:
1956 aoGuestSessions = self.oTstDrv.oVBoxMgr.getArray(atTests[0][0].oTest.oGuest, 'sessions');
1957 except:
1958 return (reporter.errorXcpt('i=%d/%d' % (i, cMaxGuestSessions,)), oTxsSession);
1959 if oClosedGuestSession in aoGuestSessions:
1960 fRc = reporter.error('i=%d/%d: %s should not be in %s'
1961 % (i, cMaxGuestSessions, oClosedGuestSession, aoGuestSessions));
1962 if i + 1 < cMaxGuestSessions: # Not sure what xrange(2,2) does...
1963 for j in xrange(i + 1, cMaxGuestSessions):
1964 if aoMultiSessions[j].oGuestSession not in aoGuestSessions:
1965 fRc = reporter.error('i=%d/j=%d/%d: %s should be in %s'
1966 % (i, j, cMaxGuestSessions, aoMultiSessions[j].oGuestSession, aoGuestSessions));
1967 ## @todo any way to check that they work?
1968
1969 ## @todo Test session timeouts.
1970
1971 return (fRc, oTxsSession);
1972
1973 def testGuestCtrlSessionFileRefs(self, oSession, oTxsSession, oTestVm):
1974 """
1975 Tests the guest session file reference handling.
1976 """
1977
1978 # Find a file to play around with:
1979 sFile = self.getGuestSystemFileForReading(oTestVm);
1980
1981 # Use credential defaults.
1982 oCreds = tdCtxCreds();
1983 oCreds.applyDefaultsIfNotSet(oTestVm);
1984
1985 # Number of stale guest files to create.
1986 cStaleFiles = 10;
1987
1988 #
1989 # Start a session.
1990 #
1991 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
1992 try:
1993 oGuest = oSession.o.console.guest;
1994 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionFileRefs");
1995 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
1996 except:
1997 return (reporter.errorXcpt(), oTxsSession);
1998
1999 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2000 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2001 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2002 reporter.log('Session successfully started');
2003
2004 #
2005 # Open guest files and "forget" them (stale entries).
2006 # For them we don't have any references anymore intentionally.
2007 #
2008 reporter.log2('Opening stale files');
2009 fRc = True;
2010 for i in xrange(0, cStaleFiles):
2011 try:
2012 if self.oTstDrv.fpApiVer >= 5.0:
2013 oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly, vboxcon.FileOpenAction_OpenExisting, 0);
2014 else:
2015 oGuestSession.fileOpen(sFile, "r", "oe", 0);
2016 # Note: Use a timeout in the call above for not letting the stale processes
2017 # hanging around forever. This can happen if the installed Guest Additions
2018 # do not support terminating guest processes.
2019 except:
2020 fRc = reporter.errorXcpt('Opening stale file #%d failed:' % (i,));
2021 break;
2022
2023 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2024 except: fRc = reporter.errorXcpt();
2025 else:
2026 if cFiles != cStaleFiles:
2027 fRc = reporter.error('Got %d stale files, expected %d' % (cFiles, cStaleFiles));
2028
2029 if fRc is True:
2030 #
2031 # Open non-stale files and close them again.
2032 #
2033 reporter.log2('Opening non-stale files');
2034 aoFiles = [];
2035 for i in xrange(0, cStaleFiles):
2036 try:
2037 if self.oTstDrv.fpApiVer >= 5.0:
2038 oCurFile = oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly,
2039 vboxcon.FileOpenAction_OpenExisting, 0);
2040 else:
2041 oCurFile = oGuestSession.fileOpen(sFile, "r", "oe", 0);
2042 aoFiles.append(oCurFile);
2043 except:
2044 fRc = reporter.errorXcpt('Opening non-stale file #%d failed:' % (i,));
2045 break;
2046
2047 # Check the count.
2048 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2049 except: fRc = reporter.errorXcpt();
2050 else:
2051 if cFiles != cStaleFiles * 2:
2052 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles * 2));
2053
2054 # Close them.
2055 reporter.log2('Closing all non-stale files again ...');
2056 for i, oFile in enumerate(aoFiles):
2057 try:
2058 oFile.close();
2059 except:
2060 fRc = reporter.errorXcpt('Closing non-stale file #%d failed:' % (i,));
2061
2062 # Check the count again.
2063 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2064 except: fRc = reporter.errorXcpt();
2065 # Here we count the stale files (that is, files we don't have a reference
2066 # anymore for) and the opened and then closed non-stale files (that we still keep
2067 # a reference in aoFiles[] for).
2068 if cFiles != cStaleFiles:
2069 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles));
2070
2071 #
2072 # Check that all (referenced) non-stale files are now in the "closed" state.
2073 #
2074 reporter.log2('Checking statuses of all non-stale files ...');
2075 for i, oFile in enumerate(aoFiles):
2076 try:
2077 eFileStatus = aoFiles[i].status;
2078 except:
2079 fRc = reporter.errorXcpt('Checking status of file #%d failed:' % (i,));
2080 else:
2081 if eFileStatus != vboxcon.FileStatus_Closed:
2082 fRc = reporter.error('Non-stale file #%d has status %d, expected %d'
2083 % (i, eFileStatus, vboxcon.FileStatus_Closed));
2084
2085 if fRc is True:
2086 reporter.log2('All non-stale files closed');
2087
2088 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2089 except: fRc = reporter.errorXcpt();
2090 else: reporter.log2('Final guest session file count: %d' % (cFiles,));
2091
2092 #
2093 # Now try to close the session and see what happens.
2094 # Note! Session closing is why we've been doing all the 'if fRc is True' stuff above rather than returning.
2095 #
2096 reporter.log2('Closing guest session ...');
2097 try:
2098 oGuestSession.close();
2099 except:
2100 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2101
2102 return (fRc, oTxsSession);
2103
2104 #def testGuestCtrlSessionDirRefs(self, oSession, oTxsSession, oTestVm):
2105 # """
2106 # Tests the guest session directory reference handling.
2107 # """
2108
2109 # fRc = True;
2110 # return (fRc, oTxsSession);
2111
2112 def testGuestCtrlSessionProcRefs(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2113 """
2114 Tests the guest session process reference handling.
2115 """
2116
2117 sCmd = self.getGuestSystemShell(oTestVm);
2118 asArgs = [sCmd,];
2119
2120 # Use credential defaults.
2121 oCreds = tdCtxCreds();
2122 oCreds.applyDefaultsIfNotSet(oTestVm);
2123
2124 # Number of stale guest processes to create.
2125 cStaleProcs = 10;
2126
2127 #
2128 # Start a session.
2129 #
2130 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2131 try:
2132 oGuest = oSession.o.console.guest;
2133 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionProcRefs");
2134 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2135 except:
2136 return (reporter.errorXcpt(), oTxsSession);
2137
2138 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2139 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2140 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2141 reporter.log('Session successfully started');
2142
2143 #
2144 # Fire off forever-running processes and "forget" them (stale entries).
2145 # For them we don't have any references anymore intentionally.
2146 #
2147 reporter.log2('Starting stale processes...');
2148 fRc = True;
2149 for i in xrange(0, cStaleProcs):
2150 try:
2151 oGuestSession.processCreate(sCmd,
2152 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], [],
2153 [ vboxcon.ProcessCreateFlag_WaitForStdOut ], \
2154 30 * 1000);
2155 # Note: Use a timeout in the call above for not letting the stale processes
2156 # hanging around forever. This can happen if the installed Guest Additions
2157 # do not support terminating guest processes.
2158 except:
2159 fRc = reporter.errorXcpt('Creating stale process #%d failed:' % (i,));
2160 break;
2161
2162 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2163 except: fRc = reporter.errorXcpt();
2164 else:
2165 if cProcesses != cStaleProcs:
2166 fRc = reporter.error('Got %d stale processes, expected %d' % (cProcesses, cStaleProcs));
2167
2168 if fRc is True:
2169 #
2170 # Fire off non-stale processes and wait for termination.
2171 #
2172 if oTestVm.isWindows() or oTestVm.isOS2():
2173 asArgs = [ sCmd, '/C', 'dir', '/S', self.getGuestSystemDir(oTestVm), ];
2174 else:
2175 asArgs = [ sCmd, '-c', 'ls -la ' + self.getGuestSystemDir(oTestVm), ];
2176 reporter.log2('Starting non-stale processes...');
2177 aoProcesses = [];
2178 for i in xrange(0, cStaleProcs):
2179 try:
2180 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2181 [], [], 0); # Infinite timeout.
2182 aoProcesses.append(oCurProc);
2183 except:
2184 fRc = reporter.errorXcpt('Creating non-stale process #%d failed:' % (i,));
2185 break;
2186
2187 reporter.log2('Waiting for non-stale processes to terminate...');
2188 for i, oProcess in enumerate(aoProcesses):
2189 try:
2190 oProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 30 * 1000);
2191 eProcessStatus = oProcess.status;
2192 except:
2193 fRc = reporter.errorXcpt('Waiting for non-stale process #%d failed:' % (i,));
2194 else:
2195 if eProcessStatus != vboxcon.ProcessStatus_TerminatedNormally:
2196 fRc = reporter.error('Waiting for non-stale processes #%d resulted in status %d, expected %d'
2197 % (i, eProcessStatus, vboxcon.ProcessStatus_TerminatedNormally));
2198
2199 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2200 except: fRc = reporter.errorXcpt();
2201 else:
2202 # Here we count the stale processes (that is, processes we don't have a reference
2203 # anymore for) and the started + terminated non-stale processes (that we still keep
2204 # a reference in aoProcesses[] for).
2205 if cProcesses != (cStaleProcs * 2):
2206 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2207
2208 if fRc is True:
2209 reporter.log2('All non-stale processes terminated');
2210
2211 #
2212 # Fire off non-stale blocking processes which are terminated via terminate().
2213 #
2214 if oTestVm.isWindows() or oTestVm.isOS2():
2215 asArgs = [ sCmd, '/C', 'pause'];
2216 else:
2217 asArgs = [ sCmd ];
2218 reporter.log2('Starting blocking processes...');
2219 aoProcesses = [];
2220 for i in xrange(0, cStaleProcs):
2221 try:
2222 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2223 [], [], 30 * 1000);
2224 # Note: Use a timeout in the call above for not letting the stale processes
2225 # hanging around forever. This can happen if the installed Guest Additions
2226 # do not support terminating guest processes.
2227 aoProcesses.append(oCurProc);
2228 except:
2229 fRc = reporter.errorXcpt('Creating non-stale blocking process #%d failed:' % (i,));
2230 break;
2231
2232 reporter.log2('Terminating blocking processes...');
2233 for i, oProcess in enumerate(aoProcesses):
2234 try:
2235 oProcess.terminate();
2236 except: # Termination might not be supported, just skip and log it.
2237 reporter.logXcpt('Termination of blocking process #%d failed, skipped:' % (i,));
2238
2239 # There still should be 20 processes because we terminated the 10 newest ones.
2240 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2241 except: fRc = reporter.errorXcpt();
2242 else:
2243 if cProcesses != (cStaleProcs * 2):
2244 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2245 reporter.log2('Final guest session processes count: %d' % (cProcesses,));
2246
2247 #
2248 # Now try to close the session and see what happens.
2249 #
2250 reporter.log2('Closing guest session ...');
2251 try:
2252 oGuestSession.close();
2253 except:
2254 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2255
2256 return (fRc, oTxsSession);
2257
2258 def testGuestCtrlExec(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements
2259 """
2260 Tests the basic execution feature.
2261 """
2262
2263 # Paths:
2264 sVBoxControl = None; ## @todo Get path of installed Guest Additions. Later.
2265 sShell = self.getGuestSystemShell(oTestVm);
2266 sShellOpt = '/C' if oTestVm.isWindows() or oTestVm.isOS2() else '-c';
2267 sSystemDir = self.getGuestSystemDir(oTestVm);
2268 sFileForReading = self.getGuestSystemFileForReading(oTestVm);
2269 if oTestVm.isWindows() or oTestVm.isOS2():
2270 sImageOut = self.getGuestSystemShell(oTestVm);
2271 if oTestVm.isWindows():
2272 sVBoxControl = "C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\VBoxControl.exe";
2273 else:
2274 sImageOut = "/bin/ls";
2275 if oTestVm.isLinux(): ## @todo check solaris and darwin.
2276 sVBoxControl = "/usr/bin/VBoxControl"; # Symlink
2277
2278 # Use credential defaults.
2279 oCreds = tdCtxCreds();
2280 oCreds.applyDefaultsIfNotSet(oTestVm);
2281
2282 atInvalid = [
2283 # Invalid parameters.
2284 [ tdTestExec(), tdTestResultExec() ],
2285 # Non-existent / invalid image.
2286 [ tdTestExec(sCmd = "non-existent"), tdTestResultExec() ],
2287 [ tdTestExec(sCmd = "non-existent2"), tdTestResultExec() ],
2288 # Use an invalid format string.
2289 [ tdTestExec(sCmd = "%$%%%&"), tdTestResultExec() ],
2290 # More stuff.
2291 [ tdTestExec(sCmd = u"ƒ‰‹ˆ÷‹¸"), tdTestResultExec() ],
2292 [ tdTestExec(sCmd = "???://!!!"), tdTestResultExec() ],
2293 [ tdTestExec(sCmd = "<>!\\"), tdTestResultExec() ],
2294 # Enable as soon as ERROR_BAD_DEVICE is implemented.
2295 #[ tdTestExec(sCmd = "CON", tdTestResultExec() ],
2296 ];
2297
2298 atExec = [];
2299 if oTestVm.isWindows() or oTestVm.isOS2():
2300 atExec += [
2301 # Basic execution.
2302 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2303 tdTestResultExec(fRc = True) ],
2304 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sFileForReading ]),
2305 tdTestResultExec(fRc = True) ],
2306 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir + '\\nonexist.dll' ]),
2307 tdTestResultExec(fRc = True, iExitCode = 1) ],
2308 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', '/wrongparam' ]),
2309 tdTestResultExec(fRc = True, iExitCode = 1) ],
2310 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2311 tdTestResultExec(fRc = True, iExitCode = 1) ],
2312 # StdOut.
2313 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2314 tdTestResultExec(fRc = True) ],
2315 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdout-non-existing' ]),
2316 tdTestResultExec(fRc = True, iExitCode = 1) ],
2317 # StdErr.
2318 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2319 tdTestResultExec(fRc = True) ],
2320 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stderr-non-existing' ]),
2321 tdTestResultExec(fRc = True, iExitCode = 1) ],
2322 # StdOut + StdErr.
2323 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2324 tdTestResultExec(fRc = True) ],
2325 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdouterr-non-existing' ]),
2326 tdTestResultExec(fRc = True, iExitCode = 1) ],
2327 ];
2328 # atExec.extend([
2329 # FIXME: Failing tests.
2330 # Environment variables.
2331 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2332 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2333 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2334 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2335 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2336 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2337 # aEnv = [ 'TEST_FOO=BAR' ],
2338 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2339 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2340 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2341 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2342 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2343 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2344
2345 ## @todo Create some files (or get files) we know the output size of to validate output length!
2346 ## @todo Add task which gets killed at some random time while letting the guest output something.
2347 #];
2348 else:
2349 atExec += [
2350 # Basic execution.
2351 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '-R', sSystemDir ]),
2352 tdTestResultExec(fRc = True, iExitCode = 1) ],
2353 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sFileForReading ]),
2354 tdTestResultExec(fRc = True) ],
2355 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '--wrong-parameter' ]),
2356 tdTestResultExec(fRc = True, iExitCode = 2) ],
2357 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/non/existent' ]),
2358 tdTestResultExec(fRc = True, iExitCode = 2) ],
2359 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2360 tdTestResultExec(fRc = True, iExitCode = 127) ],
2361 # StdOut.
2362 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2363 tdTestResultExec(fRc = True) ],
2364 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdout-non-existing' ]),
2365 tdTestResultExec(fRc = True, iExitCode = 2) ],
2366 # StdErr.
2367 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2368 tdTestResultExec(fRc = True) ],
2369 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stderr-non-existing' ]),
2370 tdTestResultExec(fRc = True, iExitCode = 2) ],
2371 # StdOut + StdErr.
2372 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2373 tdTestResultExec(fRc = True) ],
2374 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdouterr-non-existing' ]),
2375 tdTestResultExec(fRc = True, iExitCode = 2) ],
2376 ];
2377 # atExec.extend([
2378 # FIXME: Failing tests.
2379 # Environment variables.
2380 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2381 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2382 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2383 #
2384 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2385 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2386 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2387 # aEnv = [ 'TEST_FOO=BAR' ],
2388 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2389 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2390 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2391 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2392 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2393 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2394
2395 ## @todo Create some files (or get files) we know the output size of to validate output length!
2396 ## @todo Add task which gets killed at some random time while letting the guest output something.
2397 #];
2398
2399 #
2400 for iExitCode in xrange(0, 127):
2401 atExec.append([ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'exit %s' % iExitCode ]),
2402 tdTestResultExec(fRc = True, iExitCode = iExitCode) ]);
2403
2404 if sVBoxControl:
2405 # Paths with spaces on windows.
2406 atExec.append([ tdTestExec(sCmd = sVBoxControl, asArgs = [ sVBoxControl, 'version' ]),
2407 tdTestResultExec(fRc = True) ]);
2408
2409 # Build up the final test array for the first batch.
2410 atTests = atInvalid + atExec;
2411
2412 #
2413 # First batch: One session per guest process.
2414 #
2415 reporter.log('One session per guest process ...');
2416 fRc = True;
2417 for (i, tTest) in enumerate(atTests):
2418 oCurTest = tTest[0] # type: tdTestExec
2419 oCurRes = tTest[1] # type: tdTestResultExec
2420 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2421 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlExec: Test #%d' % (i,), True);
2422 if fRc is not True:
2423 reporter.error('Test #%d failed: Could not create session' % (i,));
2424 break;
2425 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
2426 if fRc is not True:
2427 break;
2428 fRc = oCurTest.closeSession(True);
2429 if fRc is not True:
2430 break;
2431
2432 reporter.log('Execution of all tests done, checking for stale sessions');
2433
2434 # No sessions left?
2435 try:
2436 aSessions = self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions');
2437 except:
2438 fRc = reporter.errorXcpt();
2439 else:
2440 cSessions = len(aSessions);
2441 if cSessions != 0:
2442 fRc = reporter.error('Found %d stale session(s), expected 0:' % (cSessions,));
2443 for (i, aSession) in enumerate(aSessions):
2444 try: reporter.log(' Stale session #%d ("%s")' % (aSession.id, aSession.name));
2445 except: reporter.errorXcpt();
2446
2447 if fRc is not True:
2448 return (fRc, oTxsSession);
2449
2450 reporter.log('Now using one guest session for all tests ...');
2451
2452 #
2453 # Second batch: One session for *all* guest processes.
2454 #
2455
2456 # Create session.
2457 reporter.log('Creating session for all tests ...');
2458 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
2459 try:
2460 oGuest = oSession.o.console.guest;
2461 oCurGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain,
2462 'testGuestCtrlExec: One session for all tests');
2463 except:
2464 return (reporter.errorXcpt(), oTxsSession);
2465
2466 try:
2467 eWaitResult = oCurGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2468 except:
2469 fRc = reporter.errorXcpt('Waiting for guest session to start failed:');
2470 else:
2471 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2472 fRc = reporter.error('Session did not start successfully, returned wait result: %d' % (eWaitResult,));
2473 else:
2474 reporter.log('Session successfully started');
2475
2476 # Do the tests within this session.
2477 for (i, tTest) in enumerate(atTests):
2478 oCurTest = tTest[0] # type: tdTestExec
2479 oCurRes = tTest[1] # type: tdTestResultExec
2480
2481 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2482 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
2483 if fRc is False:
2484 break;
2485
2486 # Close the session.
2487 reporter.log2('Closing guest session ...');
2488 try:
2489 oCurGuestSession.close();
2490 oCurGuestSession = None;
2491 except:
2492 fRc = reporter.errorXcpt('Closing guest session failed:');
2493
2494 # No sessions left?
2495 reporter.log('Execution of all tests done, checking for stale sessions again');
2496 try: cSessions = len(self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions'));
2497 except: fRc = reporter.errorXcpt();
2498 else:
2499 if cSessions != 0:
2500 fRc = reporter.error('Found %d stale session(s), expected 0' % (cSessions,));
2501 return (fRc, oTxsSession);
2502
2503 def threadForTestGuestCtrlSessionReboot(self, oGuestProcess):
2504 """
2505 Thread routine which waits for the stale guest process getting terminated (or some error)
2506 while the main test routine reboots the guest. It then compares the expected guest process result
2507 and logs an error if appropriate.
2508 """
2509 reporter.log('Waiting for process to get terminated at reboot ...');
2510 try:
2511 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate ], 5 * 60 * 1000);
2512 except:
2513 return reporter.errorXcpt('waitForArray failed');
2514 try:
2515 eStatus = oGuestProcess.status
2516 except:
2517 return reporter.errorXcpt('failed to get status (wait result %d)' % (eWaitResult,));
2518
2519 if eWaitResult == vboxcon.ProcessWaitResult_Terminate and eStatus == vboxcon.ProcessStatus_Down:
2520 reporter.log('Stale process was correctly terminated (status: down)');
2521 return True;
2522
2523 return reporter.error('Process wait across reboot failed: eWaitResult=%d, expected %d; eStatus=%d, expected %d'
2524 % (eWaitResult, vboxcon.ProcessWaitResult_Terminate, eStatus, vboxcon.ProcessStatus_Down,));
2525
2526 def testGuestCtrlSessionReboot(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2527 """
2528 Tests guest object notifications when a guest gets rebooted / shutdown.
2529
2530 These notifications gets sent from the guest sessions in order to make API clients
2531 aware of guest session changes.
2532
2533 To test that we create a stale guest process and trigger a reboot of the guest.
2534 """
2535
2536 ## @todo backport fixes to 6.0 and maybe 5.2
2537 if self.oTstDrv.fpApiVer <= 6.0:
2538 reporter.log('Skipping: Required fixes not yet backported!');
2539 return None;
2540
2541 # Use credential defaults.
2542 oCreds = tdCtxCreds();
2543 oCreds.applyDefaultsIfNotSet(oTestVm);
2544
2545 fRc = True;
2546
2547 #
2548 # Start a session.
2549 #
2550 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2551 try:
2552 oGuest = oSession.o.console.guest;
2553 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionReboot");
2554 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2555 except:
2556 return (reporter.errorXcpt(), oTxsSession);
2557
2558 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2559 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2560 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2561 reporter.log('Session successfully started');
2562
2563 #
2564 # Create a process.
2565 #
2566 sImage = self.getGuestSystemShell(oTestVm);
2567 asArgs = [ sImage, ];
2568 aEnv = [];
2569 fFlags = [];
2570 try:
2571 oGuestProcess = oGuestSession.processCreate(sImage,
2572 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], aEnv, fFlags,
2573 30 * 1000);
2574 except:
2575 fRc = reporter.error('Failed to start shell process (%s)' % (sImage,));
2576 else:
2577 try:
2578 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2579 except:
2580 fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
2581 else:
2582 # Check the result and state:
2583 try: eStatus = oGuestProcess.status;
2584 except: fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
2585 else:
2586 reporter.log2('Starting process wait result returned: %d; Process status is: %d' % (eWaitResult, eStatus,));
2587 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2588 fRc = reporter.error('wait for ProcessWaitForFlag_Start failed: %d, expected %d (Start)'
2589 % (eWaitResult, vboxcon.ProcessWaitResult_Start,));
2590 elif eStatus != vboxcon.ProcessStatus_Started:
2591 fRc = reporter.error('Unexpected process status after startup: %d, wanted %d (Started)'
2592 % (eStatus, vboxcon.ProcessStatus_Started,));
2593 else:
2594 # Create a thread that waits on the process to terminate
2595 reporter.log('Creating reboot thread ...');
2596 oThreadReboot = threading.Thread(target = self.threadForTestGuestCtrlSessionReboot,
2597 args = (oGuestProcess,),
2598 name = ('threadForTestGuestCtrlSessionReboot'));
2599 oThreadReboot.setDaemon(True);
2600 oThreadReboot.start();
2601
2602 # Not sure why this fudge is needed...
2603 reporter.log('5 second wait fudge before triggering reboot ...');
2604 self.oTstDrv.sleep(5);
2605
2606 # Do the reboot.
2607 reporter.log('Rebooting guest and reconnecting TXS ...');
2608 (oSession, oTxsSession) = self.oTstDrv.txsRebootAndReconnectViaTcp(oSession, oTxsSession,
2609 cMsTimeout = 3 * 60000);
2610 if not oSession or not oTxsSession:
2611 try: oGuestProcess.terminate();
2612 except: reporter.logXcpt();
2613 fRc = False;
2614
2615 reporter.log('Waiting for thread to finish ...');
2616 oThreadReboot.join();
2617
2618 #
2619 # Try make sure we don't leave with a stale process on failure.
2620 #
2621 try: oGuestProcess.terminate();
2622 except: reporter.logXcpt();
2623
2624 #
2625 # Close the session.
2626 #
2627 reporter.log2('Closing guest session ...');
2628 try:
2629 oGuestSession.close();
2630 except:
2631 fRc = reporter.errorXcpt();
2632
2633 return (fRc, oTxsSession);
2634
2635 def testGuestCtrlExecTimeout(self, oSession, oTxsSession, oTestVm):
2636 """
2637 Tests handling of timeouts of started guest processes.
2638 """
2639
2640 sShell = self.getGuestSystemShell(oTestVm);
2641
2642 # Use credential defaults.
2643 oCreds = tdCtxCreds();
2644 oCreds.applyDefaultsIfNotSet(oTestVm);
2645
2646 #
2647 # Create a session.
2648 #
2649 try:
2650 oGuest = oSession.o.console.guest;
2651 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlExecTimeout");
2652 eWaitResult = oGuestSession.waitForArray([ vboxcon.GuestSessionWaitForFlag_Start, ], 30 * 1000);
2653 except:
2654 return (reporter.errorXcpt(), oTxsSession);
2655
2656 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2657 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2658 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2659 reporter.log('Session successfully started');
2660
2661 #
2662 # Create a process which never terminates and should timeout when
2663 # waiting for termination.
2664 #
2665 fRc = True;
2666 try:
2667 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
2668 [], [], 30 * 1000);
2669 except:
2670 fRc = reporter.errorXcpt();
2671 else:
2672 reporter.log('Waiting for process 1 being started ...');
2673 try:
2674 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2675 except:
2676 fRc = reporter.errorXcpt();
2677 else:
2678 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2679 fRc = reporter.error('Waiting for process 1 to start failed, got status %d' % (eWaitResult,));
2680 else:
2681 for msWait in (1, 32, 2000,):
2682 reporter.log('Waiting for process 1 to time out within %sms ...' % (msWait,));
2683 try:
2684 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], msWait);
2685 except:
2686 fRc = reporter.errorXcpt();
2687 break;
2688 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
2689 fRc = reporter.error('Waiting for process 1 did not time out in %sms as expected: %d'
2690 % (msWait, eWaitResult,));
2691 break;
2692 reporter.log('Waiting for process 1 timed out in %u ms, good' % (msWait,));
2693
2694 try:
2695 oCurProcess.terminate();
2696 except:
2697 reporter.errorXcpt();
2698 oCurProcess = None;
2699
2700 #
2701 # Create another process that doesn't terminate, but which will be killed by VBoxService
2702 # because it ran out of execution time (3 seconds).
2703 #
2704 try:
2705 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
2706 [], [], 3 * 1000);
2707 except:
2708 fRc = reporter.errorXcpt();
2709 else:
2710 reporter.log('Waiting for process 2 being started ...');
2711 try:
2712 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2713 except:
2714 fRc = reporter.errorXcpt();
2715 else:
2716 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2717 fRc = reporter.error('Waiting for process 2 to start failed, got status %d' % (eWaitResult,));
2718 else:
2719 reporter.log('Waiting for process 2 to get killed for running out of execution time ...');
2720 try:
2721 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 15 * 1000);
2722 except:
2723 fRc = reporter.errorXcpt();
2724 else:
2725 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
2726 fRc = reporter.error('Waiting for process 2 did not time out when it should, got wait result %d'
2727 % (eWaitResult,));
2728 else:
2729 reporter.log('Waiting for process 2 did not time out, good: %s' % (eWaitResult,));
2730 try:
2731 eStatus = oCurProcess.status;
2732 except:
2733 fRc = reporter.errorXcpt();
2734 else:
2735 if eStatus != vboxcon.ProcessStatus_TimedOutKilled:
2736 fRc = reporter.error('Status of process 2 wrong; excepted %d, got %d'
2737 % (vboxcon.ProcessStatus_TimedOutKilled, eStatus));
2738 else:
2739 reporter.log('Status of process 2 is TimedOutKilled (%d) is it should be.'
2740 % (vboxcon.ProcessStatus_TimedOutKilled,));
2741 try:
2742 oCurProcess.terminate();
2743 except:
2744 reporter.logXcpt();
2745 oCurProcess = None;
2746
2747 #
2748 # Clean up the session.
2749 #
2750 try:
2751 oGuestSession.close();
2752 except:
2753 fRc = reporter.errorXcpt();
2754
2755 return (fRc, oTxsSession);
2756
2757 def testGuestCtrlDirCreate(self, oSession, oTxsSession, oTestVm):
2758 """
2759 Tests creation of guest directories.
2760 """
2761
2762 sScratch = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'testGuestCtrlDirCreate');
2763
2764 atTests = [
2765 # Invalid stuff.
2766 [ tdTestDirCreate(sDirectory = '' ), tdTestResultFailure() ],
2767 # More unusual stuff.
2768 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '..') ), tdTestResultFailure() ],
2769 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '.') ), tdTestResultFailure() ],
2770 ];
2771 if oTestVm.isWindows() or oTestVm.isOS2():
2772 atTests.extend([
2773 [ tdTestDirCreate(sDirectory = '..' ), tdTestResultFailure() ],
2774 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
2775 [ tdTestDirCreate(sDirectory = '../..' ), tdTestResultFailure() ],
2776 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
2777 [ tdTestDirCreate(sDirectory = 'C:\\' ), tdTestResultFailure() ],
2778 [ tdTestDirCreate(sDirectory = 'C:\\..' ), tdTestResultFailure() ],
2779 [ tdTestDirCreate(sDirectory = 'C:\\..\\' ), tdTestResultFailure() ],
2780 [ tdTestDirCreate(sDirectory = 'C:/' ), tdTestResultFailure() ],
2781 [ tdTestDirCreate(sDirectory = 'C:/.' ), tdTestResultFailure() ],
2782 [ tdTestDirCreate(sDirectory = 'C:/./' ), tdTestResultFailure() ],
2783 [ tdTestDirCreate(sDirectory = 'C:/..' ), tdTestResultFailure() ],
2784 [ tdTestDirCreate(sDirectory = 'C:/../' ), tdTestResultFailure() ],
2785 [ tdTestDirCreate(sDirectory = '\\\\uncrulez\\foo' ), tdTestResultFailure() ],
2786 ]);
2787 else:
2788 atTests.extend([
2789 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
2790 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
2791 [ tdTestDirCreate(sDirectory = '/' ), tdTestResultFailure() ],
2792 [ tdTestDirCreate(sDirectory = '/..' ), tdTestResultFailure() ],
2793 [ tdTestDirCreate(sDirectory = '/../' ), tdTestResultFailure() ],
2794 ]);
2795 atTests.extend([
2796 # Existing directories and files.
2797 [ tdTestDirCreate(sDirectory = self.getGuestSystemDir(oTestVm) ), tdTestResultFailure() ],
2798 [ tdTestDirCreate(sDirectory = self.getGuestSystemShell(oTestVm) ), tdTestResultFailure() ],
2799 [ tdTestDirCreate(sDirectory = self.getGuestSystemFileForReading(oTestVm) ), tdTestResultFailure() ],
2800 ]);
2801
2802 atTests.extend([
2803 # Creating directories.
2804 [ tdTestDirCreate(sDirectory = sScratch ), tdTestResultSuccess() ],
2805 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
2806 fFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
2807 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
2808 fFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
2809 # Long random names.
2810 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(36, 28))),
2811 tdTestResultSuccess() ],
2812 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(140, 116))),
2813 tdTestResultSuccess() ],
2814 # Too long names. ASSUMES a guests has a 255 filename length limitation.
2815 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
2816 tdTestResultFailure() ],
2817 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
2818 tdTestResultFailure() ],
2819 # Missing directory in path.
2820 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo1', 'bar') ), tdTestResultFailure() ],
2821 ]);
2822
2823 fRc = True;
2824 for (i, tTest) in enumerate(atTests):
2825 oCurTest = tTest[0] # type: tdTestDirCreate
2826 oCurRes = tTest[1] # type: tdTestResult
2827 reporter.log('Testing #%d, sDirectory="%s" ...' % (i, oCurTest.sDirectory));
2828
2829 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2830 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreate: Test #%d' % (i,), fIsError = True);
2831 if fRc is False:
2832 return reporter.error('Test #%d failed: Could not create session' % (i,));
2833
2834 fRc = self.gctrlCreateDir(oCurTest, oCurRes, oCurGuestSession);
2835
2836 fRc = oCurTest.closeSession(fIsError = True) and fRc;
2837 if fRc is False:
2838 reporter.error('Test #%d failed' % (i,));
2839 break;
2840
2841 return (fRc, oTxsSession);
2842
2843 def testGuestCtrlDirCreateTemp(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2844 """
2845 Tests creation of temporary directories.
2846 """
2847
2848 sSystemDir = self.getGuestSystemDir(oTestVm);
2849 atTests = [
2850 # Invalid stuff (template must have one or more trailin 'X'es (upper case only), or a cluster of three or more).
2851 [ tdTestDirCreateTemp(sDirectory = ''), tdTestResultFailure() ],
2852 [ tdTestDirCreateTemp(sDirectory = sSystemDir, fMode = 1234), tdTestResultFailure() ],
2853 [ tdTestDirCreateTemp(sTemplate = 'xXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2854 [ tdTestDirCreateTemp(sTemplate = 'xxx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2855 [ tdTestDirCreateTemp(sTemplate = 'XXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2856 [ tdTestDirCreateTemp(sTemplate = 'bar', sDirectory = 'whatever', fMode = 0o700), tdTestResultFailure() ],
2857 [ tdTestDirCreateTemp(sTemplate = 'foo', sDirectory = 'it is not used', fMode = 0o700), tdTestResultFailure() ],
2858 [ tdTestDirCreateTemp(sTemplate = 'X,so', sDirectory = 'pointless test', fMode = 0o700), tdTestResultFailure() ],
2859 # Non-existing stuff.
2860 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX',
2861 sDirectory = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'non', 'existing')),
2862 tdTestResultFailure() ],
2863 # Working stuff:
2864 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2865 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2866 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2867 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2868 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2869 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2870 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2871 ## @todo test fSecure and pass weird fMode values once these parameters are implemented in the API.
2872 ];
2873
2874 fRc = True;
2875 for (i, tTest) in enumerate(atTests):
2876 oCurTest = tTest[0] # type: tdTestDirCreateTemp
2877 oCurRes = tTest[1] # type: tdTestResult
2878 reporter.log('Testing #%d, sTemplate="%s", fMode=%#o, path="%s", secure="%s" ...' %
2879 (i, oCurTest.sTemplate, oCurTest.fMode, oCurTest.sDirectory, oCurTest.fSecure));
2880
2881 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2882 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreateTemp: Test #%d' % (i,), fIsError = True);
2883 if fRc is False:
2884 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
2885 break;
2886
2887 sDirTemp = '';
2888 try:
2889 sDirTemp = oCurGuestSession.directoryCreateTemp(oCurTest.sTemplate, oCurTest.fMode,
2890 oCurTest.sDirectory, oCurTest.fSecure);
2891 except:
2892 if oCurRes.fRc is True:
2893 fRc = reporter.errorXcpt('Creating temp directory "%s" failed:' % (oCurTest.sDirectory,));
2894 else:
2895 reporter.logXcpt('Creating temp directory "%s" failed expectedly, skipping:' % (oCurTest.sDirectory,));
2896 else:
2897 reporter.log2('Temporary directory is: "%s"' % (sDirTemp,));
2898 if not sDirTemp:
2899 fRc = reporter.error('Resulting directory is empty!');
2900 else:
2901 ## @todo This does not work for some unknown reason.
2902 #try:
2903 # if self.oTstDrv.fpApiVer >= 5.0:
2904 # fExists = oCurGuestSession.directoryExists(sDirTemp, False);
2905 # else:
2906 # fExists = oCurGuestSession.directoryExists(sDirTemp);
2907 #except:
2908 # fRc = reporter.errorXcpt('sDirTemp=%s' % (sDirTemp,));
2909 #else:
2910 # if fExists is not True:
2911 # fRc = reporter.error('Test #%d failed: Temporary directory "%s" does not exists (%s)'
2912 # % (i, sDirTemp, fExists));
2913 try:
2914 oFsObjInfo = oCurGuestSession.fsObjQueryInfo(sDirTemp, False);
2915 eType = oFsObjInfo.type;
2916 except:
2917 fRc = reporter.errorXcpt('sDirTemp="%s"' % (sDirTemp,));
2918 else:
2919 reporter.log2('%s: eType=%s (dir=%d)' % (sDirTemp, eType, vboxcon.FsObjType_Directory,));
2920 if eType != vboxcon.FsObjType_Directory:
2921 fRc = reporter.error('Temporary directory "%s" not created as a directory: eType=%d'
2922 % (sDirTemp, eType));
2923 fRc = oCurTest.closeSession(True) and fRc;
2924 return (fRc, oTxsSession);
2925
2926 def testGuestCtrlDirRead(self, oSession, oTxsSession, oTestVm):
2927 """
2928 Tests opening and reading (enumerating) guest directories.
2929 """
2930
2931 sSystemDir = self.getGuestSystemDir(oTestVm);
2932 atTests = [
2933 # Invalid stuff.
2934 [ tdTestDirRead(sDirectory = ''), tdTestResultDirRead() ],
2935 [ tdTestDirRead(sDirectory = sSystemDir, fFlags = [ 1234 ]), tdTestResultDirRead() ],
2936 [ tdTestDirRead(sDirectory = sSystemDir, sFilter = '*.foo'), tdTestResultDirRead() ],
2937 # Non-existing stuff.
2938 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'really-no-such-subdir')), tdTestResultDirRead() ],
2939 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'non', 'existing')), tdTestResultDirRead() ],
2940 ];
2941
2942 if oTestVm.isWindows() or oTestVm.isOS2():
2943 atTests.extend([
2944 # More unusual stuff.
2945 [ tdTestDirRead(sDirectory = 'z:\\'), tdTestResultDirRead() ],
2946 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
2947 ]);
2948 else:
2949 atTests.extend([
2950 # More unusual stuff.
2951 [ tdTestDirRead(sDirectory = 'z:/'), tdTestResultDirRead() ],
2952 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
2953 ]);
2954 # Read the system directory (ASSUMES at least 5 files in it):
2955 atTests.append([ tdTestDirRead(sDirectory = sSystemDir), tdTestResultDirRead(fRc = True, cFiles = -5, cDirs = None) ]);
2956 ## @todo trailing slash
2957
2958 # Read from the test file set.
2959 atTests.extend([
2960 [ tdTestDirRead(sDirectory = self.oTestFiles.oEmptyDir.sPath),
2961 tdTestResultDirRead(fRc = True, cFiles = 0, cDirs = 0, cOthers = 0) ],
2962 [ tdTestDirRead(sDirectory = self.oTestFiles.oManyDir.sPath),
2963 tdTestResultDirRead(fRc = True, cFiles = len(self.oTestFiles.oManyDir.aoChildren), cDirs = 0, cOthers = 0) ],
2964 [ tdTestDirRead(sDirectory = self.oTestFiles.oTreeDir.sPath),
2965 tdTestResultDirRead(fRc = True, cFiles = self.oTestFiles.cTreeFiles, cDirs = self.oTestFiles.cTreeDirs,
2966 cOthers = self.oTestFiles.cTreeOthers) ],
2967 ]);
2968
2969
2970 fRc = True;
2971 for (i, tTest) in enumerate(atTests):
2972 oCurTest = tTest[0] # type: tdTestExec
2973 oCurRes = tTest[1] # type: tdTestResultDirRead
2974
2975 reporter.log('Testing #%d, dir="%s" ...' % (i, oCurTest.sDirectory));
2976 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2977 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: Test #%d' % (i,), True);
2978 if fRc is not True:
2979 break;
2980 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc);
2981 fRc = oCurTest.closeSession(True) and fRc;
2982
2983 reporter.log2('Test #%d: Returned %d directories, %d files total' % (i, cDirs, cFiles));
2984 if fRc2 is oCurRes.fRc:
2985 if fRc2 is True:
2986 if oCurRes.cFiles is None:
2987 pass; # ignore
2988 elif oCurRes.cFiles >= 0 and cFiles != oCurRes.cFiles:
2989 fRc = reporter.error('Test #%d failed: Got %d files, expected %d' % (i, cFiles, oCurRes.cFiles));
2990 elif oCurRes.cFiles < 0 and cFiles < -oCurRes.cFiles:
2991 fRc = reporter.error('Test #%d failed: Got %d files, expected at least %d'
2992 % (i, cFiles, -oCurRes.cFiles));
2993 if oCurRes.cDirs is None:
2994 pass; # ignore
2995 elif oCurRes.cDirs >= 0 and cDirs != oCurRes.cDirs:
2996 fRc = reporter.error('Test #%d failed: Got %d directories, expected %d' % (i, cDirs, oCurRes.cDirs));
2997 elif oCurRes.cDirs < 0 and cDirs < -oCurRes.cDirs:
2998 fRc = reporter.error('Test #%d failed: Got %d directories, expected at least %d'
2999 % (i, cDirs, -oCurRes.cDirs));
3000 if oCurRes.cOthers is None:
3001 pass; # ignore
3002 elif oCurRes.cOthers >= 0 and cOthers != oCurRes.cOthers:
3003 fRc = reporter.error('Test #%d failed: Got %d other types, expected %d' % (i, cOthers, oCurRes.cOthers));
3004 elif oCurRes.cOthers < 0 and cOthers < -oCurRes.cOthers:
3005 fRc = reporter.error('Test #%d failed: Got %d other types, expected at least %d'
3006 % (i, cOthers, -oCurRes.cOthers));
3007
3008 else:
3009 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3010
3011
3012 #
3013 # Go over a few directories in the test file set and compare names,
3014 # types and sizes rather than just the counts like we did above.
3015 #
3016 if fRc is True:
3017 oCurTest = tdTestDirRead();
3018 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3019 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: gctrlReadDirTree2', True);
3020 if fRc is True:
3021 for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir):
3022 reporter.log('Checking "%s" ...' % (oDir.sPath,));
3023 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir) and fRc;
3024 fRc = oCurTest.closeSession(True) and fRc;
3025
3026 return (fRc, oTxsSession);
3027
3028 def testGuestCtrlFileRemove(self, oSession, oTxsSession, oTestVm):
3029 """
3030 Tests removing guest files.
3031 """
3032
3033 ## @todo r=bird: This fails on windows 7 RTM. Just create a stupid file and delete it again,
3034 # this chord.wav stuff is utter nonsense.
3035 if oTestVm.isWindows():
3036 sFileToDelete = "c:\\Windows\\Media\\chord.wav";
3037 else:
3038 sFileToDelete = "/home/vbox/.profile";
3039
3040 atTests = [];
3041 if oTestVm.isWindows():
3042 atTests.extend([
3043 # Invalid stuff.
3044 [ tdTestFileRemove(sFile = ''), tdTestResultFailure() ],
3045 [ tdTestFileRemove(sFile = 'C:\\Windows'), tdTestResultFailure() ],
3046 # More unusual stuff.
3047 [ tdTestFileRemove(sFile = 'z:\\'), tdTestResultFailure() ],
3048 [ tdTestFileRemove(sFile = '\\\\uncrulez\\foo'), tdTestResultFailure() ],
3049 # Non-existing stuff.
3050 [ tdTestFileRemove(sFile = 'c:\\Apps\\nonexisting'), tdTestResultFailure() ],
3051 # Try to delete system files.
3052 [ tdTestFileRemove(sFile = 'c:\\pagefile.sys'), tdTestResultFailure() ],
3053 [ tdTestFileRemove(sFile = 'c:\\Windows\\kernel32.sys'), tdTestResultFailure() ] ## r=bird: it's in \system32\ ...
3054 ]);
3055
3056 if oTestVm.sKind == "WindowsXP":
3057 atTests.extend([
3058 # Try delete some unimportant media stuff.
3059 [ tdTestFileRemove(sFile = 'c:\\Windows\\Media\\chimes.wav'), tdTestResultSuccess() ],
3060 # Second attempt should fail.
3061 [ tdTestFileRemove(sFile = 'c:\\Windows\\Media\\chimes.wav'), tdTestResultFailure() ]
3062 ]);
3063 elif oTestVm.isLinux():
3064 atTests.extend([
3065 # Invalid stuff.
3066 [ tdTestFileRemove(sFile = ''), tdTestResultFailure() ],
3067 [ tdTestFileRemove(sFile = 'C:\\Windows'), tdTestResultFailure() ],
3068 # More unusual stuff.
3069 [ tdTestFileRemove(sFile = 'z:/'), tdTestResultFailure() ],
3070 [ tdTestFileRemove(sFile = '//uncrulez/foo'), tdTestResultFailure() ],
3071 # Non-existing stuff.
3072 [ tdTestFileRemove(sFile = '/non/existing'), tdTestResultFailure() ],
3073 # Try to delete system files.
3074 [ tdTestFileRemove(sFile = '/etc'), tdTestResultFailure() ],
3075 [ tdTestFileRemove(sFile = '/bin/sh'), tdTestResultFailure() ]
3076 ]);
3077
3078 atTests.extend([
3079 # Try delete some unimportant stuff.
3080 [ tdTestFileRemove(sFile = sFileToDelete), tdTestResultSuccess() ],
3081 # Second attempt should fail.
3082 [ tdTestFileRemove(sFile = sFileToDelete), tdTestResultFailure() ]
3083 ]);
3084
3085 fRc = True;
3086 for (i, aTest) in enumerate(atTests):
3087 oCurTest = aTest[0]; # tdTestExec, use an index, later.
3088 oCurRes = aTest[1]; # tdTestResult
3089 reporter.log('Testing #%d, file="%s" ...' % (i, oCurTest.sFile));
3090 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3091 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileRemove: Test #%d' % (i,));
3092 if fRc is False:
3093 reporter.error('Test #%d failed: Could not create session' % (i,));
3094 break;
3095 try:
3096 if self.oTstDrv.fpApiVer >= 5.0:
3097 oCurGuestSession.fsObjRemove(oCurTest.sFile);
3098 else:
3099 oCurGuestSession.fileRemove(oCurTest.sFile);
3100 except:
3101 if oCurRes.fRc is True:
3102 reporter.errorXcpt('Removing file "%s" failed:' % (oCurTest.sFile,));
3103 fRc = False;
3104 break;
3105 else:
3106 reporter.logXcpt('Removing file "%s" failed expectedly, skipping:' % (oCurTest.sFile,));
3107 oCurTest.closeSession();
3108 return (fRc, oTxsSession);
3109
3110 def testGuestCtrlFileStat(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3111 """
3112 Tests querying file information through stat.
3113 """
3114
3115 # Basic stuff, existing stuff.
3116 aoTests = [
3117 tdTestSessionEx([ tdStepStatDir('.'),
3118 tdStepStatDir('..'),
3119 ]),
3120 ];
3121 if oTestVm.isWindows():
3122 aoTests += [ tdTestSessionEx([ tdStepStatDir('C:\\Windows'),
3123 tdStepStatDir('C:\\Windows\\System32'),
3124 tdStepStatDir('C:\\Windows\\System32\\'),
3125 tdStepStatDir('C:\\Windows\\System32\\.'),
3126 tdStepStatDir('C:\\Windows\\System32\\.\\'),
3127 tdStepStatDir('C:\\Windows\\System32\\..'),
3128 tdStepStatDir('C:\\Windows\\System32\\..\\'),
3129 tdStepStatDir('C:\\Windows\\System32\\..\\\\'),
3130 tdStepStatDir('C:\\Windows\\System32\\\\..\\\\'),
3131 tdStepStatDir('C:/Windows/System32'),
3132 tdStepStatDir('C:/Windows/System32/'),
3133 tdStepStatDir('c:/winDowS/sYsTeM32/'),
3134 tdStepStatDir('C:/Windows/System32/.'),
3135 tdStepStatDir('C:/Windows/System32/./'),
3136 tdStepStatDir('C:/Windows/System32/..'),
3137 tdStepStatDir('C:/Windows/System32/../'),
3138 tdStepStatDir('C:/Windows/System32/..//'),
3139 tdStepStatDir('C:/Windows/System32//..//'),
3140 tdStepStatFile('C:\\Windows\\System32\\kernel32.dll'),
3141 tdStepStatFile('C:/Windows/System32/kernel32.dll')
3142 ]) ];
3143 elif oTestVm.isOS2():
3144 aoTests += [ tdTestSessionEx([ tdStepStatDir('C:\\OS2'),
3145 tdStepStatDir('C:\\OS2\\DLL'),
3146 tdStepStatDir('C:\\OS2\\DLL\\'),
3147 tdStepStatDir('C:/OS2/DLL'),
3148 tdStepStatDir('c:/OS2/DLL'),
3149 tdStepStatDir('c:/OS2/DLL/'),
3150 tdStepStatFile('C:\\CONFIG.SYS'),
3151 tdStepStatFile('C:\\OS2\\DLL\\DOSCALL1.DLL'),
3152 ]) ];
3153 else: # generic unix.
3154 aoTests += [ tdTestSessionEx([ tdStepStatDir('/'),
3155 tdStepStatDir('///'),
3156 tdStepStatDir('/usr/bin/.'),
3157 tdStepStatDir('/usr/bin/./'),
3158 tdStepStatDir('/usr/bin/..'),
3159 tdStepStatDir('/usr/bin/../'),
3160 tdStepStatFile('/bin/ls'),
3161 tdStepStatFile('/bin/cp'),
3162 tdStepStatFile('/bin/date'),
3163 ]) ];
3164 # None existing stuff.
3165 if oTestVm.isWindows() or oTestVm.isOS2():
3166 aoTests += [ tdTestSessionEx([ tdStepStatFileNotFound('C:\\NoSuchFileOrDirectory', ),
3167 tdStepStatPathNotFound('C:\\NoSuchDirectory\\'),
3168 tdStepStatPathNotFound('C:/NoSuchDirectory/'),
3169 tdStepStatPathNotFound('C:\\NoSuchDirectory\\.'),
3170 tdStepStatPathNotFound('C:/NoSuchDirectory/.'),
3171 tdStepStatPathNotFound('C:\\NoSuchDirectory\\NoSuchFileOrDirectory'),
3172 tdStepStatPathNotFound('C:/NoSuchDirectory/NoSuchFileOrDirectory'),
3173 tdStepStatPathNotFound('C:/NoSuchDirectory/NoSuchFileOrDirectory/'),
3174 tdStepStatPathNotFound('N:\\'), # ASSUMES nothing mounted on N:!
3175 tdStepStatPathNotFound('\\\\NoSuchUncServerName\\NoSuchShare'),
3176 ]) ];
3177 else: # generic unix.
3178 aoTests += [ tdTestSessionEx([ tdStepStatFileNotFound('/NoSuchFileOrDirectory', ),
3179 tdStepStatFileNotFound('/bin/NoSuchFileOrDirectory'),
3180 tdStepStatPathNotFound('/NoSuchDirectory/'),
3181 tdStepStatPathNotFound('/NoSuchDirectory/.'),
3182 ]) ];
3183 # Invalid parameter check.
3184 aoTests += [ tdTestSessionEx([ tdStepStat('', vbox.ComError.E_INVALIDARG), ]), ];
3185
3186 # Some test VM specific tests.
3187 if oTestVm.sVmName.startswith('tst-xpsp2'):
3188 aoTests += [ tdTestSessionEx([ tdStepStatFileSize('c:\\Windows\\system32\\kernel32.dll', 983552), ]) ];
3189
3190 #
3191 # Execute the tests.
3192 #
3193 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'FsStat');
3194
3195 def testGuestCtrlFileRead(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3196 """
3197 Tests reading from guest files.
3198 """
3199
3200 if oTxsSession.syncMkDir('${SCRATCH}/testGuestCtrlFileRead') is False:
3201 reporter.error('Could not create scratch directory on guest');
3202 return (False, oTxsSession);
3203
3204 atTests = [];
3205 atTests.extend([
3206 # Invalid stuff.
3207 [ tdTestFileReadWrite(cbToReadWrite = 0), tdTestResultFileReadWrite() ],
3208 [ tdTestFileReadWrite(sFile = ''), tdTestResultFileReadWrite() ],
3209 [ tdTestFileReadWrite(sFile = 'non-existing.file'), tdTestResultFileReadWrite() ],
3210 # Wrong open mode.
3211 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'rt', sDisposition = 'oe'),
3212 tdTestResultFileReadWrite() ],
3213 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'tr', sDisposition = 'oe'),
3214 tdTestResultFileReadWrite() ],
3215 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'wr', sDisposition = 'oe'),
3216 tdTestResultFileReadWrite() ],
3217 # Wrong disposition.
3218 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'r', sDisposition = 'e'),
3219 tdTestResultFileReadWrite() ],
3220 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'r', sDisposition = 'o'),
3221 tdTestResultFileReadWrite() ],
3222 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'r', sDisposition = 'c'),
3223 tdTestResultFileReadWrite() ],
3224 # Opening non-existing file when it should exist.
3225 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3226 tdTestResultFileReadWrite() ],
3227 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3228 tdTestResultFileReadWrite() ],
3229 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3230 tdTestResultFileReadWrite() ]
3231 ]);
3232
3233 if oTestVm.isWindows():
3234 atTests.extend([
3235 # Create a file which must not exist (but it hopefully does).
3236 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\calc.exe', sOpenMode = 'w', sDisposition = 'ce'),
3237 tdTestResultFileReadWrite() ],
3238 # Open a file which must exist.
3239 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\kernel32.dll', sOpenMode = 'r', sDisposition = 'oe'),
3240 tdTestResultFileReadWrite(fRc = True) ],
3241 # Try truncating a file which already is opened with a different sharing mode (and thus should fail).
3242 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\kernel32.dll', sOpenMode = 'w', sDisposition = 'ot'),
3243 tdTestResultFileReadWrite() ]
3244 ]);
3245
3246 # Note: tst-xppro has other contents in eula.txt.
3247 if oTestVm.sVmName.startswith('tst-xpsp2'):
3248 atTests.extend([
3249 # Reading from beginning.
3250 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\eula.txt',
3251 sOpenMode = 'r', sDisposition = 'oe', cbToReadWrite = 33),
3252 tdTestResultFileReadWrite(fRc = True, abBuf = 'Microsoft(r) Windows(r) XP Profes',
3253 cbProcessed = 33, offFile = 33) ],
3254 # Reading from offset.
3255 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\eula.txt',
3256 sOpenMode = 'r', sDisposition = 'oe', offFile = 17769, cbToReadWrite = 31),
3257 tdTestResultFileReadWrite(fRc = True, abBuf = 'only with the HARDWARE. If\x0d\x0a ',
3258 cbProcessed = 31, offFile = 17769 + 31) ]
3259 ]);
3260 elif oTestVm.isLinux():
3261 atTests.extend([
3262 # Create a file which must not exist (but it hopefully does).
3263 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'w', sDisposition = 'ce'),
3264 tdTestResultFileReadWrite() ],
3265 # Open a file which must exist.
3266 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'r', sDisposition = 'oe'),
3267 tdTestResultFileReadWrite(fRc = True) ],
3268 # Try truncating a file which already is opened with a different sharing mode (and thus should fail).
3269 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'w', sDisposition = 'ot'),
3270 tdTestResultFileReadWrite() ]
3271 ]);
3272
3273 fRc = True;
3274 for (i, aTest) in enumerate(atTests):
3275 oCurTest = aTest[0]; # tdTestFileReadWrite, use an index, later.
3276 oCurRes = aTest[1]; # tdTestResult
3277 reporter.log('Testing #%d, sFile="%s", cbToReadWrite=%d, sOpenMode="%s", sDisposition="%s", offFile=%d ...'
3278 % (i, oCurTest.sFile, oCurTest.cbToReadWrite, oCurTest.sOpenMode,
3279 oCurTest.sDisposition, oCurTest.offFile));
3280 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3281 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileRead: Test #%d' % (i,));
3282 if fRc is False:
3283 reporter.error('Test #%d failed: Could not create session' % (i,));
3284 break;
3285 try:
3286 fRc2 = True;
3287 if oCurTest.offFile > 0: # The offset parameter is gone.
3288 if self.oTstDrv.fpApiVer >= 5.0:
3289 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3290 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3291 curFile.seek(oCurTest.offFile, vboxcon.FileSeekOrigin_Begin);
3292 else:
3293 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3294 oCurTest.sSharingMode, oCurTest.fCreationMode, oCurTest.offFile);
3295 curOffset = long(curFile.offset);
3296 resOffset = long(oCurTest.offFile);
3297 if curOffset != resOffset:
3298 reporter.error('Test #%d failed: Initial offset on open does not match: Got %d, expected %d'
3299 % (i, curOffset, resOffset));
3300 fRc2 = False;
3301 else:
3302 if self.oTstDrv.fpApiVer >= 5.0:
3303 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3304 oCurTest.fCreationMode);
3305 else:
3306 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3307 oCurTest.fCreationMode);
3308 if fRc2 and oCurTest.cbToReadWrite > 0:
3309 ## @todo Split this up in 64K reads. Later.
3310 ## @todo Test timeouts.
3311 aBufRead = curFile.read(oCurTest.cbToReadWrite, 30 * 1000);
3312 if oCurRes.cbProcessed > 0 \
3313 and oCurRes.cbProcessed != len(aBufRead):
3314 reporter.error('Test #%d failed: Read buffer length does not match: Got %d, expected %d'
3315 % (i, len(aBufRead), oCurRes.cbProcessed));
3316 fRc2 = False;
3317 if fRc2:
3318 if oCurRes.abBuf is not None \
3319 and not utils.areBytesEqual(oCurRes.abBuf, aBufRead):
3320 reporter.error('Test #%d failed: Got buffer:\n"%s" (%d bytes, type %s)\n'
3321 'Expected buffer:\n"%s" (%d bytes, type %s)'
3322 % (i, map(hex, map(ord, aBufRead)), len(aBufRead), type(aBufRead),
3323 map(hex, map(ord, oCurRes.abBuf)), len(oCurRes.abBuf), type(oCurRes.abBuf),));
3324 reporter.error('Test #%d failed: Got buffer:\n"%s"\nExpected buffer:\n"%s"'
3325 % (i, aBufRead, oCurRes.abBuf));
3326 fRc2 = False;
3327 # Test final offset.
3328 curOffset = long(curFile.offset);
3329 resOffset = long(oCurRes.offFile);
3330 if curOffset != resOffset:
3331 reporter.error('Test #%d failed: Final offset does not match: Got %d, expected %d' \
3332 % (i, curOffset, resOffset));
3333 fRc2 = False;
3334 curFile.close();
3335
3336 if fRc2 != oCurRes.fRc:
3337 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3338 fRc = False;
3339
3340 except:
3341 reporter.logXcpt('Opening "%s" failed:' % (oCurTest.sFile,));
3342 fRc = False;
3343
3344 oCurTest.closeSession();
3345
3346 return (fRc, oTxsSession);
3347
3348 def testGuestCtrlFileWrite(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3349 """
3350 Tests writing to guest files.
3351 """
3352
3353 if oTestVm.isWindows():
3354 sScratch = "C:\\Temp\\vboxtest\\testGuestCtrlFileWrite\\";
3355 else:
3356 sScratch = "/tmp/";
3357
3358 if oTxsSession.syncMkDir('${SCRATCH}/testGuestCtrlFileWrite') is False:
3359 reporter.error('Could not create scratch directory on guest');
3360 return (False, oTxsSession);
3361
3362 atTests = [];
3363
3364 cbScratchBuf = random.randint(1, 4096);
3365 abScratchBuf = os.urandom(cbScratchBuf);
3366 atTests.extend([
3367 # Write to a non-existing file.
3368 [ tdTestFileReadWrite(sFile = sScratch + 'testGuestCtrlFileWrite.txt',
3369 sOpenMode = 'w+', sDisposition = 'ce', cbToReadWrite = cbScratchBuf, abBuf = abScratchBuf),
3370 tdTestResultFileReadWrite(fRc = True, abBuf = abScratchBuf, cbProcessed = cbScratchBuf, offFile = cbScratchBuf) ],
3371 ]);
3372
3373 aScratchBuf2 = os.urandom(cbScratchBuf);
3374 atTests.extend([
3375 # Append the same amount of data to the just created file.
3376 [ tdTestFileReadWrite(sFile = sScratch + 'testGuestCtrlFileWrite.txt',
3377 sOpenMode = 'w+', sDisposition = 'oa', cbToReadWrite = cbScratchBuf,
3378 offFile = cbScratchBuf, abBuf = aScratchBuf2),
3379 tdTestResultFileReadWrite(fRc = True, abBuf = aScratchBuf2, cbProcessed = cbScratchBuf,
3380 offFile = cbScratchBuf * 2) ],
3381 ]);
3382
3383 fRc = True;
3384 for (i, aTest) in enumerate(atTests):
3385 oCurTest = aTest[0]; # tdTestFileReadWrite, use an index, later.
3386 oCurRes = aTest[1]; # tdTestResult
3387 reporter.log('Testing #%d, sFile="%s", cbToReadWrite=%d, sOpenMode="%s", sDisposition="%s", offFile=%d ...'
3388 % (i, oCurTest.sFile, oCurTest.cbToReadWrite, oCurTest.sOpenMode,
3389 oCurTest.sDisposition, oCurTest.offFile,));
3390 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3391 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileWrite: Test #%d' % (i,));
3392 if fRc is False:
3393 reporter.error('Test #%d failed: Could not create session' % (i,));
3394 break;
3395
3396 try:
3397 if oCurTest.offFile > 0: # The offset parameter is gone.
3398 if self.oTstDrv.fpApiVer >= 5.0:
3399 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3400 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3401 curFile.seek(oCurTest.offFile, vboxcon.FileSeekOrigin_Begin);
3402 else:
3403 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3404 oCurTest.sSharingMode, oCurTest.fCreationMode, oCurTest.offFile);
3405 curOffset = long(curFile.offset);
3406 resOffset = long(oCurTest.offFile);
3407 if curOffset != resOffset:
3408 reporter.error('Test #%d failed: Initial offset on open does not match: Got %d, expected %d' \
3409 % (i, curOffset, resOffset));
3410 fRc = False;
3411 else:
3412 if self.oTstDrv.fpApiVer >= 5.0:
3413 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3414 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3415 else:
3416 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3417 oCurTest.fCreationMode);
3418 if fRc and oCurTest.cbToReadWrite > 0:
3419 reporter.log("File '%s' opened" % oCurTest.sFile);
3420 ## @todo Split this up in 64K writes. Later.
3421 ## @todo Test timeouts.
3422 cBytesWritten = curFile.write(array('b', oCurTest.abBuf), 30 * 1000);
3423 if oCurRes.cbProcessed > 0 \
3424 and oCurRes.cbProcessed != cBytesWritten:
3425 reporter.error('Test #%d failed: Written buffer length does not match: Got %d, expected %d' \
3426 % (i, cBytesWritten, oCurRes.cbProcessed));
3427 fRc = False;
3428 if fRc:
3429 # Verify written content by seeking back to the initial offset and
3430 # re-read & compare the written data.
3431 try:
3432 if self.oTstDrv.fpApiVer >= 5.0:
3433 curFile.seek(-(oCurTest.cbToReadWrite), vboxcon.FileSeekOrigin_Current);
3434 else:
3435 curFile.seek(-(oCurTest.cbToReadWrite), vboxcon.FileSeekType_Current);
3436 except:
3437 reporter.logXcpt('Seeking back to initial write position failed:');
3438 fRc = False;
3439 if fRc and long(curFile.offset) != oCurTest.offFile:
3440 reporter.error('Test #%d failed: Initial write position does not match current position, ' \
3441 'got %d, expected %d' % (i, long(curFile.offset), oCurTest.offFile));
3442 fRc = False;
3443 if fRc:
3444 aBufRead = curFile.read(oCurTest.cbToReadWrite, 30 * 1000);
3445 if len(aBufRead) != oCurTest.cbToReadWrite:
3446 reporter.error('Test #%d failed: Got buffer length %d, expected %d' \
3447 % (i, len(aBufRead), oCurTest.cbToReadWrite));
3448 fRc = False;
3449 if fRc \
3450 and oCurRes.abBuf is not None \
3451 and bytes(oCurRes.abBuf) != bytes(aBufRead):
3452 reporter.error('Test #%d failed: Read back buffer (%d bytes) does not match ' \
3453 'written content (%d bytes)' % (i, len(aBufRead), len(aBufRead)));
3454
3455 curFile.close();
3456
3457 # Download written file from guest.
3458 aGstFiles = [];
3459 aGstFiles.append(oCurTest.sFile.replace('\\', '/'));
3460 self.oTstDrv.txsDownloadFiles(oSession, oTxsSession, aGstFiles, fIgnoreErrors = True);
3461
3462 # Create files with buffer contents and upload those for later (manual) inspection.
3463 oCurTest.uploadLogData(self.oTstDrv, oCurRes.abBuf, ('testGuestCtrlWriteTest%d-BufExcepted' % i),
3464 ('Test #%d: Expected buffer' % i));
3465 oCurTest.uploadLogData(self.oTstDrv, aBufRead, ('testGuestCtrlWriteTest%d-BufGot' % i),
3466 ('Test #%d: Got buffer' % i));
3467 fRc = False;
3468 # Test final offset.
3469 curOffset = long(curFile.offset);
3470 resOffset = long(oCurRes.offFile);
3471 if curOffset != resOffset:
3472 reporter.error('Test #%d failed: Final offset does not match: Got %d, expected %d' \
3473 % (i, curOffset, resOffset));
3474 fRc = False;
3475 if curFile.status == vboxcon.FileStatus_Open:
3476 curFile.close();
3477 reporter.log("File '%s' closed" % oCurTest.sFile);
3478 except:
3479 reporter.logXcpt('Opening "%s" failed:' % (oCurTest.sFile,));
3480 fRc = False;
3481
3482 oCurTest.closeSession();
3483
3484 if fRc != oCurRes.fRc:
3485 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
3486 fRc = False;
3487 break;
3488
3489 return (fRc, oTxsSession);
3490
3491 @staticmethod
3492 def __generateFile(sName, cbFile):
3493 """ Helper for generating a file with a given size. """
3494 oFile = open(sName, 'wb');
3495 while cbFile > 0:
3496 cb = cbFile if cbFile < 256*1024 else 256*1024;
3497 oFile.write(bytearray(random.getrandbits(8) for _ in xrange(cb)));
3498 cbFile -= cb;
3499 oFile.close();
3500
3501 def testGuestCtrlCopyTo(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3502 """
3503 Tests copying files from host to the guest.
3504 """
3505
3506 #
3507 # Paths and test files.
3508 #
3509 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, 'cp2');
3510 sScratchTestFilesHst = os.path.join(sScratchHst, self.oTestFiles.sSubDir);
3511 sScratchEmptyDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oEmptyDir.sName);
3512 sScratchNonEmptyDirHst = self.oTestFiles.chooseRandomDirFromTree().buildPath(sScratchHst, os.path.sep);
3513 sScratchTreeDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oTreeDir.sName);
3514
3515 sScratchGst = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'cp2');
3516 sScratchDstDir1Gst = oTestVm.pathJoin(sScratchGst, 'dstdir1');
3517 sScratchDstDir2Gst = oTestVm.pathJoin(sScratchGst, 'dstdir2');
3518 sScratchDstDir3Gst = oTestVm.pathJoin(sScratchGst, 'dstdir3');
3519 sScratchDstDir4Gst = oTestVm.pathJoin(sScratchGst, 'dstdir4');
3520 #sScratchGstNotExist = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'no-such-file-or-directory');
3521 sScratchHstNotExist = os.path.join(self.oTstDrv.sScratchPath, 'no-such-file-or-directory');
3522 sScratchGstPathNotFound = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'no-such-directory', 'or-file');
3523 #sScratchHstPathNotFound = os.path.join(self.oTstDrv.sScratchPath, 'no-such-directory', 'or-file');
3524
3525 if oTestVm.isWindows() or oTestVm.isOS2():
3526 sScratchGstInvalid = "?*|<invalid-name>";
3527 else:
3528 sScratchGstInvalid = None;
3529 if utils.getHostOs() in ('win', 'os2'):
3530 sScratchHstInvalid = "?*|<invalid-name>";
3531 else:
3532 sScratchHstInvalid = None;
3533
3534 for sDir in (sScratchGst, sScratchDstDir1Gst, sScratchDstDir2Gst, sScratchDstDir3Gst, sScratchDstDir4Gst):
3535 if oTxsSession.syncMkDir(sDir) is not True:
3536 return reporter.error('TXS failed to create directory "%s"!' % (sDir,));
3537
3538 # Put the test file set under sScratchHst.
3539 if os.path.exists(sScratchHst):
3540 if base.wipeDirectory(sScratchHst) != 0:
3541 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
3542 else:
3543 try:
3544 os.mkdir(sScratchHst);
3545 except:
3546 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
3547 if self.oTestFiles.writeToDisk(sScratchHst) is not True:
3548 return reporter.error('Filed to write test files to "%s" on the host!' % (sScratchHst,));
3549
3550 # Generate a test file in 32MB to 64 MB range.
3551 sBigFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-random.data');
3552 cbBigFileHst = random.randrange(32*1024*1024, 64*1024*1024);
3553 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
3554 cbLeft = cbBigFileHst;
3555 try:
3556 self.__generateFile(sBigFileHst, cbBigFileHst);
3557 except:
3558 return reporter.errorXcpt('sBigFileHst=%s cbBigFileHst=%s cbLeft=%s' % (sBigFileHst, cbBigFileHst, cbLeft,));
3559 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
3560
3561 # Generate an empty file on the host that we can use to save space in the guest.
3562 sEmptyFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-empty.data');
3563 try:
3564 oFile = open(sEmptyFileHst, "wb");
3565 oFile.close();
3566 except:
3567 return reporter.errorXcpt('sEmptyFileHst=%s' % (sEmptyFileHst,));
3568
3569 #
3570 # Tests.
3571 #
3572 atTests = [
3573 # Nothing given:
3574 [ tdTestCopyToFile(), tdTestResultFailure() ],
3575 [ tdTestCopyToDir(), tdTestResultFailure() ],
3576 # Only source given:
3577 [ tdTestCopyToFile(sSrc = sBigFileHst), tdTestResultFailure() ],
3578 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst), tdTestResultFailure() ],
3579 # Only destination given:
3580 [ tdTestCopyToFile(sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')), tdTestResultFailure() ],
3581 [ tdTestCopyToDir( sDst = sScratchGst), tdTestResultFailure() ],
3582 ];
3583 if not self.fSkipKnownBugs:
3584 atTests.extend([
3585 ## @todo Apparently Main doesn't check the flags, so the first test succeeds.
3586 # Both given, but invalid flags.
3587 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst, fFlags = [ 0x40000000] ), tdTestResultFailure() ],
3588 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGst, fFlags = [ 0x40000000] ),
3589 tdTestResultFailure() ],
3590 ]);
3591 atTests.extend([
3592 # Non-existing source, but no destination:
3593 [ tdTestCopyToFile(sSrc = sScratchHstNotExist), tdTestResultFailure() ],
3594 [ tdTestCopyToDir( sSrc = sScratchHstNotExist), tdTestResultFailure() ],
3595 # Valid sources, but destination path not found:
3596 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
3597 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
3598 # Valid destination, but source file/dir not found:
3599 [ tdTestCopyToFile(sSrc = sScratchHstNotExist, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
3600 tdTestResultFailure() ],
3601 [ tdTestCopyToDir( sSrc = sScratchHstNotExist, sDst = sScratchGst), tdTestResultFailure() ],
3602 # Wrong type:
3603 [ tdTestCopyToFile(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
3604 tdTestResultFailure() ],
3605 [ tdTestCopyToDir( sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultFailure() ],
3606 ]);
3607 # Invalid characters in destination or source path:
3608 if sScratchGstInvalid is not None:
3609 atTests.extend([
3610 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
3611 tdTestResultFailure() ],
3612 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
3613 tdTestResultFailure() ],
3614 ]);
3615 if sScratchHstInvalid is not None:
3616 atTests.extend([
3617 [ tdTestCopyToFile(sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
3618 tdTestResultFailure() ],
3619 [ tdTestCopyToDir( sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
3620 tdTestResultFailure() ],
3621 ]);
3622
3623 #
3624 # Single file handling.
3625 #
3626 atTests.extend([
3627 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')),
3628 tdTestResultSuccess() ],
3629 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
3630 tdTestResultSuccess() ],
3631 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
3632 tdTestResultSuccess() ],
3633 ]);
3634 if self.oTstDrv.fpApiVer > 5.2: # Copying files into directories via Main is supported only 6.0 and later.
3635 atTests.extend([
3636 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ],
3637 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ], # Overwrite
3638 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, os.path.split(sBigFileHst)[1])),
3639 tdTestResultSuccess() ], # Overwrite
3640 ]);
3641
3642 if oTestVm.isWindows():
3643 # Copy to a Windows alternative data stream (ADS).
3644 atTests.extend([
3645 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = os.path.join(sScratchGst, 'HostGABig.dat:ADS-Test')),
3646 tdTestResultSuccess() ],
3647 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = os.path.join(sScratchGst, 'HostGABig.dat:ADS-Test')),
3648 tdTestResultSuccess() ],
3649 ]);
3650
3651 #
3652 # Directory handling.
3653 #
3654 if self.oTstDrv.fpApiVer > 5.2: # Copying directories via Main is supported only in versions > 5.2.
3655 atTests.extend([
3656 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultSuccess() ],
3657 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultFailure() ],
3658 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
3659 fFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
3660 # Try again with trailing slash, should yield the same result:
3661 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
3662 tdTestResultSuccess() ],
3663 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
3664 tdTestResultFailure() ],
3665 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep(),
3666 fFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]),
3667 tdTestResultSuccess() ],
3668 ]);
3669 if not self.fSkipKnownBugs:
3670 atTests.extend([
3671 # Copy with a different destination name just for the heck of it:
3672 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchDstDir1Gst, 'empty2')),
3673 tdTestResultSuccess() ],
3674 ]);
3675 atTests.extend([
3676 # Now the same using a directory with files in it:
3677 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst), tdTestResultSuccess() ],
3678 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst), tdTestResultFailure() ],
3679 ]);
3680 if not self.fSkipKnownBugs:
3681 atTests.extend([
3682 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
3683 fFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
3684 ]);
3685 atTests.extend([
3686 #[ tdTestRemoveGuestDir(sScratchDstDir2Gst, tdTestResult() ],
3687 # Copy the entire test tree:
3688 [ tdTestCopyToDir(sSrc = sScratchTreeDirHst, sDst = sScratchDstDir4Gst), tdTestResultSuccess() ],
3689 #[ tdTestRemoveGuestDir(sScratchDstDir3Gst, tdTestResult() ],
3690 ]);
3691
3692 fRc = True;
3693 for (i, tTest) in enumerate(atTests):
3694 oCurTest = tTest[0]; # tdTestCopyTo
3695 oCurRes = tTest[1]; # tdTestResult
3696 reporter.log('Testing #%d, sSrc=%s, sDst=%s, fFlags=%s ...' % (i, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags));
3697
3698 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3699 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyTo: Test #%d' % (i,), fIsError = True);
3700 if fRc is not True:
3701 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3702 break;
3703
3704 fRc2 = False;
3705 if isinstance(oCurTest, tdTestCopyToFile):
3706 fRc2 = self.gctrlCopyFileTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags, oCurRes.fRc);
3707 else:
3708 fRc2 = self.gctrlCopyDirTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags, oCurRes.fRc);
3709 if fRc2 is not oCurRes.fRc:
3710 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3711
3712 fRc = oCurTest.closeSession(True) and fRc;
3713
3714 return (fRc, oTxsSession);
3715
3716 def testGuestCtrlCopyFrom(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3717 """
3718 Tests copying files from guest to the host.
3719 """
3720
3721 #
3722 # Paths.
3723 #
3724 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom");
3725 sScratchDstDir1Hst = os.path.join(sScratchHst, "dstdir1");
3726 sScratchDstDir2Hst = os.path.join(sScratchHst, "dstdir2");
3727 sScratchDstDir3Hst = os.path.join(sScratchHst, "dstdir3");
3728 oExistingFileGst = self.oTestFiles.chooseRandomFile();
3729 oNonEmptyDirGst = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True);
3730 oEmptyDirGst = self.oTestFiles.oEmptyDir;
3731
3732 if oTestVm.isWindows() or oTestVm.isOS2():
3733 sScratchGstInvalid = "?*|<invalid-name>";
3734 else:
3735 sScratchGstInvalid = None;
3736 if utils.getHostOs() in ('win', 'os2'):
3737 sScratchHstInvalid = "?*|<invalid-name>";
3738 else:
3739 sScratchHstInvalid = None;
3740
3741 if os.path.exists(sScratchHst):
3742 if base.wipeDirectory(sScratchHst) != 0:
3743 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
3744 else:
3745 try:
3746 os.mkdir(sScratchHst);
3747 except:
3748 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
3749
3750 for sSubDir in (sScratchDstDir1Hst, sScratchDstDir2Hst, sScratchDstDir3Hst):
3751 try:
3752 os.mkdir(sSubDir);
3753 except:
3754 return reporter.errorXcpt('os.mkdir(%s)' % (sSubDir, ));
3755
3756 #
3757 # Bad parameter tests.
3758 #
3759 atTests = [
3760 # Missing both source and destination:
3761 [ tdTestCopyFromFile(), tdTestResultFailure() ],
3762 [ tdTestCopyFromDir(), tdTestResultFailure() ],
3763 # Missing source.
3764 [ tdTestCopyFromFile(sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3765 [ tdTestCopyFromDir( sDst = sScratchHst), tdTestResultFailure() ],
3766 # Missing destination.
3767 [ tdTestCopyFromFile(oSrc = oExistingFileGst), tdTestResultFailure() ],
3768 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath), tdTestResultFailure() ],
3769 ##
3770 ## @todo main isn't validating flags, so these theses will succeed.
3771 ##
3772 ## Invalid flags:
3773 #[ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somefile'), fFlags = [ 0x40000000] ),
3774 # tdTestResultFailure() ],
3775 #[ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'somedir'), fFlags = [ 0x40000000] ),
3776 # tdTestResultFailure() ],
3777 # Non-existing sources:
3778 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
3779 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3780 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
3781 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3782 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-file'),
3783 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3784 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-subdir'),
3785 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3786 # Non-existing destinations:
3787 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
3788 sDst = os.path.join(sScratchHst, 'no-such-directory', 'somefile') ), tdTestResultFailure() ],
3789 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'no-such-directory', 'somedir') ),
3790 tdTestResultFailure() ],
3791 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
3792 sDst = os.path.join(sScratchHst, 'no-such-directory-slash' + os.path.sep)),
3793 tdTestResultFailure() ],
3794 # Wrong source type:
3795 [ tdTestCopyFromFile(oSrc = oNonEmptyDirGst, sDst = os.path.join(sScratchHst, 'somefile') ), tdTestResultFailure() ],
3796 [ tdTestCopyFromDir(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somedir') ), tdTestResultFailure() ],
3797 ];
3798 # Bogus names:
3799 if sScratchHstInvalid:
3800 atTests.extend([
3801 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
3802 tdTestResultFailure() ],
3803 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
3804 tdTestResultFailure() ],
3805 ]);
3806 if sScratchGstInvalid:
3807 atTests.extend([
3808 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
3809 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3810 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
3811 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3812 ]);
3813
3814 #
3815 # Single file copying.
3816 #
3817 atTests.extend([
3818 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')),
3819 tdTestResultSuccess() ],
3820 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')), # Overwrite it
3821 tdTestResultSuccess() ],
3822 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile2')),
3823 tdTestResultSuccess() ],
3824 ]);
3825 if self.oTstDrv.fpApiVer >= 5.2:
3826 # Copy into a directory.
3827 atTests.extend([
3828 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst), tdTestResultSuccess() ],
3829 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst + os.path.sep), tdTestResultSuccess() ],
3830 ]);
3831
3832 #
3833 # Directory tree copying:
3834 #
3835 atTests.extend([
3836 # Copy the empty guest directory (should end up as sScratchHst/empty):
3837 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultSuccess() ],
3838 # Repeat -- this time it should fail, as the destination directory already exists (and
3839 # DirectoryCopyFlag_CopyIntoExisting is not specified):
3840 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultFailure() ],
3841 # Add the DirectoryCopyFlag_CopyIntoExisting flag being set and it should work.
3842 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst,
3843 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3844 # Try again with trailing slash, should yield the same result:
3845 [ tdTestRemoveHostDir(os.path.join(sScratchDstDir1Hst, 'empty')), tdTestResult() ],
3846 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
3847 tdTestResultSuccess() ],
3848 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
3849 tdTestResultFailure() ],
3850 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep,
3851 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3852 # Copy with a different destination name just for the heck of it:
3853 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'empty2'), fIntoDst = True),
3854 tdTestResultFailure() ],
3855 # Now the same using a directory with files in it:
3856 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultSuccess() ],
3857 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultFailure() ],
3858 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst,
3859 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3860 # Copy the entire test tree:
3861 [ tdTestCopyFromDir(sSrc = self.oTestFiles.oTreeDir.sPath, sDst = sScratchDstDir3Hst), tdTestResultSuccess() ],
3862 ]);
3863
3864 #
3865 # Execute the tests.
3866 #
3867 fRc = True;
3868 for (i, tTest) in enumerate(atTests):
3869 oCurTest = tTest[0]
3870 oCurRes = tTest[1] # type: tdTestResult
3871 if isinstance(oCurTest, tdTestCopyFrom):
3872 reporter.log('Testing #%d, %s: sSrc="%s", sDst="%s", fFlags="%s" ...'
3873 % (i, "directory" if isinstance(oCurTest, tdTestCopyFromDir) else "file",
3874 oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags,));
3875 else:
3876 reporter.log('Testing #%d, tdTestRemoveHostDir "%s" ...' % (i, oCurTest.sDir,));
3877 if isinstance(oCurTest, tdTestCopyFromDir) and self.oTstDrv.fpApiVer < 6.0:
3878 reporter.log('Skipping directoryCopyFromGuest test, not implemented in %s' % (self.oTstDrv.fpApiVer,));
3879 continue;
3880
3881 if isinstance(oCurTest, tdTestRemoveHostDir):
3882 fRc = oCurTest.execute(self.oTstDrv, oSession, oTxsSession, oTestVm, 'testing #%d' % (i,));
3883 else:
3884 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3885 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyFrom: Test #%d' % (i,), fIsError = True);
3886 if fRc2 is not True:
3887 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3888 break;
3889
3890 if isinstance(oCurTest, tdTestCopyFromFile):
3891 fRc2 = self.gctrlCopyFileFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
3892 else:
3893 fRc2 = self.gctrlCopyDirFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
3894
3895 if fRc2 != oCurRes.fRc:
3896 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3897 fRc2 = False;
3898
3899 fRc = oCurTest.closeSession(fIsError = True) and fRc;
3900
3901 return (fRc, oTxsSession);
3902
3903 def testGuestCtrlUpdateAdditions(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3904 """
3905 Tests updating the Guest Additions inside the guest.
3906
3907 """
3908
3909 # Skip test for updating Guest Additions if we run on a too old (Windows) guest.
3910 ##
3911 ## @todo make it work everywhere!
3912 ##
3913 if oTestVm.sKind in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
3914 reporter.log("Skipping updating GAs on old windows vm (sKind=%s)" % (oTestVm.sKind,));
3915 return (None, oTxsSession);
3916 if oTestVm.isOS2():
3917 reporter.log("Skipping updating GAs on OS/2 guest");
3918 return (None, oTxsSession);
3919
3920 # Some stupid trickery to guess the location of the iso.
3921 sVBoxValidationKitISO = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxValidationKit.iso'));
3922 if not os.path.isfile(sVBoxValidationKitISO):
3923 sVBoxValidationKitISO = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxTestSuite.iso'));
3924 if not os.path.isfile(sVBoxValidationKitISO):
3925 sCur = os.getcwd();
3926 for i in xrange(0, 10):
3927 sVBoxValidationKitISO = os.path.join(sCur, 'validationkit/VBoxValidationKit.iso');
3928 if os.path.isfile(sVBoxValidationKitISO):
3929 break;
3930 sVBoxValidationKitISO = os.path.join(sCur, 'testsuite/VBoxTestSuite.iso');
3931 if os.path.isfile(sVBoxValidationKitISO):
3932 break;
3933 sCur = os.path.abspath(os.path.join(sCur, '..'));
3934 if i is None: pass; # shut up pychecker/pylint.
3935 if os.path.isfile(sVBoxValidationKitISO):
3936 reporter.log('Validation Kit .ISO found at: %s' % (sVBoxValidationKitISO,));
3937 else:
3938 reporter.log('Warning: Validation Kit .ISO not found -- some tests might fail');
3939
3940 sScratch = os.path.join(self.oTstDrv.sScratchPath, "testGctrlUpdateAdditions");
3941 try:
3942 os.makedirs(sScratch);
3943 except OSError as e:
3944 if e.errno != errno.EEXIST:
3945 reporter.error('Failed: Unable to create scratch directory \"%s\"' % (sScratch,));
3946 return (False, oTxsSession);
3947 reporter.log('Scratch path is: %s' % (sScratch,));
3948
3949 atTests = [];
3950 if oTestVm.isWindows():
3951 atTests.extend([
3952 # Source is missing.
3953 [ tdTestUpdateAdditions(sSrc = ''), tdTestResultFailure() ],
3954
3955 # Wrong fFlags.
3956 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
3957 fFlags = [ 1234 ]), tdTestResultFailure() ],
3958
3959 # Non-existing .ISO.
3960 [ tdTestUpdateAdditions(sSrc = "non-existing.iso"), tdTestResultFailure() ],
3961
3962 # Wrong .ISO.
3963 [ tdTestUpdateAdditions(sSrc = sVBoxValidationKitISO), tdTestResultFailure() ],
3964
3965 # The real thing.
3966 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso()),
3967 tdTestResultSuccess() ],
3968 # Test the (optional) installer arguments. This will extract the
3969 # installer into our guest's scratch directory.
3970 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
3971 asArgs = [ '/extract', '/D=' + sScratch ]),
3972 tdTestResultSuccess() ]
3973 # Some debg ISO. Only enable locally.
3974 #[ tdTestUpdateAdditions(
3975 # sSrc = "V:\\Downloads\\VBoxGuestAdditions-r80354.iso"),
3976 # tdTestResultSuccess() ]
3977 ]);
3978 else:
3979 reporter.log('No OS-specific tests for non-Windows yet!');
3980
3981 fRc = True;
3982 for (i, aTest) in enumerate(atTests):
3983 oCurTest = aTest[0]; # tdTestExec, use an index, later.
3984 oCurRes = aTest[1]; # tdTestResult
3985 reporter.log('Testing #%d, sSrc="%s", fFlags="%s" ...' % \
3986 (i, oCurTest.sSrc, oCurTest.fFlags));
3987 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3988 fRc, _ = oCurTest.createSession('Test #%d' % (i,));
3989 if fRc is False:
3990 reporter.error('Test #%d failed: Could not create session' % (i,));
3991 break;
3992 try:
3993 oCurProgress = oCurTest.oTest.oGuest.updateGuestAdditions(oCurTest.sSrc, oCurTest.asArgs, oCurTest.fFlags);
3994 if oCurProgress is not None:
3995 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlUpGA");
3996 try:
3997 oProgress.wait();
3998 if not oProgress.isSuccess():
3999 oProgress.logResult(fIgnoreErrors = True);
4000 fRc = False;
4001 except:
4002 reporter.logXcpt('Waiting exception for updating Guest Additions:');
4003 fRc = False;
4004 else:
4005 reporter.error('No progress object returned');
4006 fRc = False;
4007 except:
4008 # Just log, don't assume an error here (will be done in the main loop then).
4009 reporter.logXcpt('Updating Guest Additions exception for sSrc="%s", fFlags="%s":' \
4010 % (oCurTest.sSrc, oCurTest.fFlags));
4011 fRc = False;
4012 oCurTest.closeSession();
4013 if fRc is oCurRes.fRc:
4014 if fRc:
4015 ## @todo Verify if Guest Additions were really updated (build, revision, ...).
4016 pass;
4017 else:
4018 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
4019 fRc = False;
4020 break;
4021
4022 return (fRc, oTxsSession);
4023
4024
4025
4026class tdAddGuestCtrl(vbox.TestDriver): # pylint: disable=too-many-instance-attributes,too-many-public-methods
4027 """
4028 Guest control using VBoxService on the guest.
4029 """
4030
4031 def __init__(self):
4032 vbox.TestDriver.__init__(self);
4033 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
4034 self.asRsrcs = None;
4035 self.fQuick = False; # Don't skip lengthly tests by default.
4036 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
4037
4038 #
4039 # Overridden methods.
4040 #
4041 def showUsage(self):
4042 """
4043 Shows the testdriver usage.
4044 """
4045 rc = vbox.TestDriver.showUsage(self);
4046 reporter.log('');
4047 reporter.log('tdAddGuestCtrl Options:');
4048 reporter.log(' --quick');
4049 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
4050 return rc;
4051
4052 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
4053 """
4054 Parses the testdriver arguments from the command line.
4055 """
4056 if asArgs[iArg] == '--quick':
4057 self.parseOption(['--virt-modes', 'hwvirt'], 0);
4058 self.parseOption(['--cpu-counts', '1'], 0);
4059 self.fQuick = True;
4060 else:
4061 return vbox.TestDriver.parseOption(self, asArgs, iArg);
4062 return iArg + 1;
4063
4064 def actionConfig(self):
4065 if not self.importVBoxApi(): # So we can use the constant below.
4066 return False;
4067
4068 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
4069 sGaIso = self.getGuestAdditionsIso();
4070 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
4071
4072 def actionExecute(self):
4073 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
4074
4075 #
4076 # Test execution helpers.
4077 #
4078 def testOneCfg(self, oVM, oTestVm): # pylint: disable=too-many-statements
4079 """
4080 Runs the specified VM thru the tests.
4081
4082 Returns a success indicator on the general test execution. This is not
4083 the actual test result.
4084 """
4085
4086 self.logVmInfo(oVM);
4087
4088 fRc = True;
4089 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False);
4090 reporter.log("TxsSession: %s" % (oTxsSession,));
4091 if oSession is not None:
4092 self.addTask(oTxsSession);
4093
4094 fManual = False; # Manual override for local testing. (Committed version shall be False.)
4095 if not fManual:
4096 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
4097 else:
4098 fRc, oTxsSession = self.testGuestCtrlManual(oSession, oTxsSession, oTestVm);
4099
4100 # Cleanup.
4101 self.removeTask(oTxsSession);
4102 if not fManual:
4103 self.terminateVmBySession(oSession);
4104 else:
4105 fRc = False;
4106 return fRc;
4107
4108 def gctrlReportError(self, progress):
4109 """
4110 Helper function to report an error of a
4111 given progress object.
4112 """
4113 if progress is None:
4114 reporter.log('No progress object to print error for');
4115 else:
4116 errInfo = progress.errorInfo;
4117 if errInfo:
4118 reporter.log('%s' % (errInfo.text,));
4119 return False;
4120
4121 def gctrlGetRemainingTime(self, msTimeout, msStart):
4122 """
4123 Helper function to return the remaining time (in ms)
4124 based from a timeout value and the start time (both in ms).
4125 """
4126 if msTimeout == 0:
4127 return 0xFFFFFFFE; # Wait forever.
4128 msElapsed = base.timestampMilli() - msStart;
4129 if msElapsed > msTimeout:
4130 return 0; # No time left.
4131 return msTimeout - msElapsed;
4132
4133 def testGuestCtrlManual(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements,unused-argument,unused-variable
4134 """
4135 For manually testing certain bits.
4136 """
4137
4138 reporter.log('Manual testing ...');
4139 fRc = True;
4140
4141 sUser = 'Administrator';
4142 sPassword = 'password';
4143
4144 oGuest = oSession.o.console.guest;
4145 oGuestSession = oGuest.createSession(sUser,
4146 sPassword,
4147 "", "Manual Test");
4148
4149 aWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
4150 _ = oGuestSession.waitForArray(aWaitFor, 30 * 1000);
4151
4152 sCmd = SubTstDrvAddGuestCtrl.getGuestSystemShell(oTestVm);
4153 asArgs = [ sCmd, '/C', 'dir', '/S', 'c:\\windows' ];
4154 aEnv = [];
4155 fFlags = [];
4156
4157 for _ in xrange(100):
4158 oProc = oGuestSession.processCreate(sCmd, asArgs if self.fpApiVer >= 5.0 else asArgs[1:],
4159 aEnv, fFlags, 30 * 1000);
4160
4161 aWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate ];
4162 _ = oProc.waitForArray(aWaitFor, 30 * 1000);
4163
4164 oGuestSession.close();
4165 oGuestSession = None;
4166
4167 time.sleep(5);
4168
4169 oSession.o.console.PowerDown();
4170
4171 return (fRc, oTxsSession);
4172
4173if __name__ == '__main__':
4174 sys.exit(tdAddGuestCtrl().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