VirtualBox

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

Last change on this file since 79213 was 79213, checked in by vboxsync, 6 years ago

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette