VirtualBox

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

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

tdAddGuestCtrl.py: pylint and some other adjustments. bugref:9151 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.3 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: 79246 $"
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 #
1157 # Make sure the temporary directory exists.
1158 #
1159 for sDir in [self.getGuestTempDir(oTestVm), ]:
1160 if oTxsSession.syncMkDirPath(sDir, 0o777) is not True:
1161 return reporter.error('Failed to create directory "%s"!' % (sDir,));
1162
1163 #
1164 # Generate and upload some random files and dirs to the guest.
1165 # Note! Make sure we don't run into too-long-path issues when using
1166 # the test files on the host if.
1167 #
1168 cchGst = len(self.getGuestTempDir(oTestVm)) + 1 + len('addgst-1') + 1;
1169 cchHst = len(self.oTstDrv.sScratchPath) + 1 + len('cp2/addgst-1') + 1;
1170 cchMaxPath = 230;
1171 if cchHst > cchGst:
1172 cchMaxPath -= cchHst - cchGst;
1173 reporter.log('cchMaxPath=%s (cchHst=%s, cchGst=%s)' % (cchMaxPath, cchHst, cchGst,));
1174 self.oTestFiles = vboxtestfileset.TestFileSet(oTestVm,
1175 self.getGuestTempDir(oTestVm), 'addgst-1',
1176 cchMaxPath = cchMaxPath);
1177 return self.oTestFiles.upload(oTxsSession, self.oTstDrv);
1178
1179
1180 #
1181 # gctrlXxxx stuff.
1182 #
1183
1184 def gctrlCopyFileFrom(self, oGuestSession, oTest, fExpected):
1185 """
1186 Helper function to copy a single file from the guest to the host.
1187 """
1188 #
1189 # Do the copying.
1190 #
1191 reporter.log2('Copying guest file "%s" to host "%s"' % (oTest.sSrc, oTest.sDst));
1192 try:
1193 if self.oTstDrv.fpApiVer >= 5.0:
1194 oCurProgress = oGuestSession.fileCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.fFlags);
1195 else:
1196 oCurProgress = oGuestSession.copyFrom(oTest.sSrc, oTest.sDst, oTest.fFlags);
1197 except:
1198 reporter.maybeErrXcpt(fExpected, 'Copy from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1199 return False;
1200 if oCurProgress is None:
1201 return reporter.error('No progress object returned');
1202 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlFileCopyFrom");
1203 oProgress.wait();
1204 if not oProgress.isSuccess():
1205 oProgress.logResult(fIgnoreErrors = not fExpected);
1206 return False;
1207
1208 #
1209 # Check the result if we can.
1210 #
1211 if oTest.oSrc:
1212 assert isinstance(oTest.oSrc, testfileset.TestFile);
1213 sDst = oTest.sDst;
1214 if os.path.isdir(sDst):
1215 sDst = os.path.join(sDst, oTest.oSrc.sName);
1216 try:
1217 oFile = open(sDst, 'rb');
1218 except:
1219 return reporter.errorXcpt('open(%s) failed during verfication' % (sDst,));
1220 fEqual = oTest.oSrc.equalFile(oFile);
1221 oFile.close();
1222 if not fEqual:
1223 return reporter.error('Content differs for "%s"' % (sDst,));
1224
1225 return True;
1226
1227 def __compareTestDir(self, oDir, sHostPath): # type: (testfileset.TestDir, str) -> bool
1228 """
1229 Recursively compare the content of oDir and sHostPath.
1230
1231 Returns True on success, False + error logging on failure.
1232
1233 Note! This ASSUMES that nothing else was copied to sHostPath!
1234 """
1235 #
1236 # First check out all the entries and files in the directory.
1237 #
1238 dLeftUpper = dict(oDir.dChildrenUpper);
1239 try:
1240 asEntries = os.listdir(sHostPath);
1241 except:
1242 return reporter.errorXcpt('os.listdir(%s) failed' % (sHostPath,));
1243
1244 fRc = True;
1245 for sEntry in asEntries:
1246 sEntryUpper = sEntry.upper();
1247 if sEntryUpper not in dLeftUpper:
1248 fRc = reporter.error('Unexpected entry "%s" in "%s"' % (sEntry, sHostPath,));
1249 else:
1250 oFsObj = dLeftUpper[sEntryUpper];
1251 del dLeftUpper[sEntryUpper];
1252
1253 if isinstance(oFsObj, testfileset.TestFile):
1254 sFilePath = os.path.join(sHostPath, oFsObj.sName);
1255 try:
1256 oFile = open(sFilePath, 'rb');
1257 except:
1258 fRc = reporter.errorXcpt('open(%s) failed during verfication' % (sFilePath,));
1259 else:
1260 fEqual = oFsObj.equalFile(oFile);
1261 oFile.close();
1262 if not fEqual:
1263 fRc = reporter.error('Content differs for "%s"' % (sFilePath,));
1264
1265 # List missing entries:
1266 for sKey in dLeftUpper:
1267 oEntry = dLeftUpper[sKey];
1268 fRc = reporter.error('%s: Missing %s "%s" (src path: %s)'
1269 % (sHostPath, oEntry.sName,
1270 'file' if isinstance(oEntry, testfileset.TestFile) else 'directory', oEntry.sPath));
1271
1272 #
1273 # Recurse into subdirectories.
1274 #
1275 for oFsObj in oDir.aoChildren:
1276 if isinstance(oFsObj, testfileset.TestDir):
1277 fRc = self.__compareTestDir(oFsObj, os.path.join(sHostPath, oFsObj.sName)) and fRc;
1278 return fRc;
1279
1280 def gctrlCopyDirFrom(self, oGuestSession, oTest, fExpected):
1281 """
1282 Helper function to copy a directory from the guest to the host.
1283 """
1284 #
1285 # Do the copying.
1286 #
1287 reporter.log2('Copying guest dir "%s" to host "%s"' % (oTest.sSrc, oTest.sDst));
1288 try:
1289 oCurProgress = oGuestSession.directoryCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.fFlags);
1290 except:
1291 reporter.maybeErrXcpt(fExpected, 'Copy dir from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1292 return False;
1293 if oCurProgress is None:
1294 return reporter.error('No progress object returned');
1295
1296 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlDirCopyFrom");
1297 oProgress.wait();
1298 if not oProgress.isSuccess():
1299 oProgress.logResult(fIgnoreErrors = not fExpected);
1300 return False;
1301
1302 #
1303 # Check the result if we can.
1304 #
1305 if oTest.oSrc:
1306 assert isinstance(oTest.oSrc, testfileset.TestDir);
1307 sDst = oTest.sDst;
1308 if oTest.fIntoDst:
1309 return self.__compareTestDir(oTest.oSrc, os.path.join(sDst, oTest.oSrc.sName));
1310 oDummy = testfileset.TestDir(None, 'dummy');
1311 oDummy.aoChildren = [oTest.oSrc,]
1312 oDummy.dChildrenUpper = { oTest.oSrc.sName.upper(): oTest.oSrc, };
1313 return self.__compareTestDir(oDummy, sDst);
1314 return True;
1315
1316 def gctrlCopyFileTo(self, oGuestSession, sSrc, sDst, fFlags, fIsError):
1317 """
1318 Helper function to copy a single file from the host to the guest.
1319 """
1320 reporter.log2('Copying host file "%s" to guest "%s" (flags %s)' % (sSrc, sDst, fFlags));
1321 try:
1322 if self.oTstDrv.fpApiVer >= 5.0:
1323 oCurProgress = oGuestSession.fileCopyToGuest(sSrc, sDst, fFlags);
1324 else:
1325 oCurProgress = oGuestSession.copyTo(sSrc, sDst, fFlags);
1326 except:
1327 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1328 return False;
1329
1330 if oCurProgress is None:
1331 return reporter.error('No progress object returned');
1332 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1333
1334 try:
1335 oProgress.wait();
1336 if not oProgress.isSuccess():
1337 oProgress.logResult(fIgnoreErrors = not fIsError);
1338 return False;
1339 except:
1340 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1341 return False;
1342 return True;
1343
1344 def gctrlCopyDirTo(self, oGuestSession, sSrc, sDst, fFlags, fIsError):
1345 """
1346 Helper function to copy a directory tree from the host to the guest.
1347 """
1348 reporter.log2('Copying host directory "%s" to guest "%s" (flags %s)' % (sSrc, sDst, fFlags));
1349 try:
1350 oCurProgress = oGuestSession.directoryCopyToGuest(sSrc, sDst, fFlags);
1351 except:
1352 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1353 return False;
1354
1355 if oCurProgress is None:
1356 return reporter.error('No progress object returned');
1357 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1358
1359 try:
1360 oProgress.wait();
1361 if not oProgress.isSuccess():
1362 oProgress.logResult(fIgnoreErrors = not fIsError);
1363 return False;
1364 except:
1365 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1366 return False;
1367 return True;
1368
1369 def gctrlCreateDir(self, oTest, oRes, oGuestSession):
1370 """
1371 Helper function to create a guest directory specified in the current test.
1372 """
1373 reporter.log2('Creating directory "%s"' % (oTest.sDirectory,));
1374 try:
1375 oGuestSession.directoryCreate(oTest.sDirectory, oTest.fMode, oTest.fFlags);
1376 except:
1377 reporter.maybeErrXcpt(oRes.fRc, 'Failed to create "%s" fMode=%o fFlags=%s'
1378 % (oTest.sDirectory, oTest.fMode, oTest.fFlags,));
1379 return not oRes.fRc;
1380 if oRes.fRc is not True:
1381 return reporter.error('Did not expect to create directory "%s"!' % (oTest.sDirectory,));
1382
1383 # Check if the directory now exists.
1384 try:
1385 if self.oTstDrv.fpApiVer >= 5.0:
1386 fDirExists = oGuestSession.directoryExists(oTest.sDirectory, False);
1387 else:
1388 fDirExists = oGuestSession.directoryExists(oTest.sDirectory);
1389 except:
1390 return reporter.errorXcpt('directoryExists failed on "%s"!' % (oTest.sDirectory,));
1391 if not fDirExists:
1392 return reporter.errorXcpt('directoryExists returned False on "%s" after directoryCreate succeeded!'
1393 % (oTest.sDirectory,));
1394 return True;
1395
1396 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, sSubDir = None):
1397 """
1398 Helper function to recursively read a guest directory tree specified in the current test.
1399 """
1400 sDir = oTest.sDirectory;
1401 sFilter = oTest.sFilter;
1402 fFlags = oTest.fFlags;
1403 oTestVm = oTest.oCreds.oTestVm;
1404 sCurDir = oTestVm.pathJoin(sDir, sSubDir) if sSubDir else sDir;
1405
1406 fRc = True; # Be optimistic.
1407 cDirs = 0; # Number of directories read.
1408 cFiles = 0; # Number of files read.
1409 cOthers = 0; # Other files.
1410
1411 ##
1412 ## @todo r=bird: Unlike fileOpen, directoryOpen will not fail if the directory does not exist.
1413 ## This is of course a bug in the implementation, as it is documented to return
1414 ## VBOX_E_OBJECT_NOT_FOUND or VBOX_E_IPRT_ERROR!
1415 ##
1416
1417 # Open the directory:
1418 #reporter.log2('Directory="%s", filter="%s", fFlags="%s"' % (sCurDir, sFilter, fFlags));
1419 try:
1420 oCurDir = oGuestSession.directoryOpen(sCurDir, sFilter, fFlags);
1421 except:
1422 reporter.maybeErrXcpt(fIsError, 'sCurDir=%s sFilter=%s fFlags=%s' % (sCurDir, sFilter, fFlags,))
1423 return (False, 0, 0, 0);
1424
1425 # Read the directory.
1426 while fRc is True:
1427 try:
1428 oFsObjInfo = oCurDir.read();
1429 except Exception as oXcpt:
1430 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1431 ##
1432 ## @todo r=bird: Change this to reporter.errorXcpt() once directoryOpen() starts
1433 ## working the way it is documented.
1434 ##
1435 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,)); # See above why 'maybe'.
1436 fRc = False;
1437 #else: reporter.log2('\tNo more directory entries for "%s"' % (sCurDir,));
1438 break;
1439
1440 try:
1441 sName = oFsObjInfo.name;
1442 eType = oFsObjInfo.type;
1443 except:
1444 fRc = reporter.errorXcpt();
1445 break;
1446
1447 if sName in ('.', '..', ):
1448 if eType != vboxcon.FsObjType_Directory:
1449 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1450 % (sName, eType, vboxcon.FsObjType_Directory));
1451 elif eType == vboxcon.FsObjType_Directory:
1452 #reporter.log2(' Directory "%s"' % oFsObjInfo.name);
1453 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError,
1454 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName);
1455 fRc = aSubResult[0];
1456 cDirs += aSubResult[1] + 1;
1457 cFiles += aSubResult[2];
1458 cOthers += aSubResult[3];
1459 elif eType is vboxcon.FsObjType_File:
1460 #reporter.log2(' File "%s"' % oFsObjInfo.name);
1461 cFiles += 1;
1462 elif eType is vboxcon.FsObjType_Symlink:
1463 #reporter.log2(' Symlink "%s" -- not tested yet' % oFsObjInfo.name);
1464 cOthers += 1;
1465 elif oTestVm.isWindows() \
1466 or oTestVm.isOS2() \
1467 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock,
1468 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut):
1469 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' %
1470 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,));
1471 else:
1472 cOthers += 1;
1473
1474 # Close the directory
1475 try:
1476 oCurDir.close();
1477 except:
1478 fRc = reporter.errorXcpt('sCurDir=%s' % (sCurDir));
1479
1480 return (fRc, cDirs, cFiles, cOthers);
1481
1482 def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (testfileset.TestDir) -> bool
1483 """
1484 Helper function to recursively read a guest directory tree specified in the current test.
1485 """
1486
1487 #
1488 # Process the directory.
1489 #
1490
1491 # Open the directory:
1492 try:
1493 oCurDir = oGuestSession.directoryOpen(oDir.sPath, '', None);
1494 except:
1495 return reporter.errorXcpt('sPath=%s' % (oDir.sPath,));
1496
1497 # Read the directory.
1498 dLeftUpper = dict(oDir.dChildrenUpper);
1499 cDot = 0;
1500 cDotDot = 0;
1501 fRc = True;
1502 while True:
1503 try:
1504 oFsObjInfo = oCurDir.read();
1505 except Exception as oXcpt:
1506 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1507 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath,));
1508 break;
1509
1510 try:
1511 sName = oFsObjInfo.name;
1512 eType = oFsObjInfo.type;
1513 cbFile = oFsObjInfo.objectSize;
1514 ## @todo check further attributes.
1515 except:
1516 fRc = reporter.errorXcpt();
1517 break;
1518
1519 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment:
1520 if sName in ('.', '..', ):
1521 if eType != vboxcon.FsObjType_Directory:
1522 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1523 % (sName, eType, vboxcon.FsObjType_Directory));
1524 if sName == '.': cDot += 1;
1525 else: cDotDot += 1;
1526 else:
1527 # Find the child and remove it from the dictionary.
1528 sNameUpper = sName.upper();
1529 oFsObj = dLeftUpper.get(sNameUpper);
1530 if oFsObj is None:
1531 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!'
1532 % (sName, oDir.sPath, eType, cbFile,));
1533 else:
1534 del dLeftUpper[sNameUpper];
1535
1536 # Check type
1537 if isinstance(oFsObj, testfileset.TestDir):
1538 if eType != vboxcon.FsObjType_Directory:
1539 fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
1540 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
1541 elif isinstance(oFsObj, testfileset.TestFile):
1542 if eType != vboxcon.FsObjType_File:
1543 fRc = reporter.error('%s: expected file (%d), got eType=%d!'
1544 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,));
1545 else:
1546 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),));
1547
1548 # Check the name.
1549 if oFsObj.sName != sName:
1550 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,));
1551
1552 # Check the size if a file.
1553 if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent:
1554 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,));
1555
1556 ## @todo check timestamps and attributes.
1557
1558 # Close the directory
1559 try:
1560 oCurDir.close();
1561 except:
1562 fRc = reporter.errorXcpt('oDir.sPath=%s' % (oDir.sPath,));
1563
1564 # Any files left over?
1565 for sKey in dLeftUpper:
1566 oFsObj = dLeftUpper[sKey];
1567 fRc = reporter.error('%s: Was not returned! (%s)' % (oFsObj.sPath, type(oFsObj),));
1568
1569 # Check the dot and dot-dot counts.
1570 if cDot != 1:
1571 fRc = reporter.error('%s: Found %s "." entries, expected exactly 1!' % (oDir.sPath, cDot,));
1572 if cDotDot != 1:
1573 fRc = reporter.error('%s: Found %s ".." entries, expected exactly 1!' % (oDir.sPath, cDotDot,));
1574
1575 #
1576 # Recurse into subdirectories using info from oDir.
1577 #
1578 for oFsObj in oDir.aoChildren:
1579 if isinstance(oFsObj, testfileset.TestDir):
1580 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc;
1581
1582 return fRc;
1583
1584 def gctrlExecDoTest(self, i, oTest, oRes, oGuestSession):
1585 """
1586 Wrapper function around gctrlExecute to provide more sanity checking
1587 when needed in actual execution tests.
1588 """
1589 reporter.log('Testing #%d, cmd="%s" ...' % (i, oTest.sCmd));
1590 fRcExec = self.gctrlExecute(oTest, oGuestSession, oRes.fRc);
1591 if fRcExec == oRes.fRc:
1592 fRc = True;
1593 if fRcExec is True:
1594 # Compare exit status / code on successful process execution.
1595 if oTest.uExitStatus != oRes.uExitStatus \
1596 or oTest.iExitCode != oRes.iExitCode:
1597 fRc = reporter.error('Test #%d (%s) failed: Got exit status + code %d,%d, expected %d,%d'
1598 % (i, oTest.asArgs, oTest.uExitStatus, oTest.iExitCode,
1599 oRes.uExitStatus, oRes.iExitCode));
1600
1601 # Compare test / result buffers on successful process execution.
1602 if oTest.sBuf is not None and oRes.sBuf is not None:
1603 if not utils.areBytesEqual(oTest.sBuf, oRes.sBuf):
1604 fRc = reporter.error('Test #%d (%s) failed: Got buffer\n%s (%d bytes), expected\n%s (%d bytes)'
1605 % (i, oTest.asArgs,
1606 map(hex, map(ord, oTest.sBuf)), len(oTest.sBuf),
1607 map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf)));
1608 reporter.log2('Test #%d passed: Buffers match (%d bytes)' % (i, len(oRes.sBuf)));
1609 elif oRes.sBuf and not oTest.sBuf:
1610 fRc = reporter.error('Test #%d (%s) failed: Got no buffer data, expected\n%s (%dbytes)' %
1611 (i, oTest.asArgs, map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf),));
1612
1613 if oRes.cbStdOut is not None and oRes.cbStdOut != oTest.cbStdOut:
1614 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stdout data, expected %d'
1615 % (i, oTest.asArgs, oTest.cbStdOut, oRes.cbStdOut));
1616 if oRes.cbStdErr is not None and oRes.cbStdErr != oTest.cbStdErr:
1617 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stderr data, expected %d'
1618 % (i, oTest.asArgs, oTest.cbStdErr, oRes.cbStdErr));
1619 else:
1620 fRc = reporter.error('Test #%d (%s) failed: Got %s, expected %s' % (i, oTest.asArgs, fRcExec, oRes.fRc));
1621 return fRc;
1622
1623 def gctrlExecute(self, oTest, oGuestSession, fIsError):
1624 """
1625 Helper function to execute a program on a guest, specified in the current test.
1626
1627 Note! This weirdo returns results (process exitcode and status) in oTest.
1628 """
1629 fRc = True; # Be optimistic.
1630
1631 # Reset the weird result stuff:
1632 oTest.cbStdOut = 0;
1633 oTest.cbStdErr = 0;
1634 oTest.sBuf = '';
1635 oTest.uExitStatus = 0;
1636 oTest.iExitCode = 0;
1637
1638 ## @todo Compare execution timeouts!
1639 #tsStart = base.timestampMilli();
1640
1641 try:
1642 reporter.log2('Using session user=%s, sDomain=%s, name=%s, timeout=%d'
1643 % (oGuestSession.user, oGuestSession.domain, oGuestSession.name, oGuestSession.timeout,));
1644 except:
1645 return reporter.errorXcpt();
1646
1647 #
1648 # Start the process:
1649 #
1650 reporter.log2('Executing sCmd=%s, fFlags=%s, timeoutMS=%d, asArgs=%s, asEnv=%s'
1651 % (oTest.sCmd, oTest.fFlags, oTest.timeoutMS, oTest.asArgs, oTest.aEnv,));
1652 try:
1653 oProcess = oGuestSession.processCreate(oTest.sCmd,
1654 oTest.asArgs if self.oTstDrv.fpApiVer >= 5.0 else oTest.asArgs[1:],
1655 oTest.aEnv, oTest.fFlags, oTest.timeoutMS);
1656 except:
1657 reporter.maybeErrXcpt(fIsError, 'asArgs=%s' % (oTest.asArgs,));
1658 return False;
1659 if oProcess is None:
1660 return reporter.error('oProcess is None! (%s)' % (oTest.asArgs,));
1661
1662 #time.sleep(5); # try this if you want to see races here.
1663
1664 # Wait for the process to start properly:
1665 reporter.log2('Process start requested, waiting for start (%dms) ...' % (oTest.timeoutMS,));
1666 iPid = -1;
1667 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Start, ];
1668 try:
1669 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
1670 except:
1671 reporter.maybeErrXcpt(fIsError, 'waitforArray failed for asArgs=%s' % (oTest.asArgs,));
1672 fRc = False;
1673 else:
1674 try:
1675 eStatus = oProcess.status;
1676 iPid = oProcess.PID;
1677 except:
1678 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1679 else:
1680 reporter.log2('Wait result returned: %d, current process status is: %d' % (eWaitResult, eStatus,));
1681
1682 #
1683 # Wait for the process to run to completion if necessary.
1684 #
1685 # Note! The above eWaitResult return value can be ignored as it will
1686 # (mostly) reflect the process status anyway.
1687 #
1688 if eStatus == vboxcon.ProcessStatus_Started:
1689
1690 # What to wait for:
1691 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate, ];
1692 if vboxcon.ProcessCreateFlag_WaitForStdOut in oTest.fFlags:
1693 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdOut);
1694 if vboxcon.ProcessCreateFlag_WaitForStdErr in oTest.fFlags:
1695 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdErr);
1696 ## @todo Add vboxcon.ProcessWaitForFlag_StdIn.
1697
1698 reporter.log2('Process (PID %d) started, waiting for termination (%dms), aeWaitFor=%s ...'
1699 % (iPid, oTest.timeoutMS, aeWaitFor));
1700 acbFdOut = [0,0,0];
1701 while True:
1702 try:
1703 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
1704 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
1705 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
1706 try: oProcess.close();
1707 except: pass;
1708 break;
1709 except:
1710 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1711 break;
1712 reporter.log2('Wait returned: %d' % (eWaitResult,));
1713
1714 # Process output:
1715 for eFdResult, iFd, sFdNm in [ (vboxcon.ProcessWaitResult_StdOut, 1, 'stdout'),
1716 (vboxcon.ProcessWaitResult_StdErr, 2, 'stderr'), ]:
1717 if eWaitResult in (eFdResult, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
1718 reporter.log2('Reading %s ...' % (sFdNm,));
1719 try:
1720 abBuf = oProcess.Read(1, 64 * 1024, oTest.timeoutMS);
1721 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
1722 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
1723 try: oProcess.close();
1724 except: pass;
1725 except:
1726 pass; ## @todo test for timeouts and fail on anything else!
1727 else:
1728 if abBuf:
1729 reporter.log2('Process (PID %d) got %d bytes of %s data' % (iPid, len(abBuf), sFdNm,));
1730 acbFdOut[iFd] += len(abBuf);
1731 oTest.sBuf = abBuf; ## @todo Figure out how to uniform + append!
1732
1733 ## Process input (todo):
1734 #if eWaitResult in (vboxcon.ProcessWaitResult_StdIn, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
1735 # reporter.log2('Process (PID %d) needs stdin data' % (iPid,));
1736
1737 # Termination or error?
1738 if eWaitResult in (vboxcon.ProcessWaitResult_Terminate,
1739 vboxcon.ProcessWaitResult_Error,
1740 vboxcon.ProcessWaitResult_Timeout,):
1741 try: eStatus = oProcess.status;
1742 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1743 reporter.log2('Process (PID %d) reported terminate/error/timeout: %d, status: %d'
1744 % (iPid, eWaitResult, eStatus,));
1745 break;
1746
1747 # End of the wait loop.
1748 _, oTest.cbStdOut, oTest.cbStdErr = acbFdOut;
1749
1750 try: eStatus = oProcess.status;
1751 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1752 reporter.log2('Final process status (PID %d) is: %d' % (iPid, eStatus));
1753 reporter.log2('Process (PID %d) %d stdout, %d stderr' % (iPid, oTest.cbStdOut, oTest.cbStdErr));
1754
1755 #
1756 # Get the final status and exit code of the process.
1757 #
1758 try:
1759 oTest.uExitStatus = oProcess.status;
1760 oTest.iExitCode = oProcess.exitCode;
1761 except:
1762 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1763 reporter.log2('Process (PID %d) has exit code: %d; status: %d ' % (iPid, oTest.iExitCode, oTest.uExitStatus));
1764 return fRc;
1765
1766 def testGuestCtrlSessionEnvironment(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
1767 """
1768 Tests the guest session environment changes.
1769 """
1770 aoTests = [
1771 # Check basic operations.
1772 tdTestSessionEx([ # Initial environment is empty.
1773 tdStepSessionCheckEnv(),
1774 # Check clearing empty env.
1775 tdStepSessionClearEnv(),
1776 tdStepSessionCheckEnv(),
1777 # Check set.
1778 tdStepSessionSetEnv('FOO', 'BAR'),
1779 tdStepSessionCheckEnv(['FOO=BAR',]),
1780 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
1781 tdStepSessionClearEnv(),
1782 tdStepSessionCheckEnv(),
1783 # Check unset.
1784 tdStepSessionUnsetEnv('BAR'),
1785 tdStepSessionCheckEnv(['BAR']),
1786 tdStepSessionClearEnv(),
1787 tdStepSessionCheckEnv(),
1788 # Set + unset.
1789 tdStepSessionSetEnv('FOO', 'BAR'),
1790 tdStepSessionCheckEnv(['FOO=BAR',]),
1791 tdStepSessionUnsetEnv('FOO'),
1792 tdStepSessionCheckEnv(['FOO']),
1793 # Bulk environment changes (via attrib) (shall replace existing 'FOO').
1794 tdStepSessionBulkEnv( ['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
1795 tdStepSessionCheckEnv(['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
1796 ]),
1797 tdTestSessionEx([ # Check that setting the same value several times works.
1798 tdStepSessionSetEnv('FOO','BAR'),
1799 tdStepSessionCheckEnv([ 'FOO=BAR',]),
1800 tdStepSessionSetEnv('FOO','BAR2'),
1801 tdStepSessionCheckEnv([ 'FOO=BAR2',]),
1802 tdStepSessionSetEnv('FOO','BAR3'),
1803 tdStepSessionCheckEnv([ 'FOO=BAR3',]),
1804 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
1805 # Add a little unsetting to the mix.
1806 tdStepSessionSetEnv('BAR', 'BEAR'),
1807 tdStepSessionCheckEnv([ 'FOO=BAR3', 'BAR=BEAR',]),
1808 tdStepSessionUnsetEnv('FOO'),
1809 tdStepSessionCheckEnv([ 'FOO', 'BAR=BEAR',]),
1810 tdStepSessionSetEnv('FOO','BAR4'),
1811 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR',]),
1812 # The environment is case sensitive.
1813 tdStepSessionSetEnv('foo','BAR5'),
1814 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo=BAR5']),
1815 tdStepSessionUnsetEnv('foo'),
1816 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo']),
1817 ]),
1818 tdTestSessionEx([ # Bulk settings merges stuff, last entry standing.
1819 tdStepSessionBulkEnv(['FOO=bar', 'foo=bar', 'FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
1820 tdStepSessionCheckEnv(['FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
1821 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
1822 tdStepSessionBulkEnv(['2=1+1', 'FOO=doofus2', ]),
1823 tdStepSessionCheckEnv(['2=1+1', 'FOO=doofus2' ]),
1824 ]),
1825 # Invalid variable names.
1826 tdTestSessionEx([
1827 tdStepSessionSetEnv('', 'FOO', vbox.ComError.E_INVALIDARG),
1828 tdStepSessionCheckEnv(),
1829 tdStepRequireMinimumApiVer(5.0), # 4.3 is too relaxed checking input!
1830 tdStepSessionSetEnv('=', '===', vbox.ComError.E_INVALIDARG),
1831 tdStepSessionCheckEnv(),
1832 tdStepSessionSetEnv('FOO=', 'BAR', vbox.ComError.E_INVALIDARG),
1833 tdStepSessionCheckEnv(),
1834 tdStepSessionSetEnv('=FOO', 'BAR', vbox.ComError.E_INVALIDARG),
1835 tdStepSessionCheckEnv(),
1836 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy and too relaxed!
1837 tdStepSessionBulkEnv(['', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1838 tdStepSessionCheckEnv(),
1839 tdStepSessionBulkEnv(['=', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1840 tdStepSessionCheckEnv(),
1841 tdStepSessionBulkEnv(['=FOO', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1842 tdStepSessionCheckEnv(),
1843 ]),
1844 # A bit more weird keys/values.
1845 tdTestSessionEx([ tdStepSessionSetEnv('$$$', ''),
1846 tdStepSessionCheckEnv([ '$$$=',]), ]),
1847 tdTestSessionEx([ tdStepSessionSetEnv('$$$', '%%%'),
1848 tdStepSessionCheckEnv([ '$$$=%%%',]),
1849 ]),
1850 tdTestSessionEx([ tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
1851 tdStepSessionSetEnv(u'ß$%ß&', ''),
1852 tdStepSessionCheckEnv([ u'ß$%ß&=',]),
1853 ]),
1854 # Misc stuff.
1855 tdTestSessionEx([ tdStepSessionSetEnv('FOO', ''),
1856 tdStepSessionCheckEnv(['FOO=',]),
1857 ]),
1858 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
1859 tdStepSessionCheckEnv(['FOO=BAR',])
1860 ],),
1861 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
1862 tdStepSessionSetEnv('BAR', 'BAZ'),
1863 tdStepSessionCheckEnv([ 'FOO=BAR', 'BAR=BAZ',]),
1864 ]),
1865 ];
1866 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'SessionEnv');
1867
1868 def testGuestCtrlSession(self, oSession, oTxsSession, oTestVm):
1869 """
1870 Tests the guest session handling.
1871 """
1872
1873 #
1874 # Parameters.
1875 #
1876 atTests = [
1877 # Invalid parameters.
1878 [ tdTestSession(sUser = ''), tdTestResultSession() ],
1879 [ tdTestSession(sPassword = 'bar'), tdTestResultSession() ],
1880 [ tdTestSession(sDomain = 'boo'),tdTestResultSession() ],
1881 [ tdTestSession(sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
1882 # User account without a passwort - forbidden.
1883 [ tdTestSession(sPassword = "" ), tdTestResultSession() ],
1884 # Wrong credentials.
1885 # Note: On Guest Additions < 4.3 this always succeeds because these don't
1886 # support creating dedicated sessions. Instead, guest process creation
1887 # then will fail. See note below.
1888 [ tdTestSession(sUser = 'foo', sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
1889 # Correct credentials.
1890 [ tdTestSession(), tdTestResultSession(fRc = True, cNumSessions = 1) ]
1891 ];
1892
1893 fRc = True;
1894 for (i, tTest) in enumerate(atTests):
1895 oCurTest = tTest[0] # type: tdTestSession
1896 oCurRes = tTest[1] # type: tdTestResult
1897
1898 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
1899 reporter.log('Testing #%d, user="%s", sPassword="%s", sDomain="%s" ...'
1900 % (i, oCurTest.oCreds.sUser, oCurTest.oCreds.sPassword, oCurTest.oCreds.sDomain));
1901 sCurGuestSessionName = 'testGuestCtrlSession: Test #%d' % (i,);
1902 fRc2, oCurGuestSession = oCurTest.createSession(sCurGuestSessionName, fIsError = oCurRes.fRc);
1903
1904 # See note about < 4.3 Guest Additions above.
1905 uProtocolVersion = 2;
1906 if oCurGuestSession is not None:
1907 try:
1908 uProtocolVersion = oCurGuestSession.protocolVersion;
1909 except:
1910 fRc = reporter.errorXcpt('Test #%d' % (i,));
1911
1912 if uProtocolVersion >= 2 and fRc2 is not oCurRes.fRc:
1913 fRc = reporter.error('Test #%d failed: Session creation failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
1914
1915 if fRc2 and oCurGuestSession is None:
1916 fRc = reporter.error('Test #%d failed: no session object' % (i,));
1917 fRc2 = False;
1918
1919 if fRc2:
1920 if uProtocolVersion >= 2: # For Guest Additions < 4.3 getSessionCount() always will return 1.
1921 cCurSessions = oCurTest.getSessionCount(self.oTstDrv.oVBoxMgr);
1922 if cCurSessions != oCurRes.cNumSessions:
1923 fRc = reporter.error('Test #%d failed: Session count does not match: Got %d, expected %d'
1924 % (i, cCurSessions, oCurRes.cNumSessions));
1925 try:
1926 sObjName = oCurGuestSession.name;
1927 except:
1928 fRc = reporter.errorXcpt('Test #%d' % (i,));
1929 else:
1930 if sObjName != sCurGuestSessionName:
1931 fRc = reporter.error('Test #%d failed: Session name does not match: Got "%s", expected "%s"'
1932 % (i, sObjName, sCurGuestSessionName));
1933 fRc2 = oCurTest.closeSession(True);
1934 if fRc2 is False:
1935 fRc = reporter.error('Test #%d failed: Session could not be closed' % (i,));
1936
1937 if fRc is False:
1938 return (False, oTxsSession);
1939
1940 #
1941 # Multiple sessions.
1942 #
1943 cMaxGuestSessions = 31; # Maximum number of concurrent guest session allowed.
1944 # Actually, this is 32, but we don't test session 0.
1945 aoMultiSessions = {};
1946 reporter.log2('Opening multiple guest tsessions at once ...');
1947 for i in xrange(cMaxGuestSessions + 1):
1948 aoMultiSessions[i] = tdTestSession(sSessionName = 'MultiSession #%d' % (i,));
1949 aoMultiSessions[i].setEnvironment(oSession, oTxsSession, oTestVm);
1950
1951 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
1952 reporter.log2('MultiSession test #%d count is %d' % (i, cCurSessions));
1953 if cCurSessions != i:
1954 return (reporter.error('MultiSession count is %d, expected %d' % (cCurSessions, i)), oTxsSession);
1955 fRc2, _ = aoMultiSessions[i].createSession('MultiSession #%d' % (i,), i < cMaxGuestSessions);
1956 if fRc2 is not True:
1957 if i < cMaxGuestSessions:
1958 return (reporter.error('MultiSession #%d test failed' % (i,)), oTxsSession);
1959 reporter.log('MultiSession #%d exceeded concurrent guest session count, good' % (i,));
1960 break;
1961
1962 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
1963 if cCurSessions is not cMaxGuestSessions:
1964 return (reporter.error('Final session count %d, expected %d ' % (cCurSessions, cMaxGuestSessions,)), oTxsSession);
1965
1966 reporter.log2('Closing MultiSessions ...');
1967 for i in xrange(cMaxGuestSessions):
1968 # Close this session:
1969 oClosedGuestSession = aoMultiSessions[i].oGuestSession;
1970 fRc2 = aoMultiSessions[i].closeSession(True);
1971 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr)
1972 reporter.log2('MultiSession #%d count is %d' % (i, cCurSessions,));
1973 if fRc2 is False:
1974 fRc = reporter.error('Closing MultiSession #%d failed' % (i,));
1975 elif cCurSessions != cMaxGuestSessions - (i + 1):
1976 fRc = reporter.error('Expected %d session after closing #%d, got %d instead'
1977 % (cMaxGuestSessions - (i + 1), cCurSessions, i,));
1978 assert aoMultiSessions[i].oGuestSession is None or not fRc2;
1979 ## @todo any way to check that the session is closed other than the 'sessions' attribute?
1980
1981 # Try check that none of the remaining sessions got closed.
1982 try:
1983 aoGuestSessions = self.oTstDrv.oVBoxMgr.getArray(atTests[0][0].oTest.oGuest, 'sessions');
1984 except:
1985 return (reporter.errorXcpt('i=%d/%d' % (i, cMaxGuestSessions,)), oTxsSession);
1986 if oClosedGuestSession in aoGuestSessions:
1987 fRc = reporter.error('i=%d/%d: %s should not be in %s'
1988 % (i, cMaxGuestSessions, oClosedGuestSession, aoGuestSessions));
1989 if i + 1 < cMaxGuestSessions: # Not sure what xrange(2,2) does...
1990 for j in xrange(i + 1, cMaxGuestSessions):
1991 if aoMultiSessions[j].oGuestSession not in aoGuestSessions:
1992 fRc = reporter.error('i=%d/j=%d/%d: %s should be in %s'
1993 % (i, j, cMaxGuestSessions, aoMultiSessions[j].oGuestSession, aoGuestSessions));
1994 ## @todo any way to check that they work?
1995
1996 ## @todo Test session timeouts.
1997
1998 return (fRc, oTxsSession);
1999
2000 def testGuestCtrlSessionFileRefs(self, oSession, oTxsSession, oTestVm):
2001 """
2002 Tests the guest session file reference handling.
2003 """
2004
2005 # Find a file to play around with:
2006 sFile = self.getGuestSystemFileForReading(oTestVm);
2007
2008 # Use credential defaults.
2009 oCreds = tdCtxCreds();
2010 oCreds.applyDefaultsIfNotSet(oTestVm);
2011
2012 # Number of stale guest files to create.
2013 cStaleFiles = 10;
2014
2015 #
2016 # Start a session.
2017 #
2018 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2019 try:
2020 oGuest = oSession.o.console.guest;
2021 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionFileRefs");
2022 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2023 except:
2024 return (reporter.errorXcpt(), oTxsSession);
2025
2026 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2027 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2028 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2029 reporter.log('Session successfully started');
2030
2031 #
2032 # Open guest files and "forget" them (stale entries).
2033 # For them we don't have any references anymore intentionally.
2034 #
2035 reporter.log2('Opening stale files');
2036 fRc = True;
2037 for i in xrange(0, cStaleFiles):
2038 try:
2039 if self.oTstDrv.fpApiVer >= 5.0:
2040 oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly, vboxcon.FileOpenAction_OpenExisting, 0);
2041 else:
2042 oGuestSession.fileOpen(sFile, "r", "oe", 0);
2043 # Note: Use a timeout in the call above for not letting the stale processes
2044 # hanging around forever. This can happen if the installed Guest Additions
2045 # do not support terminating guest processes.
2046 except:
2047 fRc = reporter.errorXcpt('Opening stale file #%d failed:' % (i,));
2048 break;
2049
2050 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2051 except: fRc = reporter.errorXcpt();
2052 else:
2053 if cFiles != cStaleFiles:
2054 fRc = reporter.error('Got %d stale files, expected %d' % (cFiles, cStaleFiles));
2055
2056 if fRc is True:
2057 #
2058 # Open non-stale files and close them again.
2059 #
2060 reporter.log2('Opening non-stale files');
2061 aoFiles = [];
2062 for i in xrange(0, cStaleFiles):
2063 try:
2064 if self.oTstDrv.fpApiVer >= 5.0:
2065 oCurFile = oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly,
2066 vboxcon.FileOpenAction_OpenExisting, 0);
2067 else:
2068 oCurFile = oGuestSession.fileOpen(sFile, "r", "oe", 0);
2069 aoFiles.append(oCurFile);
2070 except:
2071 fRc = reporter.errorXcpt('Opening non-stale file #%d failed:' % (i,));
2072 break;
2073
2074 # Check the count.
2075 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2076 except: fRc = reporter.errorXcpt();
2077 else:
2078 if cFiles != cStaleFiles * 2:
2079 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles * 2));
2080
2081 # Close them.
2082 reporter.log2('Closing all non-stale files again ...');
2083 for i, oFile in enumerate(aoFiles):
2084 try:
2085 oFile.close();
2086 except:
2087 fRc = reporter.errorXcpt('Closing non-stale file #%d failed:' % (i,));
2088
2089 # Check the count again.
2090 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2091 except: fRc = reporter.errorXcpt();
2092 # Here we count the stale files (that is, files we don't have a reference
2093 # anymore for) and the opened and then closed non-stale files (that we still keep
2094 # a reference in aoFiles[] for).
2095 if cFiles != cStaleFiles:
2096 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles));
2097
2098 #
2099 # Check that all (referenced) non-stale files are now in the "closed" state.
2100 #
2101 reporter.log2('Checking statuses of all non-stale files ...');
2102 for i, oFile in enumerate(aoFiles):
2103 try:
2104 eFileStatus = aoFiles[i].status;
2105 except:
2106 fRc = reporter.errorXcpt('Checking status of file #%d failed:' % (i,));
2107 else:
2108 if eFileStatus != vboxcon.FileStatus_Closed:
2109 fRc = reporter.error('Non-stale file #%d has status %d, expected %d'
2110 % (i, eFileStatus, vboxcon.FileStatus_Closed));
2111
2112 if fRc is True:
2113 reporter.log2('All non-stale files closed');
2114
2115 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2116 except: fRc = reporter.errorXcpt();
2117 else: reporter.log2('Final guest session file count: %d' % (cFiles,));
2118
2119 #
2120 # Now try to close the session and see what happens.
2121 # Note! Session closing is why we've been doing all the 'if fRc is True' stuff above rather than returning.
2122 #
2123 reporter.log2('Closing guest session ...');
2124 try:
2125 oGuestSession.close();
2126 except:
2127 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2128
2129 return (fRc, oTxsSession);
2130
2131 #def testGuestCtrlSessionDirRefs(self, oSession, oTxsSession, oTestVm):
2132 # """
2133 # Tests the guest session directory reference handling.
2134 # """
2135
2136 # fRc = True;
2137 # return (fRc, oTxsSession);
2138
2139 def testGuestCtrlSessionProcRefs(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2140 """
2141 Tests the guest session process reference handling.
2142 """
2143
2144 sCmd = self.getGuestSystemShell(oTestVm);
2145 asArgs = [sCmd,];
2146
2147 # Use credential defaults.
2148 oCreds = tdCtxCreds();
2149 oCreds.applyDefaultsIfNotSet(oTestVm);
2150
2151 # Number of stale guest processes to create.
2152 cStaleProcs = 10;
2153
2154 #
2155 # Start a session.
2156 #
2157 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2158 try:
2159 oGuest = oSession.o.console.guest;
2160 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionProcRefs");
2161 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2162 except:
2163 return (reporter.errorXcpt(), oTxsSession);
2164
2165 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2166 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2167 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2168 reporter.log('Session successfully started');
2169
2170 #
2171 # Fire off forever-running processes and "forget" them (stale entries).
2172 # For them we don't have any references anymore intentionally.
2173 #
2174 reporter.log2('Starting stale processes...');
2175 fRc = True;
2176 for i in xrange(0, cStaleProcs):
2177 try:
2178 oGuestSession.processCreate(sCmd,
2179 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], [],
2180 [ vboxcon.ProcessCreateFlag_WaitForStdOut ], 30 * 1000);
2181 # Note: Use a timeout in the call above for not letting the stale processes
2182 # hanging around forever. This can happen if the installed Guest Additions
2183 # do not support terminating guest processes.
2184 except:
2185 fRc = reporter.errorXcpt('Creating stale process #%d failed:' % (i,));
2186 break;
2187
2188 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2189 except: fRc = reporter.errorXcpt();
2190 else:
2191 if cProcesses != cStaleProcs:
2192 fRc = reporter.error('Got %d stale processes, expected %d' % (cProcesses, cStaleProcs));
2193
2194 if fRc is True:
2195 #
2196 # Fire off non-stale processes and wait for termination.
2197 #
2198 if oTestVm.isWindows() or oTestVm.isOS2():
2199 asArgs = [ sCmd, '/C', 'dir', '/S', self.getGuestSystemDir(oTestVm), ];
2200 else:
2201 asArgs = [ sCmd, '-c', 'ls -la ' + self.getGuestSystemDir(oTestVm), ];
2202 reporter.log2('Starting non-stale processes...');
2203 aoProcesses = [];
2204 for i in xrange(0, cStaleProcs):
2205 try:
2206 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2207 [], [], 0); # Infinite timeout.
2208 aoProcesses.append(oCurProc);
2209 except:
2210 fRc = reporter.errorXcpt('Creating non-stale process #%d failed:' % (i,));
2211 break;
2212
2213 reporter.log2('Waiting for non-stale processes to terminate...');
2214 for i, oProcess in enumerate(aoProcesses):
2215 try:
2216 oProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 30 * 1000);
2217 eProcessStatus = oProcess.status;
2218 except:
2219 fRc = reporter.errorXcpt('Waiting for non-stale process #%d failed:' % (i,));
2220 else:
2221 if eProcessStatus != vboxcon.ProcessStatus_TerminatedNormally:
2222 fRc = reporter.error('Waiting for non-stale processes #%d resulted in status %d, expected %d'
2223 % (i, eProcessStatus, vboxcon.ProcessStatus_TerminatedNormally));
2224
2225 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2226 except: fRc = reporter.errorXcpt();
2227 else:
2228 # Here we count the stale processes (that is, processes we don't have a reference
2229 # anymore for) and the started + terminated non-stale processes (that we still keep
2230 # a reference in aoProcesses[] for).
2231 if cProcesses != (cStaleProcs * 2):
2232 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2233
2234 if fRc is True:
2235 reporter.log2('All non-stale processes terminated');
2236
2237 #
2238 # Fire off non-stale blocking processes which are terminated via terminate().
2239 #
2240 if oTestVm.isWindows() or oTestVm.isOS2():
2241 asArgs = [ sCmd, '/C', 'pause'];
2242 else:
2243 asArgs = [ sCmd ];
2244 reporter.log2('Starting blocking processes...');
2245 aoProcesses = [];
2246 for i in xrange(0, cStaleProcs):
2247 try:
2248 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2249 [], [], 30 * 1000);
2250 # Note: Use a timeout in the call above for not letting the stale processes
2251 # hanging around forever. This can happen if the installed Guest Additions
2252 # do not support terminating guest processes.
2253 aoProcesses.append(oCurProc);
2254 except:
2255 fRc = reporter.errorXcpt('Creating non-stale blocking process #%d failed:' % (i,));
2256 break;
2257
2258 reporter.log2('Terminating blocking processes...');
2259 for i, oProcess in enumerate(aoProcesses):
2260 try:
2261 oProcess.terminate();
2262 except: # Termination might not be supported, just skip and log it.
2263 reporter.logXcpt('Termination of blocking process #%d failed, skipped:' % (i,));
2264
2265 # There still should be 20 processes because we terminated the 10 newest ones.
2266 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2267 except: fRc = reporter.errorXcpt();
2268 else:
2269 if cProcesses != (cStaleProcs * 2):
2270 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2271 reporter.log2('Final guest session processes count: %d' % (cProcesses,));
2272
2273 #
2274 # Now try to close the session and see what happens.
2275 #
2276 reporter.log2('Closing guest session ...');
2277 try:
2278 oGuestSession.close();
2279 except:
2280 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2281
2282 return (fRc, oTxsSession);
2283
2284 def testGuestCtrlExec(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements
2285 """
2286 Tests the basic execution feature.
2287 """
2288
2289 # Paths:
2290 sVBoxControl = None; ## @todo Get path of installed Guest Additions. Later.
2291 sShell = self.getGuestSystemShell(oTestVm);
2292 sShellOpt = '/C' if oTestVm.isWindows() or oTestVm.isOS2() else '-c';
2293 sSystemDir = self.getGuestSystemDir(oTestVm);
2294 sFileForReading = self.getGuestSystemFileForReading(oTestVm);
2295 if oTestVm.isWindows() or oTestVm.isOS2():
2296 sImageOut = self.getGuestSystemShell(oTestVm);
2297 if oTestVm.isWindows():
2298 sVBoxControl = "C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\VBoxControl.exe";
2299 else:
2300 sImageOut = "/bin/ls";
2301 if oTestVm.isLinux(): ## @todo check solaris and darwin.
2302 sVBoxControl = "/usr/bin/VBoxControl"; # Symlink
2303
2304 # Use credential defaults.
2305 oCreds = tdCtxCreds();
2306 oCreds.applyDefaultsIfNotSet(oTestVm);
2307
2308 atInvalid = [
2309 # Invalid parameters.
2310 [ tdTestExec(), tdTestResultExec() ],
2311 # Non-existent / invalid image.
2312 [ tdTestExec(sCmd = "non-existent"), tdTestResultExec() ],
2313 [ tdTestExec(sCmd = "non-existent2"), tdTestResultExec() ],
2314 # Use an invalid format string.
2315 [ tdTestExec(sCmd = "%$%%%&"), tdTestResultExec() ],
2316 # More stuff.
2317 [ tdTestExec(sCmd = u"ƒ‰‹ˆ÷‹¸"), tdTestResultExec() ],
2318 [ tdTestExec(sCmd = "???://!!!"), tdTestResultExec() ],
2319 [ tdTestExec(sCmd = "<>!\\"), tdTestResultExec() ],
2320 # Enable as soon as ERROR_BAD_DEVICE is implemented.
2321 #[ tdTestExec(sCmd = "CON", tdTestResultExec() ],
2322 ];
2323
2324 atExec = [];
2325 if oTestVm.isWindows() or oTestVm.isOS2():
2326 atExec += [
2327 # Basic execution.
2328 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2329 tdTestResultExec(fRc = True) ],
2330 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sFileForReading ]),
2331 tdTestResultExec(fRc = True) ],
2332 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir + '\\nonexist.dll' ]),
2333 tdTestResultExec(fRc = True, iExitCode = 1) ],
2334 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', '/wrongparam' ]),
2335 tdTestResultExec(fRc = True, iExitCode = 1) ],
2336 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2337 tdTestResultExec(fRc = True, iExitCode = 1) ],
2338 # StdOut.
2339 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2340 tdTestResultExec(fRc = True) ],
2341 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdout-non-existing' ]),
2342 tdTestResultExec(fRc = True, iExitCode = 1) ],
2343 # StdErr.
2344 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2345 tdTestResultExec(fRc = True) ],
2346 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stderr-non-existing' ]),
2347 tdTestResultExec(fRc = True, iExitCode = 1) ],
2348 # StdOut + StdErr.
2349 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2350 tdTestResultExec(fRc = True) ],
2351 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdouterr-non-existing' ]),
2352 tdTestResultExec(fRc = True, iExitCode = 1) ],
2353 ];
2354 # atExec.extend([
2355 # FIXME: Failing tests.
2356 # Environment variables.
2357 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2358 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2359 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2360 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2361 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2362 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2363 # aEnv = [ 'TEST_FOO=BAR' ],
2364 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2365 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2366 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2367 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2368 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2369 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2370
2371 ## @todo Create some files (or get files) we know the output size of to validate output length!
2372 ## @todo Add task which gets killed at some random time while letting the guest output something.
2373 #];
2374 else:
2375 atExec += [
2376 # Basic execution.
2377 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '-R', sSystemDir ]),
2378 tdTestResultExec(fRc = True, iExitCode = 1) ],
2379 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sFileForReading ]),
2380 tdTestResultExec(fRc = True) ],
2381 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '--wrong-parameter' ]),
2382 tdTestResultExec(fRc = True, iExitCode = 2) ],
2383 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/non/existent' ]),
2384 tdTestResultExec(fRc = True, iExitCode = 2) ],
2385 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2386 tdTestResultExec(fRc = True, iExitCode = 127) ],
2387 # StdOut.
2388 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2389 tdTestResultExec(fRc = True) ],
2390 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdout-non-existing' ]),
2391 tdTestResultExec(fRc = True, iExitCode = 2) ],
2392 # StdErr.
2393 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2394 tdTestResultExec(fRc = True) ],
2395 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stderr-non-existing' ]),
2396 tdTestResultExec(fRc = True, iExitCode = 2) ],
2397 # StdOut + StdErr.
2398 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2399 tdTestResultExec(fRc = True) ],
2400 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdouterr-non-existing' ]),
2401 tdTestResultExec(fRc = True, iExitCode = 2) ],
2402 ];
2403 # atExec.extend([
2404 # FIXME: Failing tests.
2405 # Environment variables.
2406 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2407 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2408 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2409 #
2410 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2411 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2412 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2413 # aEnv = [ 'TEST_FOO=BAR' ],
2414 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2415 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2416 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2417 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2418 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2419 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2420
2421 ## @todo Create some files (or get files) we know the output size of to validate output length!
2422 ## @todo Add task which gets killed at some random time while letting the guest output something.
2423 #];
2424
2425 #
2426 for iExitCode in xrange(0, 127):
2427 atExec.append([ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'exit %s' % iExitCode ]),
2428 tdTestResultExec(fRc = True, iExitCode = iExitCode) ]);
2429
2430 if sVBoxControl:
2431 # Paths with spaces on windows.
2432 atExec.append([ tdTestExec(sCmd = sVBoxControl, asArgs = [ sVBoxControl, 'version' ]),
2433 tdTestResultExec(fRc = True) ]);
2434
2435 # Build up the final test array for the first batch.
2436 atTests = atInvalid + atExec;
2437
2438 #
2439 # First batch: One session per guest process.
2440 #
2441 reporter.log('One session per guest process ...');
2442 fRc = True;
2443 for (i, tTest) in enumerate(atTests):
2444 oCurTest = tTest[0] # type: tdTestExec
2445 oCurRes = tTest[1] # type: tdTestResultExec
2446 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2447 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlExec: Test #%d' % (i,), True);
2448 if fRc is not True:
2449 reporter.error('Test #%d failed: Could not create session' % (i,));
2450 break;
2451 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
2452 if fRc is not True:
2453 break;
2454 fRc = oCurTest.closeSession(True);
2455 if fRc is not True:
2456 break;
2457
2458 reporter.log('Execution of all tests done, checking for stale sessions');
2459
2460 # No sessions left?
2461 try:
2462 aSessions = self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions');
2463 except:
2464 fRc = reporter.errorXcpt();
2465 else:
2466 cSessions = len(aSessions);
2467 if cSessions != 0:
2468 fRc = reporter.error('Found %d stale session(s), expected 0:' % (cSessions,));
2469 for (i, aSession) in enumerate(aSessions):
2470 try: reporter.log(' Stale session #%d ("%s")' % (aSession.id, aSession.name));
2471 except: reporter.errorXcpt();
2472
2473 if fRc is not True:
2474 return (fRc, oTxsSession);
2475
2476 reporter.log('Now using one guest session for all tests ...');
2477
2478 #
2479 # Second batch: One session for *all* guest processes.
2480 #
2481
2482 # Create session.
2483 reporter.log('Creating session for all tests ...');
2484 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
2485 try:
2486 oGuest = oSession.o.console.guest;
2487 oCurGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain,
2488 'testGuestCtrlExec: One session for all tests');
2489 except:
2490 return (reporter.errorXcpt(), oTxsSession);
2491
2492 try:
2493 eWaitResult = oCurGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2494 except:
2495 fRc = reporter.errorXcpt('Waiting for guest session to start failed:');
2496 else:
2497 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2498 fRc = reporter.error('Session did not start successfully, returned wait result: %d' % (eWaitResult,));
2499 else:
2500 reporter.log('Session successfully started');
2501
2502 # Do the tests within this session.
2503 for (i, tTest) in enumerate(atTests):
2504 oCurTest = tTest[0] # type: tdTestExec
2505 oCurRes = tTest[1] # type: tdTestResultExec
2506
2507 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2508 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
2509 if fRc is False:
2510 break;
2511
2512 # Close the session.
2513 reporter.log2('Closing guest session ...');
2514 try:
2515 oCurGuestSession.close();
2516 oCurGuestSession = None;
2517 except:
2518 fRc = reporter.errorXcpt('Closing guest session failed:');
2519
2520 # No sessions left?
2521 reporter.log('Execution of all tests done, checking for stale sessions again');
2522 try: cSessions = len(self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions'));
2523 except: fRc = reporter.errorXcpt();
2524 else:
2525 if cSessions != 0:
2526 fRc = reporter.error('Found %d stale session(s), expected 0' % (cSessions,));
2527 return (fRc, oTxsSession);
2528
2529 def threadForTestGuestCtrlSessionReboot(self, oGuestProcess):
2530 """
2531 Thread routine which waits for the stale guest process getting terminated (or some error)
2532 while the main test routine reboots the guest. It then compares the expected guest process result
2533 and logs an error if appropriate.
2534 """
2535 reporter.log('Waiting for process to get terminated at reboot ...');
2536 try:
2537 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate ], 5 * 60 * 1000);
2538 except:
2539 return reporter.errorXcpt('waitForArray failed');
2540 try:
2541 eStatus = oGuestProcess.status
2542 except:
2543 return reporter.errorXcpt('failed to get status (wait result %d)' % (eWaitResult,));
2544
2545 if eWaitResult == vboxcon.ProcessWaitResult_Terminate and eStatus == vboxcon.ProcessStatus_Down:
2546 reporter.log('Stale process was correctly terminated (status: down)');
2547 return True;
2548
2549 return reporter.error('Process wait across reboot failed: eWaitResult=%d, expected %d; eStatus=%d, expected %d'
2550 % (eWaitResult, vboxcon.ProcessWaitResult_Terminate, eStatus, vboxcon.ProcessStatus_Down,));
2551
2552 def testGuestCtrlSessionReboot(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2553 """
2554 Tests guest object notifications when a guest gets rebooted / shutdown.
2555
2556 These notifications gets sent from the guest sessions in order to make API clients
2557 aware of guest session changes.
2558
2559 To test that we create a stale guest process and trigger a reboot of the guest.
2560 """
2561
2562 ## @todo backport fixes to 6.0 and maybe 5.2
2563 if self.oTstDrv.fpApiVer <= 6.0:
2564 reporter.log('Skipping: Required fixes not yet backported!');
2565 return None;
2566
2567 # Use credential defaults.
2568 oCreds = tdCtxCreds();
2569 oCreds.applyDefaultsIfNotSet(oTestVm);
2570
2571 fRc = True;
2572
2573 #
2574 # Start a session.
2575 #
2576 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2577 try:
2578 oGuest = oSession.o.console.guest;
2579 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionReboot");
2580 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2581 except:
2582 return (reporter.errorXcpt(), oTxsSession);
2583
2584 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2585 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2586 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2587 reporter.log('Session successfully started');
2588
2589 #
2590 # Create a process.
2591 #
2592 sImage = self.getGuestSystemShell(oTestVm);
2593 asArgs = [ sImage, ];
2594 aEnv = [];
2595 fFlags = [];
2596 try:
2597 oGuestProcess = oGuestSession.processCreate(sImage,
2598 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], aEnv, fFlags,
2599 30 * 1000);
2600 except:
2601 fRc = reporter.error('Failed to start shell process (%s)' % (sImage,));
2602 else:
2603 try:
2604 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2605 except:
2606 fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
2607 else:
2608 # Check the result and state:
2609 try: eStatus = oGuestProcess.status;
2610 except: fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
2611 else:
2612 reporter.log2('Starting process wait result returned: %d; Process status is: %d' % (eWaitResult, eStatus,));
2613 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2614 fRc = reporter.error('wait for ProcessWaitForFlag_Start failed: %d, expected %d (Start)'
2615 % (eWaitResult, vboxcon.ProcessWaitResult_Start,));
2616 elif eStatus != vboxcon.ProcessStatus_Started:
2617 fRc = reporter.error('Unexpected process status after startup: %d, wanted %d (Started)'
2618 % (eStatus, vboxcon.ProcessStatus_Started,));
2619 else:
2620 # Create a thread that waits on the process to terminate
2621 reporter.log('Creating reboot thread ...');
2622 oThreadReboot = threading.Thread(target = self.threadForTestGuestCtrlSessionReboot,
2623 args = (oGuestProcess,),
2624 name = ('threadForTestGuestCtrlSessionReboot'));
2625 oThreadReboot.setDaemon(True);
2626 oThreadReboot.start();
2627
2628 # Not sure why this fudge is needed...
2629 reporter.log('5 second wait fudge before triggering reboot ...');
2630 self.oTstDrv.sleep(5);
2631
2632 # Do the reboot.
2633 reporter.log('Rebooting guest and reconnecting TXS ...');
2634 (oSession, oTxsSession) = self.oTstDrv.txsRebootAndReconnectViaTcp(oSession, oTxsSession,
2635 cMsTimeout = 3 * 60000);
2636 if not oSession or not oTxsSession:
2637 try: oGuestProcess.terminate();
2638 except: reporter.logXcpt();
2639 fRc = False;
2640
2641 reporter.log('Waiting for thread to finish ...');
2642 oThreadReboot.join();
2643
2644 #
2645 # Try make sure we don't leave with a stale process on failure.
2646 #
2647 try: oGuestProcess.terminate();
2648 except: reporter.logXcpt();
2649
2650 #
2651 # Close the session.
2652 #
2653 reporter.log2('Closing guest session ...');
2654 try:
2655 oGuestSession.close();
2656 except:
2657 fRc = reporter.errorXcpt();
2658
2659 return (fRc, oTxsSession);
2660
2661 def testGuestCtrlExecTimeout(self, oSession, oTxsSession, oTestVm):
2662 """
2663 Tests handling of timeouts of started guest processes.
2664 """
2665
2666 sShell = self.getGuestSystemShell(oTestVm);
2667
2668 # Use credential defaults.
2669 oCreds = tdCtxCreds();
2670 oCreds.applyDefaultsIfNotSet(oTestVm);
2671
2672 #
2673 # Create a session.
2674 #
2675 try:
2676 oGuest = oSession.o.console.guest;
2677 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlExecTimeout");
2678 eWaitResult = oGuestSession.waitForArray([ vboxcon.GuestSessionWaitForFlag_Start, ], 30 * 1000);
2679 except:
2680 return (reporter.errorXcpt(), oTxsSession);
2681
2682 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2683 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2684 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2685 reporter.log('Session successfully started');
2686
2687 #
2688 # Create a process which never terminates and should timeout when
2689 # waiting for termination.
2690 #
2691 fRc = True;
2692 try:
2693 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
2694 [], [], 30 * 1000);
2695 except:
2696 fRc = reporter.errorXcpt();
2697 else:
2698 reporter.log('Waiting for process 1 being started ...');
2699 try:
2700 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2701 except:
2702 fRc = reporter.errorXcpt();
2703 else:
2704 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2705 fRc = reporter.error('Waiting for process 1 to start failed, got status %d' % (eWaitResult,));
2706 else:
2707 for msWait in (1, 32, 2000,):
2708 reporter.log('Waiting for process 1 to time out within %sms ...' % (msWait,));
2709 try:
2710 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], msWait);
2711 except:
2712 fRc = reporter.errorXcpt();
2713 break;
2714 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
2715 fRc = reporter.error('Waiting for process 1 did not time out in %sms as expected: %d'
2716 % (msWait, eWaitResult,));
2717 break;
2718 reporter.log('Waiting for process 1 timed out in %u ms, good' % (msWait,));
2719
2720 try:
2721 oCurProcess.terminate();
2722 except:
2723 reporter.errorXcpt();
2724 oCurProcess = None;
2725
2726 #
2727 # Create another process that doesn't terminate, but which will be killed by VBoxService
2728 # because it ran out of execution time (3 seconds).
2729 #
2730 try:
2731 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
2732 [], [], 3 * 1000);
2733 except:
2734 fRc = reporter.errorXcpt();
2735 else:
2736 reporter.log('Waiting for process 2 being started ...');
2737 try:
2738 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2739 except:
2740 fRc = reporter.errorXcpt();
2741 else:
2742 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2743 fRc = reporter.error('Waiting for process 2 to start failed, got status %d' % (eWaitResult,));
2744 else:
2745 reporter.log('Waiting for process 2 to get killed for running out of execution time ...');
2746 try:
2747 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 15 * 1000);
2748 except:
2749 fRc = reporter.errorXcpt();
2750 else:
2751 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
2752 fRc = reporter.error('Waiting for process 2 did not time out when it should, got wait result %d'
2753 % (eWaitResult,));
2754 else:
2755 reporter.log('Waiting for process 2 did not time out, good: %s' % (eWaitResult,));
2756 try:
2757 eStatus = oCurProcess.status;
2758 except:
2759 fRc = reporter.errorXcpt();
2760 else:
2761 if eStatus != vboxcon.ProcessStatus_TimedOutKilled:
2762 fRc = reporter.error('Status of process 2 wrong; excepted %d, got %d'
2763 % (vboxcon.ProcessStatus_TimedOutKilled, eStatus));
2764 else:
2765 reporter.log('Status of process 2 is TimedOutKilled (%d) is it should be.'
2766 % (vboxcon.ProcessStatus_TimedOutKilled,));
2767 try:
2768 oCurProcess.terminate();
2769 except:
2770 reporter.logXcpt();
2771 oCurProcess = None;
2772
2773 #
2774 # Clean up the session.
2775 #
2776 try:
2777 oGuestSession.close();
2778 except:
2779 fRc = reporter.errorXcpt();
2780
2781 return (fRc, oTxsSession);
2782
2783 def testGuestCtrlDirCreate(self, oSession, oTxsSession, oTestVm):
2784 """
2785 Tests creation of guest directories.
2786 """
2787
2788 sScratch = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'testGuestCtrlDirCreate');
2789
2790 atTests = [
2791 # Invalid stuff.
2792 [ tdTestDirCreate(sDirectory = '' ), tdTestResultFailure() ],
2793 # More unusual stuff.
2794 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '.') ), tdTestResultFailure() ],
2795 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '..') ), tdTestResultFailure() ],
2796 [ tdTestDirCreate(sDirectory = '..' ), tdTestResultFailure() ],
2797 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
2798 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
2799 [ tdTestDirCreate(sDirectory = '/' ), tdTestResultFailure() ],
2800 [ tdTestDirCreate(sDirectory = '/..' ), tdTestResultFailure() ],
2801 [ tdTestDirCreate(sDirectory = '/../' ), tdTestResultFailure() ],
2802 ];
2803 if oTestVm.isWindows() or oTestVm.isOS2():
2804 atTests.extend([
2805 [ tdTestDirCreate(sDirectory = 'C:\\' ), tdTestResultFailure() ],
2806 [ tdTestDirCreate(sDirectory = 'C:\\..' ), tdTestResultFailure() ],
2807 [ tdTestDirCreate(sDirectory = 'C:\\..\\' ), tdTestResultFailure() ],
2808 [ tdTestDirCreate(sDirectory = 'C:/' ), tdTestResultFailure() ],
2809 [ tdTestDirCreate(sDirectory = 'C:/.' ), tdTestResultFailure() ],
2810 [ tdTestDirCreate(sDirectory = 'C:/./' ), tdTestResultFailure() ],
2811 [ tdTestDirCreate(sDirectory = 'C:/..' ), tdTestResultFailure() ],
2812 [ tdTestDirCreate(sDirectory = 'C:/../' ), tdTestResultFailure() ],
2813 [ tdTestDirCreate(sDirectory = '\\\\uncrulez\\foo' ), tdTestResultFailure() ],
2814 ]);
2815 atTests.extend([
2816 # Existing directories and files.
2817 [ tdTestDirCreate(sDirectory = self.getGuestSystemDir(oTestVm) ), tdTestResultFailure() ],
2818 [ tdTestDirCreate(sDirectory = self.getGuestSystemShell(oTestVm) ), tdTestResultFailure() ],
2819 [ tdTestDirCreate(sDirectory = self.getGuestSystemFileForReading(oTestVm) ), tdTestResultFailure() ],
2820 # Creating directories.
2821 [ tdTestDirCreate(sDirectory = sScratch ), tdTestResultSuccess() ],
2822 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
2823 fFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
2824 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
2825 fFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
2826 # Long random names.
2827 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(36, 28))),
2828 tdTestResultSuccess() ],
2829 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(140, 116))),
2830 tdTestResultSuccess() ],
2831 # Too long names. ASSUMES a guests has a 255 filename length limitation.
2832 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
2833 tdTestResultFailure() ],
2834 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
2835 tdTestResultFailure() ],
2836 # Missing directory in path.
2837 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo1', 'bar') ), tdTestResultFailure() ],
2838 ]);
2839
2840 fRc = True;
2841 for (i, tTest) in enumerate(atTests):
2842 oCurTest = tTest[0] # type: tdTestDirCreate
2843 oCurRes = tTest[1] # type: tdTestResult
2844 reporter.log('Testing #%d, sDirectory="%s" ...' % (i, oCurTest.sDirectory));
2845
2846 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2847 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreate: Test #%d' % (i,), fIsError = True);
2848 if fRc is False:
2849 return reporter.error('Test #%d failed: Could not create session' % (i,));
2850
2851 fRc = self.gctrlCreateDir(oCurTest, oCurRes, oCurGuestSession);
2852
2853 fRc = oCurTest.closeSession(fIsError = True) and fRc;
2854 if fRc is False:
2855 fRc = reporter.error('Test #%d failed' % (i,));
2856
2857 return (fRc, oTxsSession);
2858
2859 def testGuestCtrlDirCreateTemp(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2860 """
2861 Tests creation of temporary directories.
2862 """
2863
2864 sSystemDir = self.getGuestSystemDir(oTestVm);
2865 atTests = [
2866 # Invalid stuff (template must have one or more trailin 'X'es (upper case only), or a cluster of three or more).
2867 [ tdTestDirCreateTemp(sDirectory = ''), tdTestResultFailure() ],
2868 [ tdTestDirCreateTemp(sDirectory = sSystemDir, fMode = 1234), tdTestResultFailure() ],
2869 [ tdTestDirCreateTemp(sTemplate = 'xXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2870 [ tdTestDirCreateTemp(sTemplate = 'xxx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2871 [ tdTestDirCreateTemp(sTemplate = 'XXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2872 [ tdTestDirCreateTemp(sTemplate = 'bar', sDirectory = 'whatever', fMode = 0o700), tdTestResultFailure() ],
2873 [ tdTestDirCreateTemp(sTemplate = 'foo', sDirectory = 'it is not used', fMode = 0o700), tdTestResultFailure() ],
2874 [ tdTestDirCreateTemp(sTemplate = 'X,so', sDirectory = 'pointless test', fMode = 0o700), tdTestResultFailure() ],
2875 # Non-existing stuff.
2876 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX',
2877 sDirectory = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'non', 'existing')),
2878 tdTestResultFailure() ],
2879 # Working stuff:
2880 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2881 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2882 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2883 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2884 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2885 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2886 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2887 ## @todo test fSecure and pass weird fMode values once these parameters are implemented in the API.
2888 ];
2889
2890 fRc = True;
2891 for (i, tTest) in enumerate(atTests):
2892 oCurTest = tTest[0] # type: tdTestDirCreateTemp
2893 oCurRes = tTest[1] # type: tdTestResult
2894 reporter.log('Testing #%d, sTemplate="%s", fMode=%#o, path="%s", secure="%s" ...' %
2895 (i, oCurTest.sTemplate, oCurTest.fMode, oCurTest.sDirectory, oCurTest.fSecure));
2896
2897 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2898 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreateTemp: Test #%d' % (i,), fIsError = True);
2899 if fRc is False:
2900 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
2901 break;
2902
2903 sDirTemp = '';
2904 try:
2905 sDirTemp = oCurGuestSession.directoryCreateTemp(oCurTest.sTemplate, oCurTest.fMode,
2906 oCurTest.sDirectory, oCurTest.fSecure);
2907 except:
2908 if oCurRes.fRc is True:
2909 fRc = reporter.errorXcpt('Creating temp directory "%s" failed:' % (oCurTest.sDirectory,));
2910 else:
2911 reporter.logXcpt('Creating temp directory "%s" failed expectedly, skipping:' % (oCurTest.sDirectory,));
2912 else:
2913 reporter.log2('Temporary directory is: "%s"' % (sDirTemp,));
2914 if not sDirTemp:
2915 fRc = reporter.error('Resulting directory is empty!');
2916 else:
2917 ## @todo This does not work for some unknown reason.
2918 #try:
2919 # if self.oTstDrv.fpApiVer >= 5.0:
2920 # fExists = oCurGuestSession.directoryExists(sDirTemp, False);
2921 # else:
2922 # fExists = oCurGuestSession.directoryExists(sDirTemp);
2923 #except:
2924 # fRc = reporter.errorXcpt('sDirTemp=%s' % (sDirTemp,));
2925 #else:
2926 # if fExists is not True:
2927 # fRc = reporter.error('Test #%d failed: Temporary directory "%s" does not exists (%s)'
2928 # % (i, sDirTemp, fExists));
2929 try:
2930 oFsObjInfo = oCurGuestSession.fsObjQueryInfo(sDirTemp, False);
2931 eType = oFsObjInfo.type;
2932 except:
2933 fRc = reporter.errorXcpt('sDirTemp="%s"' % (sDirTemp,));
2934 else:
2935 reporter.log2('%s: eType=%s (dir=%d)' % (sDirTemp, eType, vboxcon.FsObjType_Directory,));
2936 if eType != vboxcon.FsObjType_Directory:
2937 fRc = reporter.error('Temporary directory "%s" not created as a directory: eType=%d'
2938 % (sDirTemp, eType));
2939 fRc = oCurTest.closeSession(True) and fRc;
2940 return (fRc, oTxsSession);
2941
2942 def testGuestCtrlDirRead(self, oSession, oTxsSession, oTestVm):
2943 """
2944 Tests opening and reading (enumerating) guest directories.
2945 """
2946
2947 sSystemDir = self.getGuestSystemDir(oTestVm);
2948 atTests = [
2949 # Invalid stuff.
2950 [ tdTestDirRead(sDirectory = ''), tdTestResultDirRead() ],
2951 [ tdTestDirRead(sDirectory = sSystemDir, fFlags = [ 1234 ]), tdTestResultDirRead() ],
2952 [ tdTestDirRead(sDirectory = sSystemDir, sFilter = '*.foo'), tdTestResultDirRead() ],
2953 # Non-existing stuff.
2954 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'really-no-such-subdir')), tdTestResultDirRead() ],
2955 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'non', 'existing')), tdTestResultDirRead() ],
2956 ];
2957
2958 if oTestVm.isWindows() or oTestVm.isOS2():
2959 atTests.extend([
2960 # More unusual stuff.
2961 [ tdTestDirRead(sDirectory = 'z:\\'), tdTestResultDirRead() ],
2962 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
2963 ]);
2964 else:
2965 atTests.extend([
2966 # More unusual stuff.
2967 [ tdTestDirRead(sDirectory = 'z:/'), tdTestResultDirRead() ],
2968 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
2969 ]);
2970 # Read the system directory (ASSUMES at least 5 files in it):
2971 atTests.append([ tdTestDirRead(sDirectory = sSystemDir), tdTestResultDirRead(fRc = True, cFiles = -5, cDirs = None) ]);
2972 ## @todo trailing slash
2973
2974 # Read from the test file set.
2975 atTests.extend([
2976 [ tdTestDirRead(sDirectory = self.oTestFiles.oEmptyDir.sPath),
2977 tdTestResultDirRead(fRc = True, cFiles = 0, cDirs = 0, cOthers = 0) ],
2978 [ tdTestDirRead(sDirectory = self.oTestFiles.oManyDir.sPath),
2979 tdTestResultDirRead(fRc = True, cFiles = len(self.oTestFiles.oManyDir.aoChildren), cDirs = 0, cOthers = 0) ],
2980 [ tdTestDirRead(sDirectory = self.oTestFiles.oTreeDir.sPath),
2981 tdTestResultDirRead(fRc = True, cFiles = self.oTestFiles.cTreeFiles, cDirs = self.oTestFiles.cTreeDirs,
2982 cOthers = self.oTestFiles.cTreeOthers) ],
2983 ]);
2984
2985
2986 fRc = True;
2987 for (i, tTest) in enumerate(atTests):
2988 oCurTest = tTest[0] # type: tdTestExec
2989 oCurRes = tTest[1] # type: tdTestResultDirRead
2990
2991 reporter.log('Testing #%d, dir="%s" ...' % (i, oCurTest.sDirectory));
2992 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2993 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: Test #%d' % (i,), True);
2994 if fRc is not True:
2995 break;
2996 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc);
2997 fRc = oCurTest.closeSession(True) and fRc;
2998
2999 reporter.log2('Test #%d: Returned %d directories, %d files total' % (i, cDirs, cFiles));
3000 if fRc2 is oCurRes.fRc:
3001 if fRc2 is True:
3002 if oCurRes.cFiles is None:
3003 pass; # ignore
3004 elif oCurRes.cFiles >= 0 and cFiles != oCurRes.cFiles:
3005 fRc = reporter.error('Test #%d failed: Got %d files, expected %d' % (i, cFiles, oCurRes.cFiles));
3006 elif oCurRes.cFiles < 0 and cFiles < -oCurRes.cFiles:
3007 fRc = reporter.error('Test #%d failed: Got %d files, expected at least %d'
3008 % (i, cFiles, -oCurRes.cFiles));
3009 if oCurRes.cDirs is None:
3010 pass; # ignore
3011 elif oCurRes.cDirs >= 0 and cDirs != oCurRes.cDirs:
3012 fRc = reporter.error('Test #%d failed: Got %d directories, expected %d' % (i, cDirs, oCurRes.cDirs));
3013 elif oCurRes.cDirs < 0 and cDirs < -oCurRes.cDirs:
3014 fRc = reporter.error('Test #%d failed: Got %d directories, expected at least %d'
3015 % (i, cDirs, -oCurRes.cDirs));
3016 if oCurRes.cOthers is None:
3017 pass; # ignore
3018 elif oCurRes.cOthers >= 0 and cOthers != oCurRes.cOthers:
3019 fRc = reporter.error('Test #%d failed: Got %d other types, expected %d' % (i, cOthers, oCurRes.cOthers));
3020 elif oCurRes.cOthers < 0 and cOthers < -oCurRes.cOthers:
3021 fRc = reporter.error('Test #%d failed: Got %d other types, expected at least %d'
3022 % (i, cOthers, -oCurRes.cOthers));
3023
3024 else:
3025 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3026
3027
3028 #
3029 # Go over a few directories in the test file set and compare names,
3030 # types and sizes rather than just the counts like we did above.
3031 #
3032 if fRc is True:
3033 oCurTest = tdTestDirRead();
3034 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3035 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: gctrlReadDirTree2', True);
3036 if fRc is True:
3037 for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir):
3038 reporter.log('Checking "%s" ...' % (oDir.sPath,));
3039 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir) and fRc;
3040 fRc = oCurTest.closeSession(True) and fRc;
3041
3042 return (fRc, oTxsSession);
3043
3044 def testGuestCtrlFileRemove(self, oSession, oTxsSession, oTestVm):
3045 """
3046 Tests removing guest files.
3047 """
3048
3049 ## @todo r=bird: This fails on windows 7 RTM. Just create a stupid file and delete it again,
3050 # this chord.wav stuff is utter nonsense.
3051 if oTestVm.isWindows():
3052 sFileToDelete = "c:\\Windows\\Media\\chord.wav";
3053 else:
3054 sFileToDelete = "/home/vbox/.profile";
3055
3056 atTests = [];
3057 if oTestVm.isWindows():
3058 atTests.extend([
3059 # Invalid stuff.
3060 [ tdTestFileRemove(sFile = ''), tdTestResultFailure() ],
3061 [ tdTestFileRemove(sFile = 'C:\\Windows'), tdTestResultFailure() ],
3062 # More unusual stuff.
3063 [ tdTestFileRemove(sFile = 'z:\\'), tdTestResultFailure() ],
3064 [ tdTestFileRemove(sFile = '\\\\uncrulez\\foo'), tdTestResultFailure() ],
3065 # Non-existing stuff.
3066 [ tdTestFileRemove(sFile = 'c:\\Apps\\nonexisting'), tdTestResultFailure() ],
3067 # Try to delete system files.
3068 [ tdTestFileRemove(sFile = 'c:\\pagefile.sys'), tdTestResultFailure() ],
3069 [ tdTestFileRemove(sFile = 'c:\\Windows\\kernel32.sys'), tdTestResultFailure() ] ## r=bird: it's in \system32\ ...
3070 ]);
3071
3072 if oTestVm.sKind == "WindowsXP":
3073 atTests.extend([
3074 # Try delete some unimportant media stuff.
3075 [ tdTestFileRemove(sFile = 'c:\\Windows\\Media\\chimes.wav'), tdTestResultSuccess() ],
3076 # Second attempt should fail.
3077 [ tdTestFileRemove(sFile = 'c:\\Windows\\Media\\chimes.wav'), tdTestResultFailure() ]
3078 ]);
3079 elif oTestVm.isLinux():
3080 atTests.extend([
3081 # Invalid stuff.
3082 [ tdTestFileRemove(sFile = ''), tdTestResultFailure() ],
3083 [ tdTestFileRemove(sFile = 'C:\\Windows'), tdTestResultFailure() ],
3084 # More unusual stuff.
3085 [ tdTestFileRemove(sFile = 'z:/'), tdTestResultFailure() ],
3086 [ tdTestFileRemove(sFile = '//uncrulez/foo'), tdTestResultFailure() ],
3087 # Non-existing stuff.
3088 [ tdTestFileRemove(sFile = '/non/existing'), tdTestResultFailure() ],
3089 # Try to delete system files.
3090 [ tdTestFileRemove(sFile = '/etc'), tdTestResultFailure() ],
3091 [ tdTestFileRemove(sFile = '/bin/sh'), tdTestResultFailure() ]
3092 ]);
3093
3094 atTests.extend([
3095 # Try delete some unimportant stuff.
3096 [ tdTestFileRemove(sFile = sFileToDelete), tdTestResultSuccess() ],
3097 # Second attempt should fail.
3098 [ tdTestFileRemove(sFile = sFileToDelete), tdTestResultFailure() ]
3099 ]);
3100
3101 fRc = True;
3102 for (i, aTest) in enumerate(atTests):
3103 oCurTest = aTest[0]; # tdTestExec, use an index, later.
3104 oCurRes = aTest[1]; # tdTestResult
3105 reporter.log('Testing #%d, file="%s" ...' % (i, oCurTest.sFile));
3106 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3107 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileRemove: Test #%d' % (i,));
3108 if fRc is False:
3109 reporter.error('Test #%d failed: Could not create session' % (i,));
3110 break;
3111 try:
3112 if self.oTstDrv.fpApiVer >= 5.0:
3113 oCurGuestSession.fsObjRemove(oCurTest.sFile);
3114 else:
3115 oCurGuestSession.fileRemove(oCurTest.sFile);
3116 except:
3117 if oCurRes.fRc is True:
3118 reporter.errorXcpt('Removing file "%s" failed:' % (oCurTest.sFile,));
3119 fRc = False;
3120 break;
3121 else:
3122 reporter.logXcpt('Removing file "%s" failed expectedly, skipping:' % (oCurTest.sFile,));
3123 oCurTest.closeSession();
3124 return (fRc, oTxsSession);
3125
3126 def testGuestCtrlFileStat(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3127 """
3128 Tests querying file information through stat.
3129 """
3130
3131 # Basic stuff, existing stuff.
3132 aoTests = [
3133 tdTestSessionEx([
3134 tdStepStatDir('.'),
3135 tdStepStatDir('..'),
3136 tdStepStatDir(self.getGuestTempDir(oTestVm)),
3137 tdStepStatDir(self.getGuestSystemDir(oTestVm)),
3138 tdStepStatDirEx(self.oTestFiles.oRoot),
3139 tdStepStatDirEx(self.oTestFiles.oEmptyDir),
3140 tdStepStatDirEx(self.oTestFiles.oTreeDir),
3141 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3142 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3143 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3144 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3145 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3146 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3147 tdStepStatFile(self.getGuestSystemFileForReading(oTestVm)),
3148 tdStepStatFile(self.getGuestSystemShell(oTestVm)),
3149 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3150 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3151 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3152 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3153 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3154 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3155 ]),
3156 ];
3157
3158 # None existing stuff.
3159 sSysDir = self.getGuestSystemDir(oTestVm);
3160 sSep = oTestVm.pathSep();
3161 aoTests += [
3162 tdTestSessionEx([
3163 tdStepStatFileNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory')),
3164 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory') + sSep),
3165 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', '.')),
3166 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory')),
3167 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory') + sSep),
3168 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory', '.')),
3169 #tdStepStatPathNotFound('N:\\'), # ASSUMES nothing mounted on N:!
3170 #tdStepStatPathNotFound('\\\\NoSuchUncServerName\\NoSuchShare'),
3171 ]),
3172 ];
3173 # Invalid parameter check.
3174 aoTests += [ tdTestSessionEx([ tdStepStat('', vbox.ComError.E_INVALIDARG), ]), ];
3175
3176 #
3177 # Execute the tests.
3178 #
3179 fRc, oTxsSession = tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession,
3180 oTestVm, 'FsStat');
3181 #
3182 # Test the full test file set.
3183 #
3184 if self.oTstDrv.fpApiVer < 5.0:
3185 return (fRc, oTxsSession);
3186
3187 oTest = tdTestGuestCtrlBase();
3188 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
3189 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet', True);
3190 if fRc2 is not True:
3191 return (False, oTxsSession);
3192
3193 for sPath in self.oTestFiles.dPaths:
3194 oFsObj = self.oTestFiles.dPaths[sPath];
3195 reporter.log2('testGuestCtrlFileStat: %s sPath=%s'
3196 % ('file' if isinstance(oFsObj, testfileset.TestFile) else 'dir ', oFsObj.sPath,));
3197
3198 # Query the information:
3199 try:
3200 oFsInfo = oGuestSession.fsObjQueryInfo(oFsObj.sPath, False);
3201 except:
3202 fRc = reporter.errorXcpt('sPath=%s type=%s: fsObjQueryInfo trouble!' % (oFsObj.sPath, type(oFsObj),));
3203 continue;
3204 if oFsInfo is None:
3205 fRc = reporter.error('sPath=%s type=%s: No info object returned!' % (oFsObj.sPath, type(oFsObj),));
3206 continue;
3207
3208 # Check attributes:
3209 try:
3210 eType = oFsInfo.type;
3211 cbObject = oFsInfo.objectSize;
3212 except:
3213 fRc = reporter.errorXcpt('sPath=%s type=%s: attribute access trouble!' % (oFsObj.sPath, type(oFsObj),));
3214 continue;
3215
3216 if isinstance(oFsObj, testfileset.TestFile):
3217 if eType != vboxcon.FsObjType_File:
3218 fRc = reporter.error('sPath=%s type=file: eType=%s, expected %s!'
3219 % (oFsObj.sPath, eType, vboxcon.FsObjType_File));
3220 if cbObject != oFsObj.cbContent:
3221 fRc = reporter.error('sPath=%s type=file: cbObject=%s, expected %s!'
3222 % (oFsObj.sPath, cbObject, oFsObj.cbContent));
3223 fFileExists = True;
3224 fDirExists = False;
3225 elif isinstance(oFsObj, testfileset.TestDir):
3226 if eType != vboxcon.FsObjType_Directory:
3227 fRc = reporter.error('sPath=%s type=dir: eType=%s, expected %s!'
3228 % (oFsObj.sPath, eType, vboxcon.FsObjType_Directory));
3229 fFileExists = False;
3230 fDirExists = True;
3231 else:
3232 fRc = reporter.error('sPath=%s type=%s: Unexpected oFsObj type!' % (oFsObj.sPath, type(oFsObj),));
3233 continue;
3234
3235 # Check the directoryExists and fileExists results too.
3236 try:
3237 fExistsResult = oGuestSession.fileExists(oFsObj.sPath, False);
3238 except:
3239 fRc = reporter.errorXcpt('sPath=%s type=%s: fileExists trouble!' % (oFsObj.sPath, type(oFsObj),));
3240 else:
3241 if fExistsResult != fFileExists:
3242 fRc = reporter.error('sPath=%s type=%s: fileExists returned %s, expected %s!'
3243 % (oFsObj.sPath, type(oFsObj), fExistsResult, fFileExists));
3244
3245 if not self.fSkipKnownBugs: ## @todo At least two different failures here.
3246 try:
3247 fExistsResult = oGuestSession.directoryExists(oFsObj.sPath, False);
3248 except:
3249 fRc = reporter.errorXcpt('sPath=%s type=%s: directoryExists trouble!' % (oFsObj.sPath, type(oFsObj),));
3250 else:
3251 if fExistsResult != fDirExists:
3252 fRc = reporter.error('sPath=%s type=%s: directoryExists returned %s, expected %s!'
3253 % (oFsObj.sPath, type(oFsObj), fExistsResult, fDirExists));
3254
3255 fRc = oTest.closeSession(True) and fRc;
3256 return (fRc, oTxsSession);
3257
3258 def testGuestCtrlFileRead(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3259 """
3260 Tests reading from guest files.
3261 """
3262
3263 if oTxsSession.syncMkDir('${SCRATCH}/testGuestCtrlFileRead') is False:
3264 reporter.error('Could not create scratch directory on guest');
3265 return (False, oTxsSession);
3266
3267 atTests = [];
3268 atTests.extend([
3269 # Invalid stuff.
3270 [ tdTestFileReadWrite(cbToReadWrite = 0), tdTestResultFileReadWrite() ],
3271 [ tdTestFileReadWrite(sFile = ''), tdTestResultFileReadWrite() ],
3272 [ tdTestFileReadWrite(sFile = 'non-existing.file'), tdTestResultFileReadWrite() ],
3273 # Wrong open mode.
3274 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'rt', sDisposition = 'oe'),
3275 tdTestResultFileReadWrite() ],
3276 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'tr', sDisposition = 'oe'),
3277 tdTestResultFileReadWrite() ],
3278 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'wr', sDisposition = 'oe'),
3279 tdTestResultFileReadWrite() ],
3280 # Wrong disposition.
3281 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'r', sDisposition = 'e'),
3282 tdTestResultFileReadWrite() ],
3283 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'r', sDisposition = 'o'),
3284 tdTestResultFileReadWrite() ],
3285 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'r', sDisposition = 'c'),
3286 tdTestResultFileReadWrite() ],
3287 # Opening non-existing file when it should exist.
3288 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3289 tdTestResultFileReadWrite() ],
3290 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3291 tdTestResultFileReadWrite() ],
3292 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3293 tdTestResultFileReadWrite() ]
3294 ]);
3295
3296 if oTestVm.isWindows():
3297 atTests.extend([
3298 # Create a file which must not exist (but it hopefully does).
3299 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\calc.exe', sOpenMode = 'w', sDisposition = 'ce'),
3300 tdTestResultFileReadWrite() ],
3301 # Open a file which must exist.
3302 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\kernel32.dll', sOpenMode = 'r', sDisposition = 'oe'),
3303 tdTestResultFileReadWrite(fRc = True) ],
3304 # Try truncating a file which already is opened with a different sharing mode (and thus should fail).
3305 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\kernel32.dll', sOpenMode = 'w', sDisposition = 'ot'),
3306 tdTestResultFileReadWrite() ]
3307 ]);
3308
3309 # Note: tst-xppro has other contents in eula.txt.
3310 if oTestVm.sVmName.startswith('tst-xpsp2'):
3311 atTests.extend([
3312 # Reading from beginning.
3313 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\eula.txt',
3314 sOpenMode = 'r', sDisposition = 'oe', cbToReadWrite = 33),
3315 tdTestResultFileReadWrite(fRc = True, abBuf = 'Microsoft(r) Windows(r) XP Profes',
3316 cbProcessed = 33, offFile = 33) ],
3317 # Reading from offset.
3318 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\eula.txt',
3319 sOpenMode = 'r', sDisposition = 'oe', offFile = 17769, cbToReadWrite = 31),
3320 tdTestResultFileReadWrite(fRc = True, abBuf = 'only with the HARDWARE. If\x0d\x0a ',
3321 cbProcessed = 31, offFile = 17769 + 31) ]
3322 ]);
3323 elif oTestVm.isLinux():
3324 atTests.extend([
3325 # Create a file which must not exist (but it hopefully does).
3326 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'w', sDisposition = 'ce'),
3327 tdTestResultFileReadWrite() ],
3328 # Open a file which must exist.
3329 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'r', sDisposition = 'oe'),
3330 tdTestResultFileReadWrite(fRc = True) ],
3331 # Try truncating a file which already is opened with a different sharing mode (and thus should fail).
3332 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'w', sDisposition = 'ot'),
3333 tdTestResultFileReadWrite() ]
3334 ]);
3335
3336 fRc = True;
3337 for (i, aTest) in enumerate(atTests):
3338 oCurTest = aTest[0]; # tdTestFileReadWrite, use an index, later.
3339 oCurRes = aTest[1]; # tdTestResult
3340 reporter.log('Testing #%d, sFile="%s", cbToReadWrite=%d, sOpenMode="%s", sDisposition="%s", offFile=%d ...'
3341 % (i, oCurTest.sFile, oCurTest.cbToReadWrite, oCurTest.sOpenMode,
3342 oCurTest.sDisposition, oCurTest.offFile));
3343 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3344 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileRead: Test #%d' % (i,));
3345 if fRc is False:
3346 reporter.error('Test #%d failed: Could not create session' % (i,));
3347 break;
3348 try:
3349 fRc2 = True;
3350 if oCurTest.offFile > 0: # The offset parameter is gone.
3351 if self.oTstDrv.fpApiVer >= 5.0:
3352 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3353 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3354 curFile.seek(oCurTest.offFile, vboxcon.FileSeekOrigin_Begin);
3355 else:
3356 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3357 oCurTest.sSharingMode, oCurTest.fCreationMode, oCurTest.offFile);
3358 curOffset = long(curFile.offset);
3359 resOffset = long(oCurTest.offFile);
3360 if curOffset != resOffset:
3361 reporter.error('Test #%d failed: Initial offset on open does not match: Got %d, expected %d'
3362 % (i, curOffset, resOffset));
3363 fRc2 = False;
3364 else:
3365 if self.oTstDrv.fpApiVer >= 5.0:
3366 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3367 oCurTest.fCreationMode);
3368 else:
3369 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3370 oCurTest.fCreationMode);
3371 if fRc2 and oCurTest.cbToReadWrite > 0:
3372 ## @todo Split this up in 64K reads. Later.
3373 ## @todo Test timeouts.
3374 aBufRead = curFile.read(oCurTest.cbToReadWrite, 30 * 1000);
3375 if oCurRes.cbProcessed > 0 \
3376 and oCurRes.cbProcessed != len(aBufRead):
3377 reporter.error('Test #%d failed: Read buffer length does not match: Got %d, expected %d'
3378 % (i, len(aBufRead), oCurRes.cbProcessed));
3379 fRc2 = False;
3380 if fRc2:
3381 if oCurRes.abBuf is not None \
3382 and not utils.areBytesEqual(oCurRes.abBuf, aBufRead):
3383 reporter.error('Test #%d failed: Got buffer:\n"%s" (%d bytes, type %s)\n'
3384 'Expected buffer:\n"%s" (%d bytes, type %s)'
3385 % (i, map(hex, map(ord, aBufRead)), len(aBufRead), type(aBufRead),
3386 map(hex, map(ord, oCurRes.abBuf)), len(oCurRes.abBuf), type(oCurRes.abBuf),));
3387 reporter.error('Test #%d failed: Got buffer:\n"%s"\nExpected buffer:\n"%s"'
3388 % (i, aBufRead, oCurRes.abBuf));
3389 fRc2 = False;
3390 # Test final offset.
3391 curOffset = long(curFile.offset);
3392 resOffset = long(oCurRes.offFile);
3393 if curOffset != resOffset:
3394 reporter.error('Test #%d failed: Final offset does not match: Got %d, expected %d' \
3395 % (i, curOffset, resOffset));
3396 fRc2 = False;
3397 curFile.close();
3398
3399 if fRc2 != oCurRes.fRc:
3400 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3401 fRc = False;
3402
3403 except:
3404 reporter.logXcpt('Opening "%s" failed:' % (oCurTest.sFile,));
3405 fRc = False;
3406
3407 oCurTest.closeSession();
3408
3409 return (fRc, oTxsSession);
3410
3411 def testGuestCtrlFileWrite(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3412 """
3413 Tests writing to guest files.
3414 """
3415
3416 if oTestVm.isWindows():
3417 sScratch = "C:\\Temp\\vboxtest\\testGuestCtrlFileWrite\\";
3418 else:
3419 sScratch = "/tmp/";
3420
3421 if oTxsSession.syncMkDir('${SCRATCH}/testGuestCtrlFileWrite') is False:
3422 reporter.error('Could not create scratch directory on guest');
3423 return (False, oTxsSession);
3424
3425 atTests = [];
3426
3427 cbScratchBuf = random.randint(1, 4096);
3428 abScratchBuf = os.urandom(cbScratchBuf);
3429 atTests.extend([
3430 # Write to a non-existing file.
3431 [ tdTestFileReadWrite(sFile = sScratch + 'testGuestCtrlFileWrite.txt',
3432 sOpenMode = 'w+', sDisposition = 'ce', cbToReadWrite = cbScratchBuf, abBuf = abScratchBuf),
3433 tdTestResultFileReadWrite(fRc = True, abBuf = abScratchBuf, cbProcessed = cbScratchBuf, offFile = cbScratchBuf) ],
3434 ]);
3435
3436 aScratchBuf2 = os.urandom(cbScratchBuf);
3437 atTests.extend([
3438 # Append the same amount of data to the just created file.
3439 [ tdTestFileReadWrite(sFile = sScratch + 'testGuestCtrlFileWrite.txt',
3440 sOpenMode = 'w+', sDisposition = 'oa', cbToReadWrite = cbScratchBuf,
3441 offFile = cbScratchBuf, abBuf = aScratchBuf2),
3442 tdTestResultFileReadWrite(fRc = True, abBuf = aScratchBuf2, cbProcessed = cbScratchBuf,
3443 offFile = cbScratchBuf * 2) ],
3444 ]);
3445
3446 fRc = True;
3447 for (i, aTest) in enumerate(atTests):
3448 oCurTest = aTest[0]; # tdTestFileReadWrite, use an index, later.
3449 oCurRes = aTest[1]; # tdTestResult
3450 reporter.log('Testing #%d, sFile="%s", cbToReadWrite=%d, sOpenMode="%s", sDisposition="%s", offFile=%d ...'
3451 % (i, oCurTest.sFile, oCurTest.cbToReadWrite, oCurTest.sOpenMode,
3452 oCurTest.sDisposition, oCurTest.offFile,));
3453 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3454 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileWrite: Test #%d' % (i,));
3455 if fRc is False:
3456 reporter.error('Test #%d failed: Could not create session' % (i,));
3457 break;
3458
3459 try:
3460 if oCurTest.offFile > 0: # The offset parameter is gone.
3461 if self.oTstDrv.fpApiVer >= 5.0:
3462 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3463 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3464 curFile.seek(oCurTest.offFile, vboxcon.FileSeekOrigin_Begin);
3465 else:
3466 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3467 oCurTest.sSharingMode, oCurTest.fCreationMode, oCurTest.offFile);
3468 curOffset = long(curFile.offset);
3469 resOffset = long(oCurTest.offFile);
3470 if curOffset != resOffset:
3471 reporter.error('Test #%d failed: Initial offset on open does not match: Got %d, expected %d' \
3472 % (i, curOffset, resOffset));
3473 fRc = False;
3474 else:
3475 if self.oTstDrv.fpApiVer >= 5.0:
3476 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3477 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3478 else:
3479 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3480 oCurTest.fCreationMode);
3481 if fRc and oCurTest.cbToReadWrite > 0:
3482 reporter.log("File '%s' opened" % oCurTest.sFile);
3483 ## @todo Split this up in 64K writes. Later.
3484 ## @todo Test timeouts.
3485 cBytesWritten = curFile.write(array('b', oCurTest.abBuf), 30 * 1000);
3486 if oCurRes.cbProcessed > 0 \
3487 and oCurRes.cbProcessed != cBytesWritten:
3488 reporter.error('Test #%d failed: Written buffer length does not match: Got %d, expected %d' \
3489 % (i, cBytesWritten, oCurRes.cbProcessed));
3490 fRc = False;
3491 if fRc:
3492 # Verify written content by seeking back to the initial offset and
3493 # re-read & compare the written data.
3494 try:
3495 if self.oTstDrv.fpApiVer >= 5.0:
3496 curFile.seek(-(oCurTest.cbToReadWrite), vboxcon.FileSeekOrigin_Current);
3497 else:
3498 curFile.seek(-(oCurTest.cbToReadWrite), vboxcon.FileSeekType_Current);
3499 except:
3500 reporter.logXcpt('Seeking back to initial write position failed:');
3501 fRc = False;
3502 if fRc and long(curFile.offset) != oCurTest.offFile:
3503 reporter.error('Test #%d failed: Initial write position does not match current position, ' \
3504 'got %d, expected %d' % (i, long(curFile.offset), oCurTest.offFile));
3505 fRc = False;
3506 if fRc:
3507 aBufRead = curFile.read(oCurTest.cbToReadWrite, 30 * 1000);
3508 if len(aBufRead) != oCurTest.cbToReadWrite:
3509 reporter.error('Test #%d failed: Got buffer length %d, expected %d' \
3510 % (i, len(aBufRead), oCurTest.cbToReadWrite));
3511 fRc = False;
3512 if fRc \
3513 and oCurRes.abBuf is not None \
3514 and bytes(oCurRes.abBuf) != bytes(aBufRead):
3515 reporter.error('Test #%d failed: Read back buffer (%d bytes) does not match ' \
3516 'written content (%d bytes)' % (i, len(aBufRead), len(aBufRead)));
3517
3518 curFile.close();
3519
3520 # Download written file from guest.
3521 aGstFiles = [];
3522 aGstFiles.append(oCurTest.sFile.replace('\\', '/'));
3523 self.oTstDrv.txsDownloadFiles(oSession, oTxsSession, aGstFiles, fIgnoreErrors = True);
3524
3525 # Create files with buffer contents and upload those for later (manual) inspection.
3526 oCurTest.uploadLogData(self.oTstDrv, oCurRes.abBuf, ('testGuestCtrlWriteTest%d-BufExcepted' % i),
3527 ('Test #%d: Expected buffer' % i));
3528 oCurTest.uploadLogData(self.oTstDrv, aBufRead, ('testGuestCtrlWriteTest%d-BufGot' % i),
3529 ('Test #%d: Got buffer' % i));
3530 fRc = False;
3531 # Test final offset.
3532 curOffset = long(curFile.offset);
3533 resOffset = long(oCurRes.offFile);
3534 if curOffset != resOffset:
3535 reporter.error('Test #%d failed: Final offset does not match: Got %d, expected %d' \
3536 % (i, curOffset, resOffset));
3537 fRc = False;
3538 if curFile.status == vboxcon.FileStatus_Open:
3539 curFile.close();
3540 reporter.log("File '%s' closed" % oCurTest.sFile);
3541 except:
3542 reporter.logXcpt('Opening "%s" failed:' % (oCurTest.sFile,));
3543 fRc = False;
3544
3545 oCurTest.closeSession();
3546
3547 if fRc != oCurRes.fRc:
3548 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
3549 fRc = False;
3550 break;
3551
3552 return (fRc, oTxsSession);
3553
3554 @staticmethod
3555 def __generateFile(sName, cbFile):
3556 """ Helper for generating a file with a given size. """
3557 oFile = open(sName, 'wb');
3558 while cbFile > 0:
3559 cb = cbFile if cbFile < 256*1024 else 256*1024;
3560 oFile.write(bytearray(random.getrandbits(8) for _ in xrange(cb)));
3561 cbFile -= cb;
3562 oFile.close();
3563
3564 def testGuestCtrlCopyTo(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3565 """
3566 Tests copying files from host to the guest.
3567 """
3568
3569 #
3570 # Paths and test files.
3571 #
3572 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, 'cp2');
3573 sScratchTestFilesHst = os.path.join(sScratchHst, self.oTestFiles.sSubDir);
3574 sScratchEmptyDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oEmptyDir.sName);
3575 sScratchNonEmptyDirHst = self.oTestFiles.chooseRandomDirFromTree().buildPath(sScratchHst, os.path.sep);
3576 sScratchTreeDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oTreeDir.sName);
3577
3578 sScratchGst = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'cp2');
3579 sScratchDstDir1Gst = oTestVm.pathJoin(sScratchGst, 'dstdir1');
3580 sScratchDstDir2Gst = oTestVm.pathJoin(sScratchGst, 'dstdir2');
3581 sScratchDstDir3Gst = oTestVm.pathJoin(sScratchGst, 'dstdir3');
3582 sScratchDstDir4Gst = oTestVm.pathJoin(sScratchGst, 'dstdir4');
3583 #sScratchGstNotExist = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'no-such-file-or-directory');
3584 sScratchHstNotExist = os.path.join(self.oTstDrv.sScratchPath, 'no-such-file-or-directory');
3585 sScratchGstPathNotFound = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'no-such-directory', 'or-file');
3586 #sScratchHstPathNotFound = os.path.join(self.oTstDrv.sScratchPath, 'no-such-directory', 'or-file');
3587
3588 if oTestVm.isWindows() or oTestVm.isOS2():
3589 sScratchGstInvalid = "?*|<invalid-name>";
3590 else:
3591 sScratchGstInvalid = None;
3592 if utils.getHostOs() in ('win', 'os2'):
3593 sScratchHstInvalid = "?*|<invalid-name>";
3594 else:
3595 sScratchHstInvalid = None;
3596
3597 for sDir in (sScratchGst, sScratchDstDir1Gst, sScratchDstDir2Gst, sScratchDstDir3Gst, sScratchDstDir4Gst):
3598 if oTxsSession.syncMkDir(sDir) is not True:
3599 return reporter.error('TXS failed to create directory "%s"!' % (sDir,));
3600
3601 # Put the test file set under sScratchHst.
3602 if os.path.exists(sScratchHst):
3603 if base.wipeDirectory(sScratchHst) != 0:
3604 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
3605 else:
3606 try:
3607 os.mkdir(sScratchHst);
3608 except:
3609 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
3610 if self.oTestFiles.writeToDisk(sScratchHst) is not True:
3611 return reporter.error('Filed to write test files to "%s" on the host!' % (sScratchHst,));
3612
3613 # Generate a test file in 32MB to 64 MB range.
3614 sBigFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-random.data');
3615 cbBigFileHst = random.randrange(32*1024*1024, 64*1024*1024);
3616 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
3617 cbLeft = cbBigFileHst;
3618 try:
3619 self.__generateFile(sBigFileHst, cbBigFileHst);
3620 except:
3621 return reporter.errorXcpt('sBigFileHst=%s cbBigFileHst=%s cbLeft=%s' % (sBigFileHst, cbBigFileHst, cbLeft,));
3622 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
3623
3624 # Generate an empty file on the host that we can use to save space in the guest.
3625 sEmptyFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-empty.data');
3626 try:
3627 oFile = open(sEmptyFileHst, "wb");
3628 oFile.close();
3629 except:
3630 return reporter.errorXcpt('sEmptyFileHst=%s' % (sEmptyFileHst,));
3631
3632 #
3633 # Tests.
3634 #
3635 atTests = [
3636 # Nothing given:
3637 [ tdTestCopyToFile(), tdTestResultFailure() ],
3638 [ tdTestCopyToDir(), tdTestResultFailure() ],
3639 # Only source given:
3640 [ tdTestCopyToFile(sSrc = sBigFileHst), tdTestResultFailure() ],
3641 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst), tdTestResultFailure() ],
3642 # Only destination given:
3643 [ tdTestCopyToFile(sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')), tdTestResultFailure() ],
3644 [ tdTestCopyToDir( sDst = sScratchGst), tdTestResultFailure() ],
3645 ];
3646 if not self.fSkipKnownBugs:
3647 atTests.extend([
3648 ## @todo Apparently Main doesn't check the flags, so the first test succeeds.
3649 # Both given, but invalid flags.
3650 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst, fFlags = [ 0x40000000] ), tdTestResultFailure() ],
3651 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGst, fFlags = [ 0x40000000] ),
3652 tdTestResultFailure() ],
3653 ]);
3654 atTests.extend([
3655 # Non-existing source, but no destination:
3656 [ tdTestCopyToFile(sSrc = sScratchHstNotExist), tdTestResultFailure() ],
3657 [ tdTestCopyToDir( sSrc = sScratchHstNotExist), tdTestResultFailure() ],
3658 # Valid sources, but destination path not found:
3659 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
3660 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
3661 # Valid destination, but source file/dir not found:
3662 [ tdTestCopyToFile(sSrc = sScratchHstNotExist, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
3663 tdTestResultFailure() ],
3664 [ tdTestCopyToDir( sSrc = sScratchHstNotExist, sDst = sScratchGst), tdTestResultFailure() ],
3665 # Wrong type:
3666 [ tdTestCopyToFile(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
3667 tdTestResultFailure() ],
3668 [ tdTestCopyToDir( sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultFailure() ],
3669 ]);
3670 # Invalid characters in destination or source path:
3671 if sScratchGstInvalid is not None:
3672 atTests.extend([
3673 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
3674 tdTestResultFailure() ],
3675 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
3676 tdTestResultFailure() ],
3677 ]);
3678 if sScratchHstInvalid is not None:
3679 atTests.extend([
3680 [ tdTestCopyToFile(sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
3681 tdTestResultFailure() ],
3682 [ tdTestCopyToDir( sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
3683 tdTestResultFailure() ],
3684 ]);
3685
3686 #
3687 # Single file handling.
3688 #
3689 atTests.extend([
3690 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')),
3691 tdTestResultSuccess() ],
3692 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
3693 tdTestResultSuccess() ],
3694 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
3695 tdTestResultSuccess() ],
3696 ]);
3697 if self.oTstDrv.fpApiVer > 5.2: # Copying files into directories via Main is supported only 6.0 and later.
3698 atTests.extend([
3699 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ],
3700 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ], # Overwrite
3701 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, os.path.split(sBigFileHst)[1])),
3702 tdTestResultSuccess() ], # Overwrite
3703 ]);
3704
3705 if oTestVm.isWindows():
3706 # Copy to a Windows alternative data stream (ADS).
3707 atTests.extend([
3708 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = os.path.join(sScratchGst, 'HostGABig.dat:ADS-Test')),
3709 tdTestResultSuccess() ],
3710 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = os.path.join(sScratchGst, 'HostGABig.dat:ADS-Test')),
3711 tdTestResultSuccess() ],
3712 ]);
3713
3714 #
3715 # Directory handling.
3716 #
3717 if self.oTstDrv.fpApiVer > 5.2: # Copying directories via Main is supported only in versions > 5.2.
3718 atTests.extend([
3719 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultSuccess() ],
3720 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultFailure() ],
3721 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
3722 fFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
3723 # Try again with trailing slash, should yield the same result:
3724 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
3725 tdTestResultSuccess() ],
3726 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
3727 tdTestResultFailure() ],
3728 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep(),
3729 fFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]),
3730 tdTestResultSuccess() ],
3731 ]);
3732 if not self.fSkipKnownBugs:
3733 atTests.extend([
3734 # Copy with a different destination name just for the heck of it:
3735 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchDstDir1Gst, 'empty2')),
3736 tdTestResultSuccess() ],
3737 ]);
3738 atTests.extend([
3739 # Now the same using a directory with files in it:
3740 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst), tdTestResultSuccess() ],
3741 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst), tdTestResultFailure() ],
3742 ]);
3743 if not self.fSkipKnownBugs:
3744 atTests.extend([
3745 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
3746 fFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
3747 ]);
3748 atTests.extend([
3749 #[ tdTestRemoveGuestDir(sScratchDstDir2Gst, tdTestResult() ],
3750 # Copy the entire test tree:
3751 [ tdTestCopyToDir(sSrc = sScratchTreeDirHst, sDst = sScratchDstDir4Gst), tdTestResultSuccess() ],
3752 #[ tdTestRemoveGuestDir(sScratchDstDir3Gst, tdTestResult() ],
3753 ]);
3754
3755 fRc = True;
3756 for (i, tTest) in enumerate(atTests):
3757 oCurTest = tTest[0]; # tdTestCopyTo
3758 oCurRes = tTest[1]; # tdTestResult
3759 reporter.log('Testing #%d, sSrc=%s, sDst=%s, fFlags=%s ...' % (i, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags));
3760
3761 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3762 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyTo: Test #%d' % (i,), fIsError = True);
3763 if fRc is not True:
3764 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3765 break;
3766
3767 fRc2 = False;
3768 if isinstance(oCurTest, tdTestCopyToFile):
3769 fRc2 = self.gctrlCopyFileTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags, oCurRes.fRc);
3770 else:
3771 fRc2 = self.gctrlCopyDirTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags, oCurRes.fRc);
3772 if fRc2 is not oCurRes.fRc:
3773 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3774
3775 fRc = oCurTest.closeSession(True) and fRc;
3776
3777 return (fRc, oTxsSession);
3778
3779 def testGuestCtrlCopyFrom(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3780 """
3781 Tests copying files from guest to the host.
3782 """
3783
3784 #
3785 # Paths.
3786 #
3787 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom");
3788 sScratchDstDir1Hst = os.path.join(sScratchHst, "dstdir1");
3789 sScratchDstDir2Hst = os.path.join(sScratchHst, "dstdir2");
3790 sScratchDstDir3Hst = os.path.join(sScratchHst, "dstdir3");
3791 oExistingFileGst = self.oTestFiles.chooseRandomFile();
3792 oNonEmptyDirGst = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True);
3793 oEmptyDirGst = self.oTestFiles.oEmptyDir;
3794
3795 if oTestVm.isWindows() or oTestVm.isOS2():
3796 sScratchGstInvalid = "?*|<invalid-name>";
3797 else:
3798 sScratchGstInvalid = None;
3799 if utils.getHostOs() in ('win', 'os2'):
3800 sScratchHstInvalid = "?*|<invalid-name>";
3801 else:
3802 sScratchHstInvalid = None;
3803
3804 if os.path.exists(sScratchHst):
3805 if base.wipeDirectory(sScratchHst) != 0:
3806 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
3807 else:
3808 try:
3809 os.mkdir(sScratchHst);
3810 except:
3811 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
3812
3813 for sSubDir in (sScratchDstDir1Hst, sScratchDstDir2Hst, sScratchDstDir3Hst):
3814 try:
3815 os.mkdir(sSubDir);
3816 except:
3817 return reporter.errorXcpt('os.mkdir(%s)' % (sSubDir, ));
3818
3819 #
3820 # Bad parameter tests.
3821 #
3822 atTests = [
3823 # Missing both source and destination:
3824 [ tdTestCopyFromFile(), tdTestResultFailure() ],
3825 [ tdTestCopyFromDir(), tdTestResultFailure() ],
3826 # Missing source.
3827 [ tdTestCopyFromFile(sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3828 [ tdTestCopyFromDir( sDst = sScratchHst), tdTestResultFailure() ],
3829 # Missing destination.
3830 [ tdTestCopyFromFile(oSrc = oExistingFileGst), tdTestResultFailure() ],
3831 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath), tdTestResultFailure() ],
3832 ##
3833 ## @todo main isn't validating flags, so these theses will succeed.
3834 ##
3835 ## Invalid flags:
3836 #[ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somefile'), fFlags = [ 0x40000000] ),
3837 # tdTestResultFailure() ],
3838 #[ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'somedir'), fFlags = [ 0x40000000] ),
3839 # tdTestResultFailure() ],
3840 # Non-existing sources:
3841 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
3842 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3843 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
3844 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3845 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-file'),
3846 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3847 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-subdir'),
3848 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3849 # Non-existing destinations:
3850 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
3851 sDst = os.path.join(sScratchHst, 'no-such-directory', 'somefile') ), tdTestResultFailure() ],
3852 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'no-such-directory', 'somedir') ),
3853 tdTestResultFailure() ],
3854 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
3855 sDst = os.path.join(sScratchHst, 'no-such-directory-slash' + os.path.sep)),
3856 tdTestResultFailure() ],
3857 # Wrong source type:
3858 [ tdTestCopyFromFile(oSrc = oNonEmptyDirGst, sDst = os.path.join(sScratchHst, 'somefile') ), tdTestResultFailure() ],
3859 [ tdTestCopyFromDir(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somedir') ), tdTestResultFailure() ],
3860 ];
3861 # Bogus names:
3862 if sScratchHstInvalid:
3863 atTests.extend([
3864 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
3865 tdTestResultFailure() ],
3866 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
3867 tdTestResultFailure() ],
3868 ]);
3869 if sScratchGstInvalid:
3870 atTests.extend([
3871 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
3872 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3873 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
3874 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3875 ]);
3876
3877 #
3878 # Single file copying.
3879 #
3880 atTests.extend([
3881 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')),
3882 tdTestResultSuccess() ],
3883 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')), # Overwrite it
3884 tdTestResultSuccess() ],
3885 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile2')),
3886 tdTestResultSuccess() ],
3887 ]);
3888 if self.oTstDrv.fpApiVer > 5.2:
3889 # Copy into a directory.
3890 atTests.extend([
3891 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst), tdTestResultSuccess() ],
3892 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst + os.path.sep), tdTestResultSuccess() ],
3893 ]);
3894
3895 #
3896 # Directory tree copying:
3897 #
3898 atTests.extend([
3899 # Copy the empty guest directory (should end up as sScratchHst/empty):
3900 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultSuccess() ],
3901 # Repeat -- this time it should fail, as the destination directory already exists (and
3902 # DirectoryCopyFlag_CopyIntoExisting is not specified):
3903 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultFailure() ],
3904 # Add the DirectoryCopyFlag_CopyIntoExisting flag being set and it should work.
3905 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst,
3906 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3907 # Try again with trailing slash, should yield the same result:
3908 [ tdTestRemoveHostDir(os.path.join(sScratchDstDir1Hst, 'empty')), tdTestResult() ],
3909 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
3910 tdTestResultSuccess() ],
3911 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
3912 tdTestResultFailure() ],
3913 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep,
3914 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3915 # Copy with a different destination name just for the heck of it:
3916 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'empty2'), fIntoDst = True),
3917 tdTestResultFailure() ],
3918 # Now the same using a directory with files in it:
3919 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultSuccess() ],
3920 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultFailure() ],
3921 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst,
3922 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3923 # Copy the entire test tree:
3924 [ tdTestCopyFromDir(sSrc = self.oTestFiles.oTreeDir.sPath, sDst = sScratchDstDir3Hst), tdTestResultSuccess() ],
3925 ]);
3926
3927 #
3928 # Execute the tests.
3929 #
3930 fRc = True;
3931 for (i, tTest) in enumerate(atTests):
3932 oCurTest = tTest[0]
3933 oCurRes = tTest[1] # type: tdTestResult
3934 if isinstance(oCurTest, tdTestCopyFrom):
3935 reporter.log('Testing #%d, %s: sSrc="%s", sDst="%s", fFlags="%s" ...'
3936 % (i, "directory" if isinstance(oCurTest, tdTestCopyFromDir) else "file",
3937 oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags,));
3938 else:
3939 reporter.log('Testing #%d, tdTestRemoveHostDir "%s" ...' % (i, oCurTest.sDir,));
3940 if isinstance(oCurTest, tdTestCopyFromDir) and self.oTstDrv.fpApiVer < 6.0:
3941 reporter.log('Skipping directoryCopyFromGuest test, not implemented in %s' % (self.oTstDrv.fpApiVer,));
3942 continue;
3943
3944 if isinstance(oCurTest, tdTestRemoveHostDir):
3945 fRc = oCurTest.execute(self.oTstDrv, oSession, oTxsSession, oTestVm, 'testing #%d' % (i,));
3946 else:
3947 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3948 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyFrom: Test #%d' % (i,), fIsError = True);
3949 if fRc2 is not True:
3950 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3951 break;
3952
3953 if isinstance(oCurTest, tdTestCopyFromFile):
3954 fRc2 = self.gctrlCopyFileFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
3955 else:
3956 fRc2 = self.gctrlCopyDirFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
3957
3958 if fRc2 != oCurRes.fRc:
3959 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3960 fRc2 = False;
3961
3962 fRc = oCurTest.closeSession(fIsError = True) and fRc;
3963
3964 return (fRc, oTxsSession);
3965
3966 def testGuestCtrlUpdateAdditions(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3967 """
3968 Tests updating the Guest Additions inside the guest.
3969
3970 """
3971
3972 # Skip test for updating Guest Additions if we run on a too old (Windows) guest.
3973 ##
3974 ## @todo make it work everywhere!
3975 ##
3976 if oTestVm.sKind in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
3977 reporter.log("Skipping updating GAs on old windows vm (sKind=%s)" % (oTestVm.sKind,));
3978 return (None, oTxsSession);
3979 if oTestVm.isOS2():
3980 reporter.log("Skipping updating GAs on OS/2 guest");
3981 return (None, oTxsSession);
3982
3983 # Some stupid trickery to guess the location of the iso.
3984 sVBoxValidationKitISO = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxValidationKit.iso'));
3985 if not os.path.isfile(sVBoxValidationKitISO):
3986 sVBoxValidationKitISO = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxTestSuite.iso'));
3987 if not os.path.isfile(sVBoxValidationKitISO):
3988 sCur = os.getcwd();
3989 for i in xrange(0, 10):
3990 sVBoxValidationKitISO = os.path.join(sCur, 'validationkit/VBoxValidationKit.iso');
3991 if os.path.isfile(sVBoxValidationKitISO):
3992 break;
3993 sVBoxValidationKitISO = os.path.join(sCur, 'testsuite/VBoxTestSuite.iso');
3994 if os.path.isfile(sVBoxValidationKitISO):
3995 break;
3996 sCur = os.path.abspath(os.path.join(sCur, '..'));
3997 if i is None: pass; # shut up pychecker/pylint.
3998 if os.path.isfile(sVBoxValidationKitISO):
3999 reporter.log('Validation Kit .ISO found at: %s' % (sVBoxValidationKitISO,));
4000 else:
4001 reporter.log('Warning: Validation Kit .ISO not found -- some tests might fail');
4002
4003 sScratch = os.path.join(self.oTstDrv.sScratchPath, "testGctrlUpdateAdditions");
4004 try:
4005 os.makedirs(sScratch);
4006 except OSError as e:
4007 if e.errno != errno.EEXIST:
4008 reporter.error('Failed: Unable to create scratch directory \"%s\"' % (sScratch,));
4009 return (False, oTxsSession);
4010 reporter.log('Scratch path is: %s' % (sScratch,));
4011
4012 atTests = [];
4013 if oTestVm.isWindows():
4014 atTests.extend([
4015 # Source is missing.
4016 [ tdTestUpdateAdditions(sSrc = ''), tdTestResultFailure() ],
4017
4018 # Wrong fFlags.
4019 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
4020 fFlags = [ 1234 ]), tdTestResultFailure() ],
4021
4022 # Non-existing .ISO.
4023 [ tdTestUpdateAdditions(sSrc = "non-existing.iso"), tdTestResultFailure() ],
4024
4025 # Wrong .ISO.
4026 [ tdTestUpdateAdditions(sSrc = sVBoxValidationKitISO), tdTestResultFailure() ],
4027
4028 # The real thing.
4029 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso()),
4030 tdTestResultSuccess() ],
4031 # Test the (optional) installer arguments. This will extract the
4032 # installer into our guest's scratch directory.
4033 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
4034 asArgs = [ '/extract', '/D=' + sScratch ]),
4035 tdTestResultSuccess() ]
4036 # Some debg ISO. Only enable locally.
4037 #[ tdTestUpdateAdditions(
4038 # sSrc = "V:\\Downloads\\VBoxGuestAdditions-r80354.iso"),
4039 # tdTestResultSuccess() ]
4040 ]);
4041 else:
4042 reporter.log('No OS-specific tests for non-Windows yet!');
4043
4044 fRc = True;
4045 for (i, aTest) in enumerate(atTests):
4046 oCurTest = aTest[0]; # tdTestExec, use an index, later.
4047 oCurRes = aTest[1]; # tdTestResult
4048 reporter.log('Testing #%d, sSrc="%s", fFlags="%s" ...' % \
4049 (i, oCurTest.sSrc, oCurTest.fFlags));
4050 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4051 fRc, _ = oCurTest.createSession('Test #%d' % (i,));
4052 if fRc is False:
4053 reporter.error('Test #%d failed: Could not create session' % (i,));
4054 break;
4055 try:
4056 oCurProgress = oCurTest.oTest.oGuest.updateGuestAdditions(oCurTest.sSrc, oCurTest.asArgs, oCurTest.fFlags);
4057 if oCurProgress is not None:
4058 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlUpGA");
4059 try:
4060 oProgress.wait();
4061 if not oProgress.isSuccess():
4062 oProgress.logResult(fIgnoreErrors = True);
4063 fRc = False;
4064 except:
4065 reporter.logXcpt('Waiting exception for updating Guest Additions:');
4066 fRc = False;
4067 else:
4068 reporter.error('No progress object returned');
4069 fRc = False;
4070 except:
4071 # Just log, don't assume an error here (will be done in the main loop then).
4072 reporter.logXcpt('Updating Guest Additions exception for sSrc="%s", fFlags="%s":' \
4073 % (oCurTest.sSrc, oCurTest.fFlags));
4074 fRc = False;
4075 oCurTest.closeSession();
4076 if fRc is oCurRes.fRc:
4077 if fRc:
4078 ## @todo Verify if Guest Additions were really updated (build, revision, ...).
4079 pass;
4080 else:
4081 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
4082 fRc = False;
4083 break;
4084
4085 return (fRc, oTxsSession);
4086
4087
4088
4089class tdAddGuestCtrl(vbox.TestDriver): # pylint: disable=too-many-instance-attributes,too-many-public-methods
4090 """
4091 Guest control using VBoxService on the guest.
4092 """
4093
4094 def __init__(self):
4095 vbox.TestDriver.__init__(self);
4096 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
4097 self.asRsrcs = None;
4098 self.fQuick = False; # Don't skip lengthly tests by default.
4099 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
4100
4101 #
4102 # Overridden methods.
4103 #
4104 def showUsage(self):
4105 """
4106 Shows the testdriver usage.
4107 """
4108 rc = vbox.TestDriver.showUsage(self);
4109 reporter.log('');
4110 reporter.log('tdAddGuestCtrl Options:');
4111 reporter.log(' --quick');
4112 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
4113 return rc;
4114
4115 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
4116 """
4117 Parses the testdriver arguments from the command line.
4118 """
4119 if asArgs[iArg] == '--quick':
4120 self.parseOption(['--virt-modes', 'hwvirt'], 0);
4121 self.parseOption(['--cpu-counts', '1'], 0);
4122 self.fQuick = True;
4123 else:
4124 return vbox.TestDriver.parseOption(self, asArgs, iArg);
4125 return iArg + 1;
4126
4127 def actionConfig(self):
4128 if not self.importVBoxApi(): # So we can use the constant below.
4129 return False;
4130
4131 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
4132 sGaIso = self.getGuestAdditionsIso();
4133 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
4134
4135 def actionExecute(self):
4136 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
4137
4138 #
4139 # Test execution helpers.
4140 #
4141 def testOneCfg(self, oVM, oTestVm): # pylint: disable=too-many-statements
4142 """
4143 Runs the specified VM thru the tests.
4144
4145 Returns a success indicator on the general test execution. This is not
4146 the actual test result.
4147 """
4148
4149 self.logVmInfo(oVM);
4150
4151 fRc = True;
4152 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False);
4153 reporter.log("TxsSession: %s" % (oTxsSession,));
4154 if oSession is not None:
4155 self.addTask(oTxsSession);
4156
4157 fManual = False; # Manual override for local testing. (Committed version shall be False.)
4158 if not fManual:
4159 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
4160 else:
4161 fRc, oTxsSession = self.testGuestCtrlManual(oSession, oTxsSession, oTestVm);
4162
4163 # Cleanup.
4164 self.removeTask(oTxsSession);
4165 if not fManual:
4166 self.terminateVmBySession(oSession);
4167 else:
4168 fRc = False;
4169 return fRc;
4170
4171 def gctrlReportError(self, progress):
4172 """
4173 Helper function to report an error of a
4174 given progress object.
4175 """
4176 if progress is None:
4177 reporter.log('No progress object to print error for');
4178 else:
4179 errInfo = progress.errorInfo;
4180 if errInfo:
4181 reporter.log('%s' % (errInfo.text,));
4182 return False;
4183
4184 def gctrlGetRemainingTime(self, msTimeout, msStart):
4185 """
4186 Helper function to return the remaining time (in ms)
4187 based from a timeout value and the start time (both in ms).
4188 """
4189 if msTimeout == 0:
4190 return 0xFFFFFFFE; # Wait forever.
4191 msElapsed = base.timestampMilli() - msStart;
4192 if msElapsed > msTimeout:
4193 return 0; # No time left.
4194 return msTimeout - msElapsed;
4195
4196 def testGuestCtrlManual(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements,unused-argument,unused-variable
4197 """
4198 For manually testing certain bits.
4199 """
4200
4201 reporter.log('Manual testing ...');
4202 fRc = True;
4203
4204 sUser = 'Administrator';
4205 sPassword = 'password';
4206
4207 oGuest = oSession.o.console.guest;
4208 oGuestSession = oGuest.createSession(sUser,
4209 sPassword,
4210 "", "Manual Test");
4211
4212 aWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
4213 _ = oGuestSession.waitForArray(aWaitFor, 30 * 1000);
4214
4215 sCmd = SubTstDrvAddGuestCtrl.getGuestSystemShell(oTestVm);
4216 asArgs = [ sCmd, '/C', 'dir', '/S', 'c:\\windows' ];
4217 aEnv = [];
4218 fFlags = [];
4219
4220 for _ in xrange(100):
4221 oProc = oGuestSession.processCreate(sCmd, asArgs if self.fpApiVer >= 5.0 else asArgs[1:],
4222 aEnv, fFlags, 30 * 1000);
4223
4224 aWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate ];
4225 _ = oProc.waitForArray(aWaitFor, 30 * 1000);
4226
4227 oGuestSession.close();
4228 oGuestSession = None;
4229
4230 time.sleep(5);
4231
4232 oSession.o.console.PowerDown();
4233
4234 return (fRc, oTxsSession);
4235
4236if __name__ == '__main__':
4237 sys.exit(tdAddGuestCtrl().main(sys.argv));
Note: See TracBrowser for help on using the repository browser.

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