VirtualBox

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

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

Validation Kit/tdAddGuestCtrl.py: Fixed quoting issue for Windows guests wrt VBoxService verbose logs.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 249.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-2020 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: 84830 $"
31
32# Standard Python imports.
33import errno
34import os
35import random
36import string
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
63def limitString(sString, cLimit = 32):
64 """
65 Returns a string with ellipsis ("...") when exceeding the specified limit.
66 Useful for toning down logging. By default strings will be shortened at 32 characters.
67 """
68 if not isinstance(sString, str):
69 sString = str(sString);
70 cLen = len(sString);
71 if not cLen:
72 return '';
73 return (sString[:cLimit] + '...[%d more]' % (cLen - cLimit)) if cLen > cLimit else sString;
74
75class GuestStream(bytearray):
76 """
77 Class for handling a guest process input/output stream.
78
79 @todo write stdout/stderr tests.
80 """
81 def appendStream(self, stream, convertTo = '<b'):
82 """
83 Appends and converts a byte sequence to this object;
84 handy for displaying a guest stream.
85 """
86 self.extend(struct.pack(convertTo, stream));
87
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, oCreds = None):
124 self.oGuest = None; ##< IGuest.
125 self.oCreds = oCreds ##< type: tdCtxCreds
126 self.timeoutMS = 30 * 1000; ##< 30s timeout
127 self.oGuestSession = None; ##< IGuestSession reference or None.
128
129 def setEnvironment(self, oSession, oTxsSession, oTestVm):
130 """
131 Sets the test environment required for this test.
132 """
133 _ = oTxsSession;
134
135 try:
136 self.oGuest = oSession.o.console.guest;
137 except:
138 reporter.errorXcpt();
139
140 if self.oCreds is None:
141 self.oCreds = tdCtxCreds();
142 self.oCreds.applyDefaultsIfNotSet(oTestVm);
143
144 return True;
145
146 def uploadLogData(self, oTstDrv, aData, sFileName, sDesc):
147 """
148 Uploads (binary) data to a log file for manual (later) inspection.
149 """
150 reporter.log('Creating + uploading log data file "%s"' % sFileName);
151 sHstFileName = os.path.join(oTstDrv.sScratchPath, sFileName);
152 try:
153 oCurTestFile = open(sHstFileName, "wb");
154 oCurTestFile.write(aData);
155 oCurTestFile.close();
156 except:
157 return reporter.error('Unable to create temporary file for "%s"' % (sDesc,));
158 return reporter.addLogFile(sHstFileName, 'misc/other', sDesc);
159
160 def createSession(self, sName, fIsError = True):
161 """
162 Creates (opens) a guest session.
163 Returns (True, IGuestSession) on success or (False, None) on failure.
164 """
165 if self.oGuestSession is None:
166 if sName is None:
167 sName = "<untitled>";
168
169 reporter.log('Creating session "%s" ...' % (sName,));
170 try:
171 self.oGuestSession = self.oGuest.createSession(self.oCreds.sUser,
172 self.oCreds.sPassword,
173 self.oCreds.sDomain,
174 sName);
175 except:
176 # Just log, don't assume an error here (will be done in the main loop then).
177 reporter.maybeErrXcpt(fIsError, 'Creating a guest session "%s" failed; sUser="%s", pw="%s", sDomain="%s":'
178 % (sName, self.oCreds.sUser, self.oCreds.sPassword, self.oCreds.sDomain));
179 return (False, None);
180
181 reporter.log('Waiting for session "%s" to start within %dms...' % (sName, self.timeoutMS));
182 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
183 try:
184 waitResult = self.oGuestSession.waitForArray(aeWaitFor, self.timeoutMS);
185
186 #
187 # Be nice to Guest Additions < 4.3: They don't support session handling and
188 # therefore return WaitFlagNotSupported.
189 #
190 if waitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
191 # Just log, don't assume an error here (will be done in the main loop then).
192 reporter.maybeErr(fIsError, 'Session did not start successfully, returned wait result: %d' % (waitResult,));
193 return (False, None);
194 reporter.log('Session "%s" successfully started' % (sName,));
195 except:
196 # Just log, don't assume an error here (will be done in the main loop then).
197 reporter.maybeErrXcpt(fIsError, 'Waiting for guest session "%s" (usr=%s;pw=%s;dom=%s) to start failed:'
198 % (sName, self.oCreds.sUser, self.oCreds.sPassword, self.oCreds.sDomain,));
199 return (False, None);
200 else:
201 reporter.log('Warning: Session already set; this is probably not what you want');
202 return (True, self.oGuestSession);
203
204 def setSession(self, oGuestSession):
205 """
206 Sets the current guest session and closes
207 an old one if necessary.
208 """
209 if self.oGuestSession is not None:
210 self.closeSession();
211 self.oGuestSession = oGuestSession;
212 return self.oGuestSession;
213
214 def closeSession(self, fIsError = True):
215 """
216 Closes the guest session.
217 """
218 if self.oGuestSession is not None:
219 try:
220 sName = self.oGuestSession.name;
221 except:
222 return reporter.errorXcpt();
223
224 reporter.log('Closing session "%s" ...' % (sName,));
225 try:
226 self.oGuestSession.close();
227 self.oGuestSession = None;
228 except:
229 # Just log, don't assume an error here (will be done in the main loop then).
230 reporter.maybeErrXcpt(fIsError, 'Closing guest session "%s" failed:' % (sName,));
231 return False;
232 return True;
233
234class tdTestCopyFrom(tdTestGuestCtrlBase):
235 """
236 Test for copying files from the guest to the host.
237 """
238 def __init__(self, sSrc = "", sDst = "", oCreds = None, afFlags = None, oSrc = None):
239 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
240 self.sSrc = sSrc;
241 self.sDst = sDst;
242 self.afFlags = afFlags;
243 self.oSrc = oSrc # type: testfileset.TestFsObj
244 if oSrc and not sSrc:
245 self.sSrc = oSrc.sPath;
246
247class tdTestCopyFromDir(tdTestCopyFrom):
248
249 def __init__(self, sSrc = "", sDst = "", oCreds = None, afFlags = None, oSrc = None, fIntoDst = False):
250 tdTestCopyFrom.__init__(self, sSrc, sDst, oCreds, afFlags, oSrc);
251 self.fIntoDst = fIntoDst; # hint to the verification code that sDst == oSrc, rather than sDst+oSrc.sNAme == oSrc.
252
253class tdTestCopyFromFile(tdTestCopyFrom):
254 pass;
255
256class tdTestRemoveHostDir(object):
257 """
258 Test step that removes a host directory tree.
259 """
260 def __init__(self, sDir):
261 self.sDir = sDir;
262
263 def execute(self, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
264 _ = oTstDrv; _ = oVmSession; _ = oTxsSession; _ = oTestVm; _ = sMsgPrefix;
265 if os.path.exists(self.sDir):
266 if base.wipeDirectory(self.sDir) != 0:
267 return False;
268 try:
269 os.rmdir(self.sDir);
270 except:
271 return reporter.errorXcpt('%s: sDir=%s' % (sMsgPrefix, self.sDir,));
272 return True;
273
274
275
276class tdTestCopyTo(tdTestGuestCtrlBase):
277 """
278 Test for copying files from the host to the guest.
279 """
280 def __init__(self, sSrc = "", sDst = "", oCreds = None, afFlags = None):
281 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
282 self.sSrc = sSrc;
283 self.sDst = sDst;
284 self.afFlags = afFlags;
285
286class tdTestCopyToFile(tdTestCopyTo):
287 pass;
288
289class tdTestCopyToDir(tdTestCopyTo):
290 pass;
291
292class tdTestDirCreate(tdTestGuestCtrlBase):
293 """
294 Test for directoryCreate call.
295 """
296 def __init__(self, sDirectory = "", oCreds = None, fMode = 0, afFlags = None):
297 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
298 self.sDirectory = sDirectory;
299 self.fMode = fMode;
300 self.afFlags = afFlags;
301
302class tdTestDirCreateTemp(tdTestGuestCtrlBase):
303 """
304 Test for the directoryCreateTemp call.
305 """
306 def __init__(self, sDirectory = "", sTemplate = "", oCreds = None, fMode = 0, fSecure = False):
307 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
308 self.sDirectory = sDirectory;
309 self.sTemplate = sTemplate;
310 self.fMode = fMode;
311 self.fSecure = fSecure;
312
313class tdTestDirOpen(tdTestGuestCtrlBase):
314 """
315 Test for the directoryOpen call.
316 """
317 def __init__(self, sDirectory = "", oCreds = None, sFilter = "", afFlags = None):
318 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
319 self.sDirectory = sDirectory;
320 self.sFilter = sFilter;
321 self.afFlags = afFlags or [];
322
323class tdTestDirRead(tdTestDirOpen):
324 """
325 Test for the opening, reading and closing a certain directory.
326 """
327 def __init__(self, sDirectory = "", oCreds = None, sFilter = "", afFlags = None):
328 tdTestDirOpen.__init__(self, sDirectory, oCreds, sFilter, afFlags);
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, afFlags = None, # pylint: disable=too-many-arguments
336 timeoutMS = 5 * 60 * 1000, oCreds = None, fWaitForExit = True):
337 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
338 self.sCmd = sCmd;
339 self.asArgs = asArgs if asArgs is not None else [sCmd,];
340 self.aEnv = aEnv;
341 self.afFlags = afFlags or [];
342 self.timeoutMS = timeoutMS;
343 self.fWaitForExit = fWaitForExit;
344 self.uExitStatus = 0;
345 self.iExitCode = 0;
346 self.cbStdOut = 0;
347 self.cbStdErr = 0;
348 self.sBuf = '';
349
350class tdTestFileExists(tdTestGuestCtrlBase):
351 """
352 Test for the file exists API call (fileExists).
353 """
354 def __init__(self, sFile = "", oCreds = None):
355 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
356 self.sFile = sFile;
357
358class tdTestFileRemove(tdTestGuestCtrlBase):
359 """
360 Test querying guest file information.
361 """
362 def __init__(self, sFile = "", oCreds = None):
363 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
364 self.sFile = sFile;
365
366class tdTestRemoveBase(tdTestGuestCtrlBase):
367 """
368 Removal base.
369 """
370 def __init__(self, sPath, fRcExpect = True, oCreds = None):
371 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
372 self.sPath = sPath;
373 self.fRcExpect = fRcExpect;
374
375 def execute(self, oSubTstDrv):
376 """
377 Executes the test, returns True/False.
378 """
379 _ = oSubTstDrv;
380 return True;
381
382 def checkRemoved(self, sType):
383 """ Check that the object was removed using fObjExists. """
384 try:
385 fExists = self.oGuestSession.fsObjExists(self.sPath, False);
386 except:
387 return reporter.errorXcpt('fsObjExists failed on "%s" after deletion (type: %s)' % (self.sPath, sType));
388 if fExists:
389 return reporter.error('fsObjExists says "%s" still exists after deletion (type: %s)!' % (self.sPath, sType));
390 return True;
391
392class tdTestRemoveFile(tdTestRemoveBase):
393 """
394 Remove a single file.
395 """
396 def __init__(self, sPath, fRcExpect = True, oCreds = None):
397 tdTestRemoveBase.__init__(self, sPath, fRcExpect, oCreds);
398
399 def execute(self, oSubTstDrv):
400 reporter.log2('Deleting file "%s" ...' % (limitString(self.sPath),));
401 try:
402 if oSubTstDrv.oTstDrv.fpApiVer >= 5.0:
403 self.oGuestSession.fsObjRemove(self.sPath);
404 else:
405 self.oGuestSession.fileRemove(self.sPath);
406 except:
407 reporter.maybeErrXcpt(self.fRcExpect, 'Removing "%s" failed' % (self.sPath,));
408 return not self.fRcExpect;
409 if not self.fRcExpect:
410 return reporter.error('Expected removing "%s" to failed, but it succeeded' % (self.sPath,));
411
412 return self.checkRemoved('file');
413
414class tdTestRemoveDir(tdTestRemoveBase):
415 """
416 Remove a single directory if empty.
417 """
418 def __init__(self, sPath, fRcExpect = True, oCreds = None):
419 tdTestRemoveBase.__init__(self, sPath, fRcExpect, oCreds);
420
421 def execute(self, oSubTstDrv):
422 _ = oSubTstDrv;
423 reporter.log2('Deleting directory "%s" ...' % (limitString(self.sPath),));
424 try:
425 self.oGuestSession.directoryRemove(self.sPath);
426 except:
427 reporter.maybeErrXcpt(self.fRcExpect, 'Removing "%s" (as a directory) failed' % (self.sPath,));
428 return not self.fRcExpect;
429 if not self.fRcExpect:
430 return reporter.error('Expected removing "%s" (dir) to failed, but it succeeded' % (self.sPath,));
431
432 return self.checkRemoved('directory');
433
434class tdTestRemoveTree(tdTestRemoveBase):
435 """
436 Recursively remove a directory tree.
437 """
438 def __init__(self, sPath, afFlags = None, fRcExpect = True, fNotExist = False, oCreds = None):
439 tdTestRemoveBase.__init__(self, sPath, fRcExpect, oCreds = None);
440 self.afFlags = afFlags if afFlags is not None else [];
441 self.fNotExist = fNotExist; # Hack for the ContentOnly scenario where the dir does not exist.
442
443 def execute(self, oSubTstDrv):
444 reporter.log2('Deleting tree "%s" ...' % (limitString(self.sPath),));
445 try:
446 oProgress = self.oGuestSession.directoryRemoveRecursive(self.sPath, self.afFlags);
447 except:
448 reporter.maybeErrXcpt(self.fRcExpect, 'Removing directory tree "%s" failed (afFlags=%s)'
449 % (self.sPath, self.afFlags));
450 return not self.fRcExpect;
451
452 oWrappedProgress = vboxwrappers.ProgressWrapper(oProgress, oSubTstDrv.oTstDrv.oVBoxMgr, oSubTstDrv.oTstDrv,
453 "remove-tree: %s" % (self.sPath,));
454 oWrappedProgress.wait();
455 if not oWrappedProgress.isSuccess():
456 oWrappedProgress.logResult(fIgnoreErrors = not self.fRcExpect);
457 return not self.fRcExpect;
458 if not self.fRcExpect:
459 return reporter.error('Expected removing "%s" (tree) to failed, but it succeeded' % (self.sPath,));
460
461 if vboxcon.DirectoryRemoveRecFlag_ContentAndDir not in self.afFlags and not self.fNotExist:
462 # Cannot use directoryExists here as it is buggy.
463 try:
464 if oSubTstDrv.oTstDrv.fpApiVer >= 5.0:
465 oFsObjInfo = self.oGuestSession.fsObjQueryInfo(self.sPath, False);
466 else:
467 oFsObjInfo = self.oGuestSession.fileQueryInfo(self.sPath);
468 eType = oFsObjInfo.type;
469 except:
470 return reporter.errorXcpt('sPath=%s' % (self.sPath,));
471 if eType != vboxcon.FsObjType_Directory:
472 return reporter.error('Found file type %d, expected directory (%d) for %s after rmtree/OnlyContent'
473 % (eType, vboxcon.FsObjType_Directory, self.sPath,));
474 return True;
475
476 return self.checkRemoved('tree');
477
478
479class tdTestFileStat(tdTestGuestCtrlBase):
480 """
481 Test querying guest file information.
482 """
483 def __init__(self, sFile = "", oCreds = None, cbSize = 0, eFileType = 0):
484 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
485 self.sFile = sFile;
486 self.cbSize = cbSize;
487 self.eFileType = eFileType;
488
489class tdTestFileIO(tdTestGuestCtrlBase):
490 """
491 Test for the IGuestFile object.
492 """
493 def __init__(self, sFile = "", oCreds = None):
494 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
495 self.sFile = sFile;
496
497class tdTestFileQuerySize(tdTestGuestCtrlBase):
498 """
499 Test for the file size query API call (fileQuerySize).
500 """
501 def __init__(self, sFile = "", oCreds = None):
502 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
503 self.sFile = sFile;
504
505class tdTestFileOpen(tdTestGuestCtrlBase):
506 """
507 Tests opening a guest files.
508 """
509 def __init__(self, sFile = "", eAccessMode = None, eAction = None, eSharing = None,
510 fCreationMode = 0o660, oCreds = None):
511 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
512 self.sFile = sFile;
513 self.eAccessMode = eAccessMode if eAccessMode is not None else vboxcon.FileAccessMode_ReadOnly;
514 self.eAction = eAction if eAction is not None else vboxcon.FileOpenAction_OpenExisting;
515 self.eSharing = eSharing if eSharing is not None else vboxcon.FileSharingMode_All;
516 self.fCreationMode = fCreationMode;
517 self.afOpenFlags = [];
518 self.oOpenedFile = None;
519
520 def toString(self):
521 """ Get a summary string. """
522 return 'eAccessMode=%s eAction=%s sFile=%s' % (self.eAccessMode, self.eAction, self.sFile);
523
524 def doOpenStep(self, fExpectSuccess):
525 """
526 Does the open step, putting the resulting file in oOpenedFile.
527 """
528 try:
529 self.oOpenedFile = self.oGuestSession.fileOpenEx(self.sFile, self.eAccessMode, self.eAction,
530 self.eSharing, self.fCreationMode, self.afOpenFlags);
531 except:
532 reporter.maybeErrXcpt(fExpectSuccess, 'fileOpenEx(%s, %s, %s, %s, %s, %s)'
533 % (self.sFile, self.eAccessMode, self.eAction, self.eSharing,
534 self.fCreationMode, self.afOpenFlags,));
535 return False;
536 return True;
537
538 def doStepsOnOpenedFile(self, fExpectSuccess, oSubTst):
539 """ Overridden by children to do more testing. """
540 _ = fExpectSuccess; _ = oSubTst;
541 return True;
542
543 def doCloseStep(self):
544 """ Closes the file. """
545 if self.oOpenedFile:
546 try:
547 self.oOpenedFile.close();
548 except:
549 return reporter.errorXcpt('close([%s, %s, %s, %s, %s, %s])'
550 % (self.sFile, self.eAccessMode, self.eAction, self.eSharing,
551 self.fCreationMode, self.afOpenFlags,));
552 self.oOpenedFile = None;
553 return True;
554
555 def doSteps(self, fExpectSuccess, oSubTst):
556 """ Do the tests. """
557 fRc = self.doOpenStep(fExpectSuccess);
558 if fRc is True:
559 fRc = self.doStepsOnOpenedFile(fExpectSuccess, oSubTst);
560 if self.oOpenedFile:
561 fRc = self.doCloseStep() and fRc;
562 return fRc;
563
564
565class tdTestFileOpenCheckSize(tdTestFileOpen):
566 """
567 Opens a file and checks the size.
568 """
569 def __init__(self, sFile = "", eAccessMode = None, eAction = None, eSharing = None,
570 fCreationMode = 0o660, cbOpenExpected = 0, oCreds = None):
571 tdTestFileOpen.__init__(self, sFile, eAccessMode, eAction, eSharing, fCreationMode, oCreds);
572 self.cbOpenExpected = cbOpenExpected;
573
574 def toString(self):
575 return 'cbOpenExpected=%s %s' % (self.cbOpenExpected, tdTestFileOpen.toString(self),);
576
577 def doStepsOnOpenedFile(self, fExpectSuccess, oSubTst):
578 #
579 # Call parent.
580 #
581 fRc = tdTestFileOpen.doStepsOnOpenedFile(self, fExpectSuccess, oSubTst);
582
583 #
584 # Check the size. Requires 6.0 or later (E_NOTIMPL in 5.2).
585 #
586 if oSubTst.oTstDrv.fpApiVer >= 6.0:
587 try:
588 oFsObjInfo = self.oOpenedFile.queryInfo();
589 except:
590 return reporter.errorXcpt('queryInfo([%s, %s, %s, %s, %s, %s])'
591 % (self.sFile, self.eAccessMode, self.eAction, self.eSharing,
592 self.fCreationMode, self.afOpenFlags,));
593 if oFsObjInfo is None:
594 return reporter.error('IGuestFile::queryInfo returned None');
595 try:
596 cbFile = oFsObjInfo.objectSize;
597 except:
598 return reporter.errorXcpt();
599 if cbFile != self.cbOpenExpected:
600 return reporter.error('Wrong file size after open (%d): %s, expected %s (file %s) (#1)'
601 % (self.eAction, cbFile, self.cbOpenExpected, self.sFile));
602
603 try:
604 cbFile = self.oOpenedFile.querySize();
605 except:
606 return reporter.errorXcpt('querySize([%s, %s, %s, %s, %s, %s])'
607 % (self.sFile, self.eAccessMode, self.eAction, self.eSharing,
608 self.fCreationMode, self.afOpenFlags,));
609 if cbFile != self.cbOpenExpected:
610 return reporter.error('Wrong file size after open (%d): %s, expected %s (file %s) (#2)'
611 % (self.eAction, cbFile, self.cbOpenExpected, self.sFile));
612
613 return fRc;
614
615
616class tdTestFileOpenAndWrite(tdTestFileOpen):
617 """
618 Opens the file and writes one or more chunks to it.
619
620 The chunks are a list of tuples(offset, bytes), where offset can be None
621 if no seeking should be performed.
622 """
623 def __init__(self, sFile = "", eAccessMode = None, eAction = None, eSharing = None, # pylint: disable=too-many-arguments
624 fCreationMode = 0o660, atChunks = None, fUseAtApi = False, abContent = None, oCreds = None):
625 tdTestFileOpen.__init__(self, sFile, eAccessMode if eAccessMode is not None else vboxcon.FileAccessMode_WriteOnly,
626 eAction, eSharing, fCreationMode, oCreds);
627 assert atChunks is not None;
628 self.atChunks = atChunks # type: list(tuple(int,bytearray))
629 self.fUseAtApi = fUseAtApi;
630 self.fAppend = ( eAccessMode in (vboxcon.FileAccessMode_AppendOnly, vboxcon.FileAccessMode_AppendRead)
631 or eAction == vboxcon.FileOpenAction_AppendOrCreate);
632 self.abContent = abContent # type: bytearray
633
634 def toString(self):
635 sChunks = ', '.join('%s LB %s' % (tChunk[0], len(tChunk[1]),) for tChunk in self.atChunks);
636 sApi = 'writeAt' if self.fUseAtApi else 'write';
637 return '%s [%s] %s' % (sApi, sChunks, tdTestFileOpen.toString(self),);
638
639 def doStepsOnOpenedFile(self, fExpectSuccess, oSubTst):
640 #
641 # Call parent.
642 #
643 fRc = tdTestFileOpen.doStepsOnOpenedFile(self, fExpectSuccess, oSubTst);
644
645 #
646 # Do the writing.
647 #
648 for offFile, abBuf in self.atChunks:
649 if self.fUseAtApi:
650 #
651 # writeAt:
652 #
653 assert offFile is not None;
654 reporter.log2('writeAt(%s, %s bytes)' % (offFile, len(abBuf),));
655 if self.fAppend:
656 if self.abContent is not None: # Try avoid seek as it updates the cached offset in GuestFileImpl.
657 offExpectAfter = len(self.abContent);
658 else:
659 try:
660 offSave = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_Current);
661 offExpectAfter = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_End);
662 self.oOpenedFile.seek(offSave, vboxcon.FileSeekOrigin_Begin);
663 except:
664 return reporter.errorXcpt();
665 offExpectAfter += len(abBuf);
666 else:
667 offExpectAfter = offFile + len(abBuf);
668
669 try:
670 cbWritten = self.oOpenedFile.writeAt(offFile, abBuf, 30*1000);
671 except:
672 return reporter.errorXcpt('writeAt(%s, %s bytes)' % (offFile, len(abBuf),));
673
674 else:
675 #
676 # write:
677 #
678 if self.fAppend:
679 if self.abContent is not None: # Try avoid seek as it updates the cached offset in GuestFileImpl.
680 offExpectAfter = len(self.abContent);
681 else:
682 try:
683 offSave = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_Current);
684 offExpectAfter = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_End);
685 self.oOpenedFile.seek(offSave, vboxcon.FileSeekOrigin_Begin);
686 except:
687 return reporter.errorXcpt('seek(0,End)');
688 if offFile is not None:
689 try:
690 self.oOpenedFile.seek(offFile, vboxcon.FileSeekOrigin_Begin);
691 except:
692 return reporter.errorXcpt('seek(%s,Begin)' % (offFile,));
693 else:
694 try:
695 offFile = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_Current);
696 except:
697 return reporter.errorXcpt();
698 if not self.fAppend:
699 offExpectAfter = offFile;
700 offExpectAfter += len(abBuf);
701
702 reporter.log2('write(%s bytes @ %s)' % (len(abBuf), offFile,));
703 try:
704 cbWritten = self.oOpenedFile.write(abBuf, 30*1000);
705 except:
706 return reporter.errorXcpt('write(%s bytes @ %s)' % (len(abBuf), offFile));
707
708 #
709 # Check how much was written, ASSUMING nothing we push thru here is too big:
710 #
711 if cbWritten != len(abBuf):
712 fRc = reporter.errorXcpt('Wrote less than expected: %s out of %s, expected all to be written'
713 % (cbWritten, len(abBuf),));
714 if not self.fAppend:
715 offExpectAfter -= len(abBuf) - cbWritten;
716
717 #
718 # Update the file content tracker if we've got one and can:
719 #
720 if self.abContent is not None:
721 if cbWritten < len(abBuf):
722 abBuf = abBuf[:cbWritten];
723
724 #
725 # In append mode, the current file offset shall be disregarded and the
726 # write always goes to the end of the file, regardless of writeAt or write.
727 # Note that RTFileWriteAt only naturally behaves this way on linux and
728 # (probably) windows, so VBoxService makes that behaviour generic across
729 # all OSes.
730 #
731 if self.fAppend:
732 reporter.log2('len(self.abContent)=%s + %s' % (len(self.abContent), cbWritten, ));
733 self.abContent.extend(abBuf);
734 else:
735 if offFile is None:
736 offFile = offExpectAfter - cbWritten;
737 reporter.log2('len(self.abContent)=%s + %s @ %s' % (len(self.abContent), cbWritten, offFile, ));
738 if offFile > len(self.abContent):
739 self.abContent.extend(bytearray(offFile - len(self.abContent)));
740 self.abContent[offFile:offFile + cbWritten] = abBuf;
741 reporter.log2('len(self.abContent)=%s' % (len(self.abContent),));
742
743 #
744 # Check the resulting file offset with IGuestFile::offset.
745 #
746 try:
747 offApi = self.oOpenedFile.offset; # Must be gotten first!
748 offSeek = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_Current);
749 except:
750 fRc = reporter.errorXcpt();
751 else:
752 reporter.log2('offApi=%s offSeek=%s offExpectAfter=%s' % (offApi, offSeek, offExpectAfter,));
753 if offSeek != offExpectAfter:
754 fRc = reporter.error('Seek offset is %s, expected %s after %s bytes write @ %s (offApi=%s)'
755 % (offSeek, offExpectAfter, len(abBuf), offFile, offApi,));
756 if offApi != offExpectAfter:
757 fRc = reporter.error('IGuestFile::offset is %s, expected %s after %s bytes write @ %s (offSeek=%s)'
758 % (offApi, offExpectAfter, len(abBuf), offFile, offSeek,));
759 # for each chunk - end
760 return fRc;
761
762
763class tdTestFileOpenAndCheckContent(tdTestFileOpen):
764 """
765 Opens the file and checks the content using the read API.
766 """
767 def __init__(self, sFile = "", eSharing = None, abContent = None, cbContentExpected = None, oCreds = None):
768 tdTestFileOpen.__init__(self, sFile = sFile, eSharing = eSharing, oCreds = oCreds);
769 self.abContent = abContent # type: bytearray
770 self.cbContentExpected = cbContentExpected;
771
772 def toString(self):
773 return 'check content %s (%s) %s' % (len(self.abContent), self.cbContentExpected, tdTestFileOpen.toString(self),);
774
775 def doStepsOnOpenedFile(self, fExpectSuccess, oSubTst):
776 #
777 # Call parent.
778 #
779 fRc = tdTestFileOpen.doStepsOnOpenedFile(self, fExpectSuccess, oSubTst);
780
781 #
782 # Check the expected content size.
783 #
784 if self.cbContentExpected is not None:
785 if len(self.abContent) != self.cbContentExpected:
786 fRc = reporter.error('Incorrect abContent size: %s, expected %s'
787 % (len(self.abContent), self.cbContentExpected,));
788
789 #
790 # Read the file and compare it with the content.
791 #
792 offFile = 0;
793 while True:
794 try:
795 abChunk = self.oOpenedFile.read(512*1024, 30*1000);
796 except:
797 return reporter.errorXcpt('read(512KB) @ %s' % (offFile,));
798 cbChunk = len(abChunk);
799 if cbChunk == 0:
800 if offFile != len(self.abContent):
801 fRc = reporter.error('Unexpected EOF @ %s, len(abContent)=%s' % (offFile, len(self.abContent),));
802 break;
803 if offFile + cbChunk > len(self.abContent):
804 fRc = reporter.error('File is larger than expected: at least %s bytes, expected %s bytes'
805 % (offFile + cbChunk, len(self.abContent),));
806 elif not utils.areBytesEqual(abChunk, self.abContent[offFile:(offFile + cbChunk)]):
807 fRc = reporter.error('Mismatch in range %s LB %s!' % (offFile, cbChunk,));
808 offFile += cbChunk;
809
810 return fRc;
811
812
813class tdTestSession(tdTestGuestCtrlBase):
814 """
815 Test the guest session handling.
816 """
817 def __init__(self, sUser = None, sPassword = None, sDomain = None, sSessionName = ""):
818 tdTestGuestCtrlBase.__init__(self, oCreds = tdCtxCreds(sUser, sPassword, sDomain));
819 self.sSessionName = sSessionName;
820
821 def getSessionCount(self, oVBoxMgr):
822 """
823 Helper for returning the number of currently
824 opened guest sessions of a VM.
825 """
826 if self.oGuest is None:
827 return 0;
828 try:
829 aoSession = oVBoxMgr.getArray(self.oGuest, 'sessions')
830 except:
831 reporter.errorXcpt('sSessionName: %s' % (self.sSessionName,));
832 return 0;
833 return len(aoSession);
834
835
836class tdTestSessionEx(tdTestGuestCtrlBase):
837 """
838 Test the guest session.
839 """
840 def __init__(self, aoSteps = None, enmUser = None):
841 tdTestGuestCtrlBase.__init__(self);
842 assert enmUser is None; # For later.
843 self.enmUser = enmUser;
844 self.aoSteps = aoSteps if aoSteps is not None else [];
845
846 def execute(self, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
847 """
848 Executes the test.
849 """
850 #
851 # Create a session.
852 #
853 assert self.enmUser is None; # For later.
854 self.oCreds = tdCtxCreds();
855 self.setEnvironment(oVmSession, oTxsSession, oTestVm);
856 reporter.log2('%s: %s steps' % (sMsgPrefix, len(self.aoSteps),));
857 fRc, oCurSession = self.createSession(sMsgPrefix);
858 if fRc is True:
859 #
860 # Execute the tests.
861 #
862 try:
863 fRc = self.executeSteps(oTstDrv, oCurSession, sMsgPrefix);
864 except:
865 fRc = reporter.errorXcpt('%s: Unexpected exception executing test steps' % (sMsgPrefix,));
866
867 #
868 # Close the session.
869 #
870 fRc2 = self.closeSession();
871 if fRc2 is False:
872 fRc = reporter.error('%s: Session could not be closed' % (sMsgPrefix,));
873 else:
874 fRc = reporter.error('%s: Session creation failed' % (sMsgPrefix,));
875 return fRc;
876
877 def executeSteps(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
878 """
879 Executes just the steps.
880 Returns True on success, False on test failure.
881 """
882 fRc = True;
883 for (i, oStep) in enumerate(self.aoSteps):
884 fRc2 = oStep.execute(oTstDrv, oGstCtrlSession, sMsgPrefix + ', step #%d' % i);
885 if fRc2 is True:
886 pass;
887 elif fRc2 is None:
888 reporter.log('%s: skipping remaining %d steps' % (sMsgPrefix, len(self.aoSteps) - i - 1,));
889 break;
890 else:
891 fRc = False;
892 return fRc;
893
894 @staticmethod
895 def executeListTestSessions(aoTests, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
896 """
897 Works thru a list of tdTestSessionEx object.
898 """
899 fRc = True;
900 for (i, oCurTest) in enumerate(aoTests):
901 try:
902 fRc2 = oCurTest.execute(oTstDrv, oVmSession, oTxsSession, oTestVm, '%s / %#d' % (sMsgPrefix, i,));
903 if fRc2 is not True:
904 fRc = False;
905 except:
906 fRc = reporter.errorXcpt('%s: Unexpected exception executing test #%d' % (sMsgPrefix, i ,));
907
908 return (fRc, oTxsSession);
909
910
911class tdSessionStepBase(object):
912 """
913 Base class for the guest control session test steps.
914 """
915
916 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
917 """
918 Executes the test step.
919
920 Returns True on success.
921 Returns False on failure (must be reported as error).
922 Returns None if to skip the remaining steps.
923 """
924 _ = oTstDrv;
925 _ = oGstCtrlSession;
926 return reporter.error('%s: Missing execute implementation: %s' % (sMsgPrefix, self,));
927
928
929class tdStepRequireMinimumApiVer(tdSessionStepBase):
930 """
931 Special test step which will cause executeSteps to skip the remaining step
932 if the VBox API is too old:
933 """
934 def __init__(self, fpMinApiVer):
935 self.fpMinApiVer = fpMinApiVer;
936
937 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
938 """ Returns None if API version is too old, otherwise True. """
939 if oTstDrv.fpApiVer >= self.fpMinApiVer:
940 return True;
941 _ = oGstCtrlSession;
942 _ = sMsgPrefix;
943 return None; # Special return value. Don't use elsewhere.
944
945
946#
947# Scheduling Environment Changes with the Guest Control Session.
948#
949
950class tdStepSessionSetEnv(tdSessionStepBase):
951 """
952 Guest session environment: schedule putenv
953 """
954 def __init__(self, sVar, sValue, hrcExpected = 0):
955 self.sVar = sVar;
956 self.sValue = sValue;
957 self.hrcExpected = hrcExpected;
958
959 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
960 """
961 Executes the step.
962 Returns True on success, False on test failure.
963 """
964 reporter.log2('tdStepSessionSetEnv: sVar=%s sValue=%s hrcExpected=%#x' % (self.sVar, self.sValue, self.hrcExpected,));
965 try:
966 if oTstDrv.fpApiVer >= 5.0:
967 oGstCtrlSession.environmentScheduleSet(self.sVar, self.sValue);
968 else:
969 oGstCtrlSession.environmentSet(self.sVar, self.sValue);
970 except vbox.ComException as oXcpt:
971 # Is this an expected failure?
972 if vbox.ComError.equal(oXcpt, self.hrcExpected):
973 return True;
974 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (setenv %s=%s)'
975 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
976 vbox.ComError.getXcptResult(oXcpt),
977 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
978 self.sVar, self.sValue,));
979 except:
980 return reporter.errorXcpt('%s: Unexpected exception in tdStepSessionSetEnv::execute (%s=%s)'
981 % (sMsgPrefix, self.sVar, self.sValue,));
982
983 # Should we succeed?
984 if self.hrcExpected != 0:
985 return reporter.error('%s: Expected hrcExpected=%#x, got S_OK (putenv %s=%s)'
986 % (sMsgPrefix, self.hrcExpected, self.sVar, self.sValue,));
987 return True;
988
989class tdStepSessionUnsetEnv(tdSessionStepBase):
990 """
991 Guest session environment: schedule unset.
992 """
993 def __init__(self, sVar, hrcExpected = 0):
994 self.sVar = sVar;
995 self.hrcExpected = hrcExpected;
996
997 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
998 """
999 Executes the step.
1000 Returns True on success, False on test failure.
1001 """
1002 reporter.log2('tdStepSessionUnsetEnv: sVar=%s hrcExpected=%#x' % (self.sVar, self.hrcExpected,));
1003 try:
1004 if oTstDrv.fpApiVer >= 5.0:
1005 oGstCtrlSession.environmentScheduleUnset(self.sVar);
1006 else:
1007 oGstCtrlSession.environmentUnset(self.sVar);
1008 except vbox.ComException as oXcpt:
1009 # Is this an expected failure?
1010 if vbox.ComError.equal(oXcpt, self.hrcExpected):
1011 return True;
1012 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (unsetenv %s)'
1013 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
1014 vbox.ComError.getXcptResult(oXcpt),
1015 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
1016 self.sVar,));
1017 except:
1018 return reporter.errorXcpt('%s: Unexpected exception in tdStepSessionUnsetEnv::execute (%s)'
1019 % (sMsgPrefix, self.sVar,));
1020
1021 # Should we succeed?
1022 if self.hrcExpected != 0:
1023 return reporter.error('%s: Expected hrcExpected=%#x, got S_OK (unsetenv %s)'
1024 % (sMsgPrefix, self.hrcExpected, self.sVar,));
1025 return True;
1026
1027class tdStepSessionBulkEnv(tdSessionStepBase):
1028 """
1029 Guest session environment: Bulk environment changes.
1030 """
1031 def __init__(self, asEnv = None, hrcExpected = 0):
1032 self.asEnv = asEnv if asEnv is not None else [];
1033 self.hrcExpected = hrcExpected;
1034
1035 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
1036 """
1037 Executes the step.
1038 Returns True on success, False on test failure.
1039 """
1040 reporter.log2('tdStepSessionBulkEnv: asEnv=%s hrcExpected=%#x' % (self.asEnv, self.hrcExpected,));
1041 try:
1042 if oTstDrv.fpApiVer >= 5.0:
1043 oTstDrv.oVBoxMgr.setArray(oGstCtrlSession, 'environmentChanges', self.asEnv);
1044 else:
1045 oTstDrv.oVBoxMgr.setArray(oGstCtrlSession, 'environment', self.asEnv);
1046 except vbox.ComException as oXcpt:
1047 # Is this an expected failure?
1048 if vbox.ComError.equal(oXcpt, self.hrcExpected):
1049 return True;
1050 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (asEnv=%s)'
1051 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
1052 vbox.ComError.getXcptResult(oXcpt),
1053 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
1054 self.asEnv,));
1055 except:
1056 return reporter.errorXcpt('%s: Unexpected exception writing the environmentChanges property (asEnv=%s).'
1057 % (sMsgPrefix, self.asEnv));
1058 return True;
1059
1060class tdStepSessionClearEnv(tdStepSessionBulkEnv):
1061 """
1062 Guest session environment: clears the scheduled environment changes.
1063 """
1064 def __init__(self):
1065 tdStepSessionBulkEnv.__init__(self);
1066
1067
1068class tdStepSessionCheckEnv(tdSessionStepBase):
1069 """
1070 Check the currently scheduled environment changes of a guest control session.
1071 """
1072 def __init__(self, asEnv = None):
1073 self.asEnv = asEnv if asEnv is not None else [];
1074
1075 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
1076 """
1077 Executes the step.
1078 Returns True on success, False on test failure.
1079 """
1080 reporter.log2('tdStepSessionCheckEnv: asEnv=%s' % (self.asEnv,));
1081
1082 #
1083 # Get the environment change list.
1084 #
1085 try:
1086 if oTstDrv.fpApiVer >= 5.0:
1087 asCurEnv = oTstDrv.oVBoxMgr.getArray(oGstCtrlSession, 'environmentChanges');
1088 else:
1089 asCurEnv = oTstDrv.oVBoxMgr.getArray(oGstCtrlSession, 'environment');
1090 except:
1091 return reporter.errorXcpt('%s: Unexpected exception reading the environmentChanges property.' % (sMsgPrefix,));
1092
1093 #
1094 # Compare it with the expected one by trying to remove each expected value
1095 # and the list anything unexpected.
1096 #
1097 fRc = True;
1098 asCopy = list(asCurEnv); # just in case asCurEnv is immutable
1099 for sExpected in self.asEnv:
1100 try:
1101 asCopy.remove(sExpected);
1102 except:
1103 fRc = reporter.error('%s: Expected "%s" to be in the resulting environment' % (sMsgPrefix, sExpected,));
1104 for sUnexpected in asCopy:
1105 fRc = reporter.error('%s: Unexpected "%s" in the resulting environment' % (sMsgPrefix, sUnexpected,));
1106
1107 if fRc is not True:
1108 reporter.log2('%s: Current environment: %s' % (sMsgPrefix, asCurEnv));
1109 return fRc;
1110
1111
1112#
1113# File system object statistics (i.e. stat()).
1114#
1115
1116class tdStepStat(tdSessionStepBase):
1117 """
1118 Stats a file system object.
1119 """
1120 def __init__(self, sPath, hrcExpected = 0, fFound = True, fFollowLinks = True, enmType = None, oTestFsObj = None):
1121 self.sPath = sPath;
1122 self.hrcExpected = hrcExpected;
1123 self.fFound = fFound;
1124 self.fFollowLinks = fFollowLinks;
1125 self.enmType = enmType if enmType is not None else vboxcon.FsObjType_File;
1126 self.cbExactSize = None;
1127 self.cbMinSize = None;
1128 self.oTestFsObj = oTestFsObj # type: testfileset.TestFsObj
1129
1130 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
1131 """
1132 Execute the test step.
1133 """
1134 reporter.log2('tdStepStat: sPath=%s enmType=%s hrcExpected=%s fFound=%s fFollowLinks=%s'
1135 % (limitString(self.sPath), self.enmType, self.hrcExpected, self.fFound, self.fFollowLinks,));
1136
1137 # Don't execute non-file tests on older VBox version.
1138 if oTstDrv.fpApiVer >= 5.0 or self.enmType == vboxcon.FsObjType_File or not self.fFound:
1139 #
1140 # Call the API.
1141 #
1142 try:
1143 if oTstDrv.fpApiVer >= 5.0:
1144 oFsInfo = oGstCtrlSession.fsObjQueryInfo(self.sPath, self.fFollowLinks);
1145 else:
1146 oFsInfo = oGstCtrlSession.fileQueryInfo(self.sPath);
1147 except vbox.ComException as oXcpt:
1148 ## @todo: The error reporting in the API just plain sucks! Most of the errors are
1149 ## VBOX_E_IPRT_ERROR and there seems to be no way to distinguish between
1150 ## non-existing files/path and a lot of other errors. Fix API and test!
1151 if not self.fFound:
1152 return True;
1153 if vbox.ComError.equal(oXcpt, self.hrcExpected): # Is this an expected failure?
1154 return True;
1155 return reporter.errorXcpt('%s: Unexpected exception for exiting path "%s" (enmType=%s, hrcExpected=%s):'
1156 % (sMsgPrefix, self.sPath, self.enmType, self.hrcExpected,));
1157 except:
1158 return reporter.errorXcpt('%s: Unexpected exception in tdStepStat::execute (%s)'
1159 % (sMsgPrefix, self.sPath,));
1160 if oFsInfo is None:
1161 return reporter.error('%s: "%s" got None instead of IFsObjInfo instance!' % (sMsgPrefix, self.sPath,));
1162
1163 #
1164 # Check type expectations.
1165 #
1166 try:
1167 enmType = oFsInfo.type;
1168 except:
1169 return reporter.errorXcpt('%s: Unexpected exception in reading "IFsObjInfo::type"' % (sMsgPrefix,));
1170 if enmType != self.enmType:
1171 return reporter.error('%s: "%s" has type %s, expected %s'
1172 % (sMsgPrefix, self.sPath, enmType, self.enmType));
1173
1174 #
1175 # Check size expectations.
1176 # Note! This is unicode string here on windows, for some reason.
1177 # long long mapping perhaps?
1178 #
1179 try:
1180 cbObject = long(oFsInfo.objectSize);
1181 except:
1182 return reporter.errorXcpt('%s: Unexpected exception in reading "IFsObjInfo::objectSize"'
1183 % (sMsgPrefix,));
1184 if self.cbExactSize is not None \
1185 and cbObject != self.cbExactSize:
1186 return reporter.error('%s: "%s" has size %s bytes, expected %s bytes'
1187 % (sMsgPrefix, self.sPath, cbObject, self.cbExactSize));
1188 if self.cbMinSize is not None \
1189 and cbObject < self.cbMinSize:
1190 return reporter.error('%s: "%s" has size %s bytes, expected as least %s bytes'
1191 % (sMsgPrefix, self.sPath, cbObject, self.cbMinSize));
1192 return True;
1193
1194class tdStepStatDir(tdStepStat):
1195 """ Checks for an existing directory. """
1196 def __init__(self, sDirPath, oTestDir = None):
1197 tdStepStat.__init__(self, sPath = sDirPath, enmType = vboxcon.FsObjType_Directory, oTestFsObj = oTestDir);
1198
1199class tdStepStatDirEx(tdStepStatDir):
1200 """ Checks for an existing directory given a TestDir object. """
1201 def __init__(self, oTestDir): # type: (testfileset.TestDir)
1202 tdStepStatDir.__init__(self, oTestDir.sPath, oTestDir);
1203
1204class tdStepStatFile(tdStepStat):
1205 """ Checks for an existing file """
1206 def __init__(self, sFilePath = None, oTestFile = None):
1207 tdStepStat.__init__(self, sPath = sFilePath, enmType = vboxcon.FsObjType_File, oTestFsObj = oTestFile);
1208
1209class tdStepStatFileEx(tdStepStatFile):
1210 """ Checks for an existing file given a TestFile object. """
1211 def __init__(self, oTestFile): # type: (testfileset.TestFile)
1212 tdStepStatFile.__init__(self, oTestFile.sPath, oTestFile);
1213
1214class tdStepStatFileSize(tdStepStat):
1215 """ Checks for an existing file of a given expected size.. """
1216 def __init__(self, sFilePath, cbExactSize = 0):
1217 tdStepStat.__init__(self, sPath = sFilePath, enmType = vboxcon.FsObjType_File);
1218 self.cbExactSize = cbExactSize;
1219
1220class tdStepStatFileNotFound(tdStepStat):
1221 """ Checks for an existing directory. """
1222 def __init__(self, sPath):
1223 tdStepStat.__init__(self, sPath = sPath, fFound = False);
1224
1225class tdStepStatPathNotFound(tdStepStat):
1226 """ Checks for an existing directory. """
1227 def __init__(self, sPath):
1228 tdStepStat.__init__(self, sPath = sPath, fFound = False);
1229
1230
1231#
1232#
1233#
1234
1235class tdTestSessionFileRefs(tdTestGuestCtrlBase):
1236 """
1237 Tests session file (IGuestFile) reference counting.
1238 """
1239 def __init__(self, cRefs = 0):
1240 tdTestGuestCtrlBase.__init__(self);
1241 self.cRefs = cRefs;
1242
1243class tdTestSessionDirRefs(tdTestGuestCtrlBase):
1244 """
1245 Tests session directory (IGuestDirectory) reference counting.
1246 """
1247 def __init__(self, cRefs = 0):
1248 tdTestGuestCtrlBase.__init__(self);
1249 self.cRefs = cRefs;
1250
1251class tdTestSessionProcRefs(tdTestGuestCtrlBase):
1252 """
1253 Tests session process (IGuestProcess) reference counting.
1254 """
1255 def __init__(self, cRefs = 0):
1256 tdTestGuestCtrlBase.__init__(self);
1257 self.cRefs = cRefs;
1258
1259class tdTestUpdateAdditions(tdTestGuestCtrlBase):
1260 """
1261 Test updating the Guest Additions inside the guest.
1262 """
1263 def __init__(self, sSrc = "", asArgs = None, afFlags = None, oCreds = None):
1264 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
1265 self.sSrc = sSrc;
1266 self.asArgs = asArgs;
1267 self.afFlags = afFlags;
1268
1269class tdTestResult(object):
1270 """
1271 Base class for test results.
1272 """
1273 def __init__(self, fRc = False):
1274 ## The overall test result.
1275 self.fRc = fRc;
1276
1277class tdTestResultFailure(tdTestResult):
1278 """
1279 Base class for test results.
1280 """
1281 def __init__(self):
1282 tdTestResult.__init__(self, fRc = False);
1283
1284class tdTestResultSuccess(tdTestResult):
1285 """
1286 Base class for test results.
1287 """
1288 def __init__(self):
1289 tdTestResult.__init__(self, fRc = True);
1290
1291class tdTestResultDirRead(tdTestResult):
1292 """
1293 Test result for reading guest directories.
1294 """
1295 def __init__(self, fRc = False, cFiles = 0, cDirs = 0, cOthers = None):
1296 tdTestResult.__init__(self, fRc = fRc);
1297 self.cFiles = cFiles;
1298 self.cDirs = cDirs;
1299 self.cOthers = cOthers;
1300
1301class tdTestResultExec(tdTestResult):
1302 """
1303 Holds a guest process execution test result,
1304 including the exit code, status + afFlags.
1305 """
1306 def __init__(self, fRc = False, uExitStatus = 500, iExitCode = 0, sBuf = None, cbBuf = 0, cbStdOut = None, cbStdErr = None):
1307 tdTestResult.__init__(self);
1308 ## The overall test result.
1309 self.fRc = fRc;
1310 ## Process exit stuff.
1311 self.uExitStatus = uExitStatus;
1312 self.iExitCode = iExitCode;
1313 ## Desired buffer length returned back from stdout/stderr.
1314 self.cbBuf = cbBuf;
1315 ## Desired buffer result from stdout/stderr. Use with caution!
1316 self.sBuf = sBuf;
1317 self.cbStdOut = cbStdOut;
1318 self.cbStdErr = cbStdErr;
1319
1320class tdTestResultFileStat(tdTestResult):
1321 """
1322 Test result for stat'ing guest files.
1323 """
1324 def __init__(self, fRc = False,
1325 cbSize = 0, eFileType = 0):
1326 tdTestResult.__init__(self, fRc = fRc);
1327 self.cbSize = cbSize;
1328 self.eFileType = eFileType;
1329 ## @todo Add more information.
1330
1331class tdTestResultFileReadWrite(tdTestResult):
1332 """
1333 Test result for reading + writing guest directories.
1334 """
1335 def __init__(self, fRc = False,
1336 cbProcessed = 0, offFile = 0, abBuf = None):
1337 tdTestResult.__init__(self, fRc = fRc);
1338 self.cbProcessed = cbProcessed;
1339 self.offFile = offFile;
1340 self.abBuf = abBuf;
1341
1342class tdTestResultSession(tdTestResult):
1343 """
1344 Test result for guest session counts.
1345 """
1346 def __init__(self, fRc = False, cNumSessions = 0):
1347 tdTestResult.__init__(self, fRc = fRc);
1348 self.cNumSessions = cNumSessions;
1349
1350class tdDebugSettings(object):
1351 """
1352 Contains local test debug settings.
1353 """
1354 def __init__(self, sImgPath = None):
1355 self.sImgPath = sImgPath;
1356 self.sGstVBoxServiceLogPath = '';
1357 self.fNoExit = False;
1358
1359class SubTstDrvAddGuestCtrl(base.SubTestDriverBase):
1360 """
1361 Sub-test driver for executing guest control (VBoxService, IGuest) tests.
1362 """
1363
1364 def __init__(self, oTstDrv):
1365 base.SubTestDriverBase.__init__(self, oTstDrv, 'add-guest-ctrl', 'Guest Control');
1366
1367 ## @todo base.TestBase.
1368 self.asTestsDef = [
1369 'debug',
1370 'session_basic', 'session_env', 'session_file_ref', 'session_dir_ref', 'session_proc_ref', 'session_reboot',
1371 'exec_basic', 'exec_timeout',
1372 'dir_create', 'dir_create_temp', 'dir_read',
1373 'file_open', 'file_remove', 'file_stat', 'file_read', 'file_write',
1374 'copy_to', 'copy_from',
1375 'update_additions'
1376 ];
1377 self.asTests = self.asTestsDef;
1378 self.fSkipKnownBugs = False;
1379 self.oTestFiles = None # type: vboxtestfileset.TestFileSet
1380 self.oDebug = tdDebugSettings();
1381
1382 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
1383 if asArgs[iArg] == '--add-guest-ctrl-tests':
1384 iArg += 1;
1385 iNext = self.oTstDrv.requireMoreArgs(1, asArgs, iArg);
1386 if asArgs[iArg] == 'all': # Nice for debugging scripts.
1387 self.asTests = self.asTestsDef;
1388 else:
1389 self.asTests = asArgs[iArg].split(':');
1390 for s in self.asTests:
1391 if s not in self.asTestsDef:
1392 raise base.InvalidOption('The "--add-guest-ctrl-tests" value "%s" is not valid; valid values are: %s'
1393 % (s, ' '.join(self.asTestsDef)));
1394 return iNext;
1395 if asArgs[iArg] == '--add-guest-ctrl-skip-known-bugs':
1396 self.fSkipKnownBugs = True;
1397 return iArg + 1;
1398 if asArgs[iArg] == '--no-add-guest-ctrl-skip-known-bugs':
1399 self.fSkipKnownBugs = False;
1400 return iArg + 1;
1401 if asArgs[iArg] == '--add-guest-ctrl-debug-img':
1402 iArg += 1;
1403 iNext = self.oTstDrv.requireMoreArgs(1, asArgs, iArg);
1404 self.oDebug.sImgPath = asArgs[iArg];
1405 return iNext;
1406 if asArgs[iArg] == '--add-guest-ctrl-debug-no-exit':
1407 self.oDebug.fNoExit = True;
1408 return iArg + 1;
1409 return iArg;
1410
1411 def showUsage(self):
1412 base.SubTestDriverBase.showUsage(self);
1413 reporter.log(' --add-guest-ctrl-tests <s1[:s2[:]]>');
1414 reporter.log(' Default: %s (all)' % (':'.join(self.asTestsDef)));
1415 reporter.log(' --add-guest-ctrl-skip-known-bugs');
1416 reporter.log(' Skips known bugs. Default: --no-add-guest-ctrl-skip-known-bugs');
1417 reporter.log('Debugging:');
1418 reporter.log(' --add-guest-ctrl-debug-img');
1419 reporter.log(' Sets VBoxService image to deploy for debugging');
1420 reporter.log(' --add-guest-ctrl-debug-no-exit');
1421 reporter.log(' Does not tear down and exit the test driver after running the tests');
1422 return True;
1423
1424 def testIt(self, oTestVm, oSession, oTxsSession):
1425 """
1426 Executes the test.
1427
1428 Returns fRc, oTxsSession. The latter may have changed.
1429 """
1430 reporter.log("Active tests: %s" % (self.asTests,));
1431
1432 # The tests. Must-succeed tests should be first.
1433 atTests = [
1434 ( True, self.prepareGuestForDebugging, None, 'Manual Debugging',),
1435 ( True, self.prepareGuestForTesting, None, 'Preparations',),
1436 ( True, self.testGuestCtrlSession, 'session_basic', 'Session Basics',),
1437 ( True, self.testGuestCtrlExec, 'exec_basic', 'Execution',),
1438 ( False, self.testGuestCtrlExecTimeout, 'exec_timeout', 'Execution Timeouts',),
1439 ( False, self.testGuestCtrlSessionEnvironment, 'session_env', 'Session Environment',),
1440 ( False, self.testGuestCtrlSessionFileRefs, 'session_file_ref', 'Session File References',),
1441 #( False, self.testGuestCtrlSessionDirRefs, 'session_dir_ref', 'Session Directory References',),
1442 ( False, self.testGuestCtrlSessionProcRefs, 'session_proc_ref', 'Session Process References',),
1443 ( False, self.testGuestCtrlDirCreate, 'dir_create', 'Creating directories',),
1444 ( False, self.testGuestCtrlDirCreateTemp, 'dir_create_temp', 'Creating temporary directories',),
1445 ( False, self.testGuestCtrlDirRead, 'dir_read', 'Reading directories',),
1446 ( False, self.testGuestCtrlCopyTo, 'copy_to', 'Copy to guest',),
1447 ( False, self.testGuestCtrlCopyFrom, 'copy_from', 'Copy from guest',),
1448 ( False, self.testGuestCtrlFileStat, 'file_stat', 'Querying file information (stat)',),
1449 ( False, self.testGuestCtrlFileOpen, 'file_open', 'File open',),
1450 ( False, self.testGuestCtrlFileRead, 'file_read', 'File read',),
1451 ( False, self.testGuestCtrlFileWrite, 'file_write', 'File write',),
1452 ( False, self.testGuestCtrlFileRemove, 'file_remove', 'Removing files',), # Destroys prepped files.
1453 ( False, self.testGuestCtrlSessionReboot, 'session_reboot', 'Session w/ Guest Reboot',), # May zap /tmp.
1454 ( False, self.testGuestCtrlUpdateAdditions, 'update_additions', 'Updating Guest Additions',),
1455 ];
1456
1457 fRc = True;
1458 for fMustSucceed, fnHandler, sShortNm, sTestNm in atTests:
1459 reporter.testStart(sTestNm);
1460
1461 if sShortNm is None or sShortNm in self.asTests:
1462 # Returns (fRc, oTxsSession, oSession) - but only the first one is mandatory.
1463 aoResult = fnHandler(oSession, oTxsSession, oTestVm);
1464 if aoResult is None or isinstance(aoResult, bool):
1465 fRcTest = aoResult;
1466 else:
1467 fRcTest = aoResult[0];
1468 if len(aoResult) > 1:
1469 oTxsSession = aoResult[1];
1470 if len(aoResult) > 2:
1471 oSession = aoResult[2];
1472 assert len(aoResult) == 3;
1473 else:
1474 fRcTest = None;
1475
1476 if fRcTest is False and reporter.testErrorCount() == 0:
1477 fRcTest = reporter.error('Buggy test! Returned False w/o logging the error!');
1478 if reporter.testDone(fRcTest is None)[1] != 0:
1479 fRcTest = False;
1480 fRc = False;
1481
1482 # Stop execution if this is a must-succeed test and it failed.
1483 if fRcTest is False and fMustSucceed is True:
1484 reporter.log('Skipping any remaining tests since the previous one failed.');
1485 break;
1486
1487 # Upload VBoxService logs on failure.
1488 if reporter.testErrorCount() > 0 \
1489 and self.oDebug.sGstVBoxServiceLogPath:
1490 sVBoxServiceLogsTarGz = 'ga-vboxservice-logs-%s.tar.gz' % oTestVm.sVmName;
1491 sGstVBoxServiceLogsTarGz = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), sVBoxServiceLogsTarGz);
1492 if self.oTstDrv.txsPackFile(oSession, oTxsSession, \
1493 sGstVBoxServiceLogsTarGz, self.oDebug.sGstVBoxServiceLogPath, fIgnoreErrors = True):
1494 self.oTstDrv.txsDownloadFiles(oSession, oTxsSession, [ (sGstVBoxServiceLogsTarGz, sVBoxServiceLogsTarGz) ], \
1495 fIgnoreErrors = True);
1496
1497 return (fRc, oTxsSession);
1498
1499 def prepareGuestForDebugging(self, oSession, oTxsSession, oTestVm): # pylint: disable=unused-argument
1500 """
1501 Prepares a guest for (manual) debugging.
1502
1503 This involves copying over and invoking a the locally built VBoxService binary.
1504 """
1505
1506 if self.oDebug.sImgPath is None: # If no debugging enabled, bail out.
1507 reporter.log('Skipping debugging');
1508 return True
1509
1510 reporter.log('Preparing for debugging ...');
1511
1512 try:
1513
1514 self.vboxServiceControl(oTxsSession, oTestVm, fStart = False);
1515
1516 if oTestVm.isLinux():
1517 reporter.log('Uploading %s ...' % self.oDebug.sImgPath);
1518 sFileVBoxServiceHst = self.oDebug.sImgPath;
1519 sFileVBoxServiceGst = "/tmp/VBoxService-txs";
1520 oTxsSession.syncUploadFile(sFileVBoxServiceHst, sFileVBoxServiceGst);
1521 oTxsSession.syncChMod(sFileVBoxServiceGst, 0o755);
1522 reporter.log('Executing VBoxService (in background)...');
1523 oTxsSession.syncExec(sFileVBoxServiceGst, (sFileVBoxServiceGst, "-vvvv", "--only-control", \
1524 "--logfile", "/tmp/VBoxService-txs.log") );
1525 elif oTestVm.isWindows():
1526 reporter.log('Uploading %s ...' % self.oDebug.sImgPath);
1527 sFileVBoxServiceHst = self.oDebug.sImgPath;
1528 sFileVBoxServiceGst = os.path.join(self.oTstDrv.getGuestSystemDir(oTestVm), 'VBoxService.exe');
1529 oTxsSession.syncUploadFile(sFileVBoxServiceHst, sFileVBoxServiceGst);
1530 sPathSC = os.path.join(self.oTstDrv.getGuestSystemDir(oTestVm), 'sc.exe');
1531 oTxsSession.syncExec(sPathSC, (sPathSC, "stop", "VBoxService") );
1532 time.sleep(5);
1533 oTxsSession.syncExec(sPathSC, (sPathSC, "start", "VBoxService") );
1534
1535 else: ## @todo Implement others.
1536 reporter.log('Debugging not available on this guest OS yet, skipping ...');
1537
1538 self.vboxServiceControl(oTxsSession, oTestVm, fStart = True);
1539
1540 except:
1541 return reporter.errorXcpt('Unable to prepare for debugging');
1542
1543 return True;
1544
1545 #
1546 # VBoxService handling.
1547 #
1548 def vboxServiceControl(self, oTxsSession, oTestVm, fStart):
1549 """
1550 Controls VBoxService on the guest by starting or stopping the service.
1551 Returns success indicator.
1552 """
1553
1554 fRc = True;
1555
1556 if oTestVm.isWindows():
1557 sPathSC = os.path.join(self.oTstDrv.getGuestSystemDir(oTestVm), 'sc.exe');
1558 if fStart is True:
1559 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Starting VBoxService with verbose logging', 30 * 1000, \
1560 sPathSC, (sPathSC, 'start', 'VBoxService'));
1561 else:
1562 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Stopping VBoxService', 30 * 1000, \
1563 sPathSC, (sPathSC, 'stop', 'VBoxService'));
1564 else:
1565 reporter.log('Controlling VBoxService not supported for this guest yet');
1566
1567 return fRc;
1568
1569 def waitForGuestFacility(self, oSession, eFacilityType, sDesc,
1570 eFacilityStatus, cMsTimeout = 30 * 1000):
1571 """
1572 Waits for a guest facility to enter a certain status.
1573 By default the "Active" status is being used.
1574
1575 Returns success status.
1576 """
1577
1578 reporter.log('Waiting for Guest Additions facility "%s" to change to status %s (%dms timeout)...'
1579 % (sDesc, str(eFacilityStatus), cMsTimeout));
1580
1581 fRc = False;
1582
1583 eStatusOld = None;
1584 tsStart = base.timestampMilli();
1585 while base.timestampMilli() - tsStart < cMsTimeout:
1586 try:
1587 eStatus, _ = oSession.o.console.guest.getFacilityStatus(eFacilityType);
1588 reporter.log('Current status is %s' % (str(eStatus)));
1589 if eStatusOld is None:
1590 eStatusOld = eStatus;
1591 except:
1592 reporter.errorXcpt('Getting facility status failed');
1593 break;
1594 if eStatus != eStatusOld:
1595 reporter.log('Status changed to %s' % (str(eStatus)));
1596 eStatusOld = eStatus;
1597 if eStatus == eFacilityStatus:
1598 fRc = True;
1599 break;
1600 self.oTstDrv.sleep(5); # Do some busy waiting.
1601
1602 if not fRc:
1603 reporter.error('Waiting for Guest Additions facility "%s" timed out' % (sDesc));
1604 else:
1605 reporter.log('Guest Additions facility "%s" reached requested status %s after %dms'
1606 % (sDesc, str(eFacilityStatus), base.timestampMilli() - tsStart));
1607
1608 return fRc;
1609
1610 #
1611 # Guest test files.
1612 #
1613
1614 def prepareGuestForTesting(self, oSession, oTxsSession, oTestVm):
1615 """
1616 Prepares the VM for testing, uploading a bunch of files and stuff via TXS.
1617 Returns success indicator.
1618 """
1619 _ = oSession;
1620
1621 #
1622 # Wait for VBoxService to come up.
1623 #
1624 reporter.testStart('Waiting for VBoxService to get started');
1625 fRc = self.waitForGuestFacility(oSession, vboxcon.AdditionsFacilityType_VBoxService, "VBoxService",
1626 vboxcon.AdditionsFacilityStatus_Active);
1627 reporter.testDone();
1628 if not fRc:
1629 return (False, oTxsSession);
1630
1631 #
1632 # Make sure the temporary directory exists.
1633 #
1634 for sDir in [self.oTstDrv.getGuestTempDir(oTestVm), ]:
1635 if oTxsSession.syncMkDirPath(sDir, 0o777) is not True:
1636 return reporter.error('Failed to create directory "%s"!' % (sDir,));
1637
1638 #
1639 # Enable VBoxService verbose logging.
1640 #
1641 self.oDebug.sGstVBoxServiceLogPath = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), "VBoxService");
1642 if oTxsSession.syncMkDirPath(self.oDebug.sGstVBoxServiceLogPath, 0o777) is not True:
1643 return reporter.error('Failed to create directory "%s"!' % (self.oDebug.sGstVBoxServiceLogPath,));
1644 sPathLogFile = oTestVm.pathJoin(self.oDebug.sGstVBoxServiceLogPath, 'VBoxService.log');
1645
1646 reporter.log('VBoxService logs will be stored in "%s"' % (self.oDebug.sGstVBoxServiceLogPath,));
1647
1648 if oTestVm.isWindows():
1649 sPathRegExe = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'reg.exe');
1650 sPathVBoxServiceExe = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'VBoxService.exe');
1651 sImagePath = '%s -vvvv --logfile %s' % (sPathVBoxServiceExe, sPathLogFile);
1652 self.oTstDrv.txsRunTest(oTxsSession, 'Enabling VBoxService verbose logging (via registry)', 30 * 1000,
1653 sPathRegExe,
1654 (sPathRegExe, 'add',
1655 'HKLM\\SYSTEM\\CurrentControlSet\\Services\\VBoxService',
1656 '/v', 'ImagePath', '/t', 'REG_SZ', '/d', sImagePath, '/f'));
1657
1658 self.vboxServiceControl(oTxsSession, oTestVm, fStart = False);
1659 time.sleep(5);
1660 self.vboxServiceControl(oTxsSession, oTestVm, fStart = True);
1661
1662 else:
1663 reporter.log('Verbose logging for VBoxService not supported for this guest yet');
1664
1665 #
1666 # Generate and upload some random files and dirs to the guest.
1667 # Note! Make sure we don't run into too-long-path issues when using
1668 # the test files on the host if.
1669 #
1670 cchGst = len(self.oTstDrv.getGuestTempDir(oTestVm)) + 1 + len('addgst-1') + 1;
1671 cchHst = len(self.oTstDrv.sScratchPath) + 1 + len('copyto/addgst-1') + 1;
1672 cchMaxPath = 230;
1673 if cchHst > cchGst:
1674 cchMaxPath -= cchHst - cchGst;
1675 reporter.log('cchMaxPath=%s (cchHst=%s, cchGst=%s)' % (cchMaxPath, cchHst, cchGst,));
1676 asCompatibleWith = None;
1677 if oTestVm.isWindows():
1678 asCompatibleWith = [ 'win' ];
1679 self.oTestFiles = vboxtestfileset.TestFileSet(oTestVm,
1680 self.oTstDrv.getGuestTempDir(oTestVm), 'addgst-1',
1681 cchMaxPath = cchMaxPath, asCompatibleWith = asCompatibleWith);
1682 return self.oTestFiles.upload(oTxsSession, self.oTstDrv);
1683
1684
1685 #
1686 # gctrlXxxx stuff.
1687 #
1688
1689 def gctrlCopyFileFrom(self, oGuestSession, oTest, fExpected):
1690 """
1691 Helper function to copy a single file from the guest to the host.
1692 """
1693 #
1694 # Do the copying.
1695 #
1696 reporter.log2('Copying guest file "%s" to host "%s"' % (limitString(oTest.sSrc), limitString(oTest.sDst)));
1697 try:
1698 if self.oTstDrv.fpApiVer >= 5.0:
1699 oCurProgress = oGuestSession.fileCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.afFlags);
1700 else:
1701 oCurProgress = oGuestSession.copyFrom(oTest.sSrc, oTest.sDst, oTest.afFlags);
1702 except:
1703 reporter.maybeErrXcpt(fExpected, 'Copy from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1704 return False;
1705 if oCurProgress is None:
1706 return reporter.error('No progress object returned');
1707 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlFileCopyFrom");
1708 oProgress.wait();
1709 if not oProgress.isSuccess():
1710 oProgress.logResult(fIgnoreErrors = not fExpected);
1711 return False;
1712
1713 #
1714 # Check the result if we can.
1715 #
1716 if oTest.oSrc:
1717 assert isinstance(oTest.oSrc, testfileset.TestFile);
1718 sDst = oTest.sDst;
1719 if os.path.isdir(sDst):
1720 sDst = os.path.join(sDst, oTest.oSrc.sName);
1721 try:
1722 oFile = open(sDst, 'rb');
1723 except:
1724 return reporter.errorXcpt('open(%s) failed during verfication' % (sDst,));
1725 fEqual = oTest.oSrc.equalFile(oFile);
1726 oFile.close();
1727 if not fEqual:
1728 return reporter.error('Content differs for "%s"' % (sDst,));
1729
1730 return True;
1731
1732 def __compareTestDir(self, oDir, sHostPath): # type: (testfileset.TestDir, str) -> bool
1733 """
1734 Recursively compare the content of oDir and sHostPath.
1735
1736 Returns True on success, False + error logging on failure.
1737
1738 Note! This ASSUMES that nothing else was copied to sHostPath!
1739 """
1740 #
1741 # First check out all the entries and files in the directory.
1742 #
1743 dLeftUpper = dict(oDir.dChildrenUpper);
1744 try:
1745 asEntries = os.listdir(sHostPath);
1746 except:
1747 return reporter.errorXcpt('os.listdir(%s) failed' % (sHostPath,));
1748
1749 fRc = True;
1750 for sEntry in asEntries:
1751 sEntryUpper = sEntry.upper();
1752 if sEntryUpper not in dLeftUpper:
1753 fRc = reporter.error('Unexpected entry "%s" in "%s"' % (sEntry, sHostPath,));
1754 else:
1755 oFsObj = dLeftUpper[sEntryUpper];
1756 del dLeftUpper[sEntryUpper];
1757
1758 if isinstance(oFsObj, testfileset.TestFile):
1759 sFilePath = os.path.join(sHostPath, oFsObj.sName);
1760 try:
1761 oFile = open(sFilePath, 'rb');
1762 except:
1763 fRc = reporter.errorXcpt('open(%s) failed during verfication' % (sFilePath,));
1764 else:
1765 fEqual = oFsObj.equalFile(oFile);
1766 oFile.close();
1767 if not fEqual:
1768 fRc = reporter.error('Content differs for "%s"' % (sFilePath,));
1769
1770 # List missing entries:
1771 for sKey in dLeftUpper:
1772 oEntry = dLeftUpper[sKey];
1773 fRc = reporter.error('%s: Missing %s "%s" (src path: %s)'
1774 % (sHostPath, oEntry.sName,
1775 'file' if isinstance(oEntry, testfileset.TestFile) else 'directory', oEntry.sPath));
1776
1777 #
1778 # Recurse into subdirectories.
1779 #
1780 for oFsObj in oDir.aoChildren:
1781 if isinstance(oFsObj, testfileset.TestDir):
1782 fRc = self.__compareTestDir(oFsObj, os.path.join(sHostPath, oFsObj.sName)) and fRc;
1783 return fRc;
1784
1785 def gctrlCopyDirFrom(self, oGuestSession, oTest, fExpected):
1786 """
1787 Helper function to copy a directory from the guest to the host.
1788 """
1789 #
1790 # Do the copying.
1791 #
1792 reporter.log2('Copying guest dir "%s" to host "%s"' % (limitString(oTest.sSrc), limitString(oTest.sDst)));
1793 try:
1794 oCurProgress = oGuestSession.directoryCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.afFlags);
1795 except:
1796 reporter.maybeErrXcpt(fExpected, 'Copy dir from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1797 return False;
1798 if oCurProgress is None:
1799 return reporter.error('No progress object returned');
1800
1801 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlDirCopyFrom");
1802 oProgress.wait();
1803 if not oProgress.isSuccess():
1804 oProgress.logResult(fIgnoreErrors = not fExpected);
1805 return False;
1806
1807 #
1808 # Check the result if we can.
1809 #
1810 if oTest.oSrc:
1811 assert isinstance(oTest.oSrc, testfileset.TestDir);
1812 sDst = oTest.sDst;
1813 if oTest.fIntoDst:
1814 return self.__compareTestDir(oTest.oSrc, os.path.join(sDst, oTest.oSrc.sName));
1815 oDummy = testfileset.TestDir(None, 'dummy');
1816 oDummy.aoChildren = [oTest.oSrc,]
1817 oDummy.dChildrenUpper = { oTest.oSrc.sName.upper(): oTest.oSrc, };
1818 return self.__compareTestDir(oDummy, sDst);
1819 return True;
1820
1821 def gctrlCopyFileTo(self, oGuestSession, sSrc, sDst, afFlags, fIsError):
1822 """
1823 Helper function to copy a single file from the host to the guest.
1824 """
1825 reporter.log2('Copying host file "%s" to guest "%s" (flags %s)' % (limitString(sSrc), limitString(sDst), afFlags));
1826 try:
1827 if self.oTstDrv.fpApiVer >= 5.0:
1828 oCurProgress = oGuestSession.fileCopyToGuest(sSrc, sDst, afFlags);
1829 else:
1830 oCurProgress = oGuestSession.copyTo(sSrc, sDst, afFlags);
1831 except:
1832 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1833 return False;
1834
1835 if oCurProgress is None:
1836 return reporter.error('No progress object returned');
1837 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1838
1839 try:
1840 oProgress.wait();
1841 if not oProgress.isSuccess():
1842 oProgress.logResult(fIgnoreErrors = not fIsError);
1843 return False;
1844 except:
1845 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1846 return False;
1847 return True;
1848
1849 def gctrlCopyDirTo(self, oGuestSession, sSrc, sDst, afFlags, fIsError):
1850 """
1851 Helper function to copy a directory tree from the host to the guest.
1852 """
1853 reporter.log2('Copying host directory "%s" to guest "%s" (flags %s)' % (limitString(sSrc), limitString(sDst), afFlags));
1854 try:
1855 oCurProgress = oGuestSession.directoryCopyToGuest(sSrc, sDst, afFlags);
1856 except:
1857 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1858 return False;
1859
1860 if oCurProgress is None:
1861 return reporter.error('No progress object returned');
1862 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1863
1864 try:
1865 oProgress.wait();
1866 if not oProgress.isSuccess():
1867 oProgress.logResult(fIgnoreErrors = not fIsError);
1868 return False;
1869 except:
1870 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1871 return False;
1872 return True;
1873
1874 def gctrlCreateDir(self, oTest, oRes, oGuestSession):
1875 """
1876 Helper function to create a guest directory specified in the current test.
1877 """
1878 reporter.log2('Creating directory "%s"' % (limitString(oTest.sDirectory),));
1879 try:
1880 oGuestSession.directoryCreate(oTest.sDirectory, oTest.fMode, oTest.afFlags);
1881 except:
1882 reporter.maybeErrXcpt(oRes.fRc, 'Failed to create "%s" fMode=%o afFlags=%s'
1883 % (oTest.sDirectory, oTest.fMode, oTest.afFlags,));
1884 return not oRes.fRc;
1885 if oRes.fRc is not True:
1886 return reporter.error('Did not expect to create directory "%s"!' % (oTest.sDirectory,));
1887
1888 # Check if the directory now exists.
1889 try:
1890 if self.oTstDrv.fpApiVer >= 5.0:
1891 fDirExists = oGuestSession.directoryExists(oTest.sDirectory, False);
1892 else:
1893 fDirExists = oGuestSession.directoryExists(oTest.sDirectory);
1894 except:
1895 return reporter.errorXcpt('directoryExists failed on "%s"!' % (oTest.sDirectory,));
1896 if not fDirExists:
1897 return reporter.errorXcpt('directoryExists returned False on "%s" after directoryCreate succeeded!'
1898 % (oTest.sDirectory,));
1899 return True;
1900
1901 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, sSubDir = None):
1902 """
1903 Helper function to recursively read a guest directory tree specified in the current test.
1904 """
1905 sDir = oTest.sDirectory;
1906 sFilter = oTest.sFilter;
1907 afFlags = oTest.afFlags;
1908 oTestVm = oTest.oCreds.oTestVm;
1909 sCurDir = oTestVm.pathJoin(sDir, sSubDir) if sSubDir else sDir;
1910
1911 fRc = True; # Be optimistic.
1912 cDirs = 0; # Number of directories read.
1913 cFiles = 0; # Number of files read.
1914 cOthers = 0; # Other files.
1915
1916 # Open the directory:
1917 reporter.log2('Directory="%s", filter="%s", afFlags="%s"' % (limitString(sCurDir), sFilter, afFlags));
1918 try:
1919 oCurDir = oGuestSession.directoryOpen(sCurDir, sFilter, afFlags);
1920 except:
1921 reporter.maybeErrXcpt(fIsError, 'sCurDir=%s sFilter=%s afFlags=%s' % (sCurDir, sFilter, afFlags,))
1922 return (False, 0, 0, 0);
1923
1924 # Read the directory.
1925 while fRc is True:
1926 try:
1927 oFsObjInfo = oCurDir.read();
1928 except Exception as oXcpt:
1929 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1930 if self.oTstDrv.fpApiVer > 5.2:
1931 reporter.errorXcpt('Error reading directory "%s":' % (sCurDir,));
1932 else:
1933 # Unlike fileOpen, directoryOpen will not fail if the directory does not exist.
1934 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,));
1935 fRc = False;
1936 else:
1937 reporter.log2('\tNo more directory entries for "%s"' % (limitString(sCurDir),));
1938 break;
1939
1940 try:
1941 sName = oFsObjInfo.name;
1942 eType = oFsObjInfo.type;
1943 except:
1944 fRc = reporter.errorXcpt();
1945 break;
1946
1947 if sName in ('.', '..', ):
1948 if eType != vboxcon.FsObjType_Directory:
1949 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1950 % (sName, eType, vboxcon.FsObjType_Directory));
1951 elif eType == vboxcon.FsObjType_Directory:
1952 reporter.log2(' Directory "%s"' % limitString(oFsObjInfo.name));
1953 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError,
1954 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName);
1955 fRc = aSubResult[0];
1956 cDirs += aSubResult[1] + 1;
1957 cFiles += aSubResult[2];
1958 cOthers += aSubResult[3];
1959 elif eType is vboxcon.FsObjType_File:
1960 reporter.log4(' File "%s"' % oFsObjInfo.name);
1961 cFiles += 1;
1962 elif eType is vboxcon.FsObjType_Symlink:
1963 reporter.log4(' Symlink "%s" -- not tested yet' % oFsObjInfo.name);
1964 cOthers += 1;
1965 elif oTestVm.isWindows() \
1966 or oTestVm.isOS2() \
1967 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock,
1968 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut):
1969 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' %
1970 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,));
1971 else:
1972 cOthers += 1;
1973
1974 # Close the directory
1975 try:
1976 oCurDir.close();
1977 except:
1978 fRc = reporter.errorXcpt('sCurDir=%s' % (sCurDir));
1979
1980 return (fRc, cDirs, cFiles, cOthers);
1981
1982 def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (testfileset.TestDir) -> bool
1983 """
1984 Helper function to recursively read a guest directory tree specified in the current test.
1985 """
1986
1987 #
1988 # Process the directory.
1989 #
1990
1991 # Open the directory:
1992 try:
1993 oCurDir = oGuestSession.directoryOpen(oDir.sPath, '', None);
1994 except:
1995 return reporter.errorXcpt('sPath=%s' % (oDir.sPath,));
1996
1997 # Read the directory.
1998 dLeftUpper = dict(oDir.dChildrenUpper);
1999 cDot = 0;
2000 cDotDot = 0;
2001 fRc = True;
2002 while True:
2003 try:
2004 oFsObjInfo = oCurDir.read();
2005 except Exception as oXcpt:
2006 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
2007 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath,));
2008 break;
2009
2010 try:
2011 sName = oFsObjInfo.name;
2012 eType = oFsObjInfo.type;
2013 cbFile = oFsObjInfo.objectSize;
2014 ## @todo check further attributes.
2015 except:
2016 fRc = reporter.errorXcpt();
2017 break;
2018
2019 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment:
2020 if sName in ('.', '..', ):
2021 if eType != vboxcon.FsObjType_Directory:
2022 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
2023 % (sName, eType, vboxcon.FsObjType_Directory));
2024 if sName == '.': cDot += 1;
2025 else: cDotDot += 1;
2026 else:
2027 # Find the child and remove it from the dictionary.
2028 sNameUpper = sName.upper();
2029 oFsObj = dLeftUpper.get(sNameUpper);
2030 if oFsObj is None:
2031 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!'
2032 % (sName, oDir.sPath, eType, cbFile,));
2033 else:
2034 del dLeftUpper[sNameUpper];
2035
2036 # Check type
2037 if isinstance(oFsObj, testfileset.TestDir):
2038 if eType != vboxcon.FsObjType_Directory:
2039 fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
2040 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
2041 elif isinstance(oFsObj, testfileset.TestFile):
2042 if eType != vboxcon.FsObjType_File:
2043 fRc = reporter.error('%s: expected file (%d), got eType=%d!'
2044 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,));
2045 else:
2046 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),));
2047
2048 # Check the name.
2049 if oFsObj.sName != sName:
2050 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,));
2051
2052 # Check the size if a file.
2053 if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent:
2054 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,));
2055
2056 ## @todo check timestamps and attributes.
2057
2058 # Close the directory
2059 try:
2060 oCurDir.close();
2061 except:
2062 fRc = reporter.errorXcpt('oDir.sPath=%s' % (oDir.sPath,));
2063
2064 # Any files left over?
2065 for sKey in dLeftUpper:
2066 oFsObj = dLeftUpper[sKey];
2067 fRc = reporter.error('%s: Was not returned! (%s)' % (oFsObj.sPath, type(oFsObj),));
2068
2069 # Check the dot and dot-dot counts.
2070 if cDot != 1:
2071 fRc = reporter.error('%s: Found %s "." entries, expected exactly 1!' % (oDir.sPath, cDot,));
2072 if cDotDot != 1:
2073 fRc = reporter.error('%s: Found %s ".." entries, expected exactly 1!' % (oDir.sPath, cDotDot,));
2074
2075 #
2076 # Recurse into subdirectories using info from oDir.
2077 #
2078 for oFsObj in oDir.aoChildren:
2079 if isinstance(oFsObj, testfileset.TestDir):
2080 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc;
2081
2082 return fRc;
2083
2084 def gctrlExecDoTest(self, i, oTest, oRes, oGuestSession):
2085 """
2086 Wrapper function around gctrlExecute to provide more sanity checking
2087 when needed in actual execution tests.
2088 """
2089 reporter.log('Testing #%d, cmd="%s" ...' % (i, oTest.sCmd));
2090 fRcExec = self.gctrlExecute(oTest, oGuestSession, oRes.fRc);
2091 if fRcExec == oRes.fRc:
2092 fRc = True;
2093 if fRcExec is True:
2094 # Compare exit status / code on successful process execution.
2095 if oTest.uExitStatus != oRes.uExitStatus \
2096 or oTest.iExitCode != oRes.iExitCode:
2097 fRc = reporter.error('Test #%d (%s) failed: Got exit status + code %d,%d, expected %d,%d'
2098 % (i, oTest.asArgs, oTest.uExitStatus, oTest.iExitCode,
2099 oRes.uExitStatus, oRes.iExitCode));
2100
2101 # Compare test / result buffers on successful process execution.
2102 if oTest.sBuf is not None and oRes.sBuf is not None:
2103 if not utils.areBytesEqual(oTest.sBuf, oRes.sBuf):
2104 fRc = reporter.error('Test #%d (%s) failed: Got buffer\n%s (%d bytes), expected\n%s (%d bytes)'
2105 % (i, oTest.asArgs,
2106 map(hex, map(ord, oTest.sBuf)), len(oTest.sBuf),
2107 map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf)));
2108 reporter.log2('Test #%d passed: Buffers match (%d bytes)' % (i, len(oRes.sBuf)));
2109 elif oRes.sBuf and not oTest.sBuf:
2110 fRc = reporter.error('Test #%d (%s) failed: Got no buffer data, expected\n%s (%dbytes)' %
2111 (i, oTest.asArgs, map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf),));
2112
2113 if oRes.cbStdOut is not None and oRes.cbStdOut != oTest.cbStdOut:
2114 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stdout data, expected %d'
2115 % (i, oTest.asArgs, oTest.cbStdOut, oRes.cbStdOut));
2116 if oRes.cbStdErr is not None and oRes.cbStdErr != oTest.cbStdErr:
2117 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stderr data, expected %d'
2118 % (i, oTest.asArgs, oTest.cbStdErr, oRes.cbStdErr));
2119 else:
2120 fRc = reporter.error('Test #%d (%s) failed: Got %s, expected %s' % (i, oTest.asArgs, fRcExec, oRes.fRc));
2121 return fRc;
2122
2123 def gctrlExecute(self, oTest, oGuestSession, fIsError): # pylint: disable=too-many-statements
2124 """
2125 Helper function to execute a program on a guest, specified in the current test.
2126
2127 Note! This weirdo returns results (process exitcode and status) in oTest.
2128 """
2129 fRc = True; # Be optimistic.
2130
2131 # Reset the weird result stuff:
2132 oTest.cbStdOut = 0;
2133 oTest.cbStdErr = 0;
2134 oTest.sBuf = '';
2135 oTest.uExitStatus = 0;
2136 oTest.iExitCode = 0;
2137
2138 ## @todo Compare execution timeouts!
2139 #tsStart = base.timestampMilli();
2140
2141 try:
2142 reporter.log2('Using session user=%s, sDomain=%s, name=%s, timeout=%d'
2143 % (oGuestSession.user, oGuestSession.domain, oGuestSession.name, oGuestSession.timeout,));
2144 except:
2145 return reporter.errorXcpt();
2146
2147 #
2148 # Start the process:
2149 #
2150 reporter.log2('Executing sCmd=%s, afFlags=%s, timeoutMS=%d, asArgs=%s, asEnv=%s'
2151 % (oTest.sCmd, oTest.afFlags, oTest.timeoutMS, limitString(oTest.asArgs), limitString(oTest.aEnv),));
2152 try:
2153 oProcess = oGuestSession.processCreate(oTest.sCmd,
2154 oTest.asArgs if self.oTstDrv.fpApiVer >= 5.0 else oTest.asArgs[1:],
2155 oTest.aEnv, oTest.afFlags, oTest.timeoutMS);
2156 except:
2157 reporter.maybeErrXcpt(fIsError, 'type=%s, asArgs=%s' % (type(oTest.asArgs), oTest.asArgs,));
2158 return False;
2159 if oProcess is None:
2160 return reporter.error('oProcess is None! (%s)' % (oTest.asArgs,));
2161
2162 #time.sleep(5); # try this if you want to see races here.
2163
2164 # Wait for the process to start properly:
2165 reporter.log2('Process start requested, waiting for start (%dms) ...' % (oTest.timeoutMS,));
2166 iPid = -1;
2167 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Start, ];
2168 try:
2169 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
2170 except:
2171 reporter.maybeErrXcpt(fIsError, 'waitforArray failed for asArgs=%s' % (oTest.asArgs,));
2172 fRc = False;
2173 else:
2174 try:
2175 eStatus = oProcess.status;
2176 iPid = oProcess.PID;
2177 except:
2178 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2179 else:
2180 reporter.log2('Wait result returned: %d, current process status is: %d' % (eWaitResult, eStatus,));
2181
2182 #
2183 # Wait for the process to run to completion if necessary.
2184 #
2185 # Note! The above eWaitResult return value can be ignored as it will
2186 # (mostly) reflect the process status anyway.
2187 #
2188 if eStatus == vboxcon.ProcessStatus_Started:
2189
2190 # What to wait for:
2191 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate, ];
2192 if vboxcon.ProcessCreateFlag_WaitForStdOut in oTest.afFlags:
2193 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdOut);
2194 if vboxcon.ProcessCreateFlag_WaitForStdErr in oTest.afFlags:
2195 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdErr);
2196 ## @todo Add vboxcon.ProcessWaitForFlag_StdIn.
2197
2198 reporter.log2('Process (PID %d) started, waiting for termination (%dms), aeWaitFor=%s ...'
2199 % (iPid, oTest.timeoutMS, aeWaitFor));
2200 acbFdOut = [0,0,0];
2201 while True:
2202 try:
2203 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
2204 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
2205 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
2206 try: oProcess.close();
2207 except: pass;
2208 break;
2209 except:
2210 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2211 break;
2212 #reporter.log2('Wait returned: %d' % (eWaitResult,));
2213
2214 # Process output:
2215 for eFdResult, iFd, sFdNm in [ (vboxcon.ProcessWaitResult_StdOut, 1, 'stdout'),
2216 (vboxcon.ProcessWaitResult_StdErr, 2, 'stderr'), ]:
2217 if eWaitResult in (eFdResult, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
2218 try:
2219 abBuf = oProcess.read(iFd, 64 * 1024, oTest.timeoutMS);
2220 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
2221 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
2222 try: oProcess.close();
2223 except: pass;
2224 except:
2225 reporter.maybeErrXcpt(fIsError, 'asArgs=%s' % (oTest.asArgs,));
2226 else:
2227 if abBuf:
2228 reporter.log2('Process (PID %d) got %d bytes of %s data (type: %s)'
2229 % (iPid, len(abBuf), sFdNm, type(abBuf)));
2230 if reporter.getVerbosity() >= 4:
2231 sBuf = '';
2232 if sys.version_info >= (2, 7):
2233 if isinstance(abBuf, memoryview): ## @todo Why is this happening?
2234 abBuf = abBuf.tobytes();
2235 sBuf = abBuf.decode("utf-8");
2236 if isinstance(abBuf, buffer):
2237 sBuf = str(abBuf);
2238 for sLine in sBuf.splitlines():
2239 reporter.log4('%s: %s' % (sFdNm, sLine));
2240 acbFdOut[iFd] += len(abBuf);
2241 oTest.sBuf = abBuf; ## @todo Figure out how to uniform + append!
2242
2243 ## Process input (todo):
2244 #if eWaitResult in (vboxcon.ProcessWaitResult_StdIn, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
2245 # reporter.log2('Process (PID %d) needs stdin data' % (iPid,));
2246
2247 # Termination or error?
2248 if eWaitResult in (vboxcon.ProcessWaitResult_Terminate,
2249 vboxcon.ProcessWaitResult_Error,
2250 vboxcon.ProcessWaitResult_Timeout,):
2251 try: eStatus = oProcess.status;
2252 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2253 reporter.log2('Process (PID %d) reported terminate/error/timeout: %d, status: %d'
2254 % (iPid, eWaitResult, eStatus,));
2255 break;
2256
2257 # End of the wait loop.
2258 _, oTest.cbStdOut, oTest.cbStdErr = acbFdOut;
2259
2260 try: eStatus = oProcess.status;
2261 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2262 reporter.log2('Final process status (PID %d) is: %d' % (iPid, eStatus));
2263 reporter.log2('Process (PID %d) %d stdout, %d stderr' % (iPid, oTest.cbStdOut, oTest.cbStdErr));
2264
2265 #
2266 # Get the final status and exit code of the process.
2267 #
2268 try:
2269 oTest.uExitStatus = oProcess.status;
2270 oTest.iExitCode = oProcess.exitCode;
2271 except:
2272 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2273 reporter.log2('Process (PID %d) has exit code: %d; status: %d ' % (iPid, oTest.iExitCode, oTest.uExitStatus));
2274 return fRc;
2275
2276 def testGuestCtrlSessionEnvironment(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2277 """
2278 Tests the guest session environment changes.
2279 """
2280 aoTests = [
2281 # Check basic operations.
2282 tdTestSessionEx([ # Initial environment is empty.
2283 tdStepSessionCheckEnv(),
2284 # Check clearing empty env.
2285 tdStepSessionClearEnv(),
2286 tdStepSessionCheckEnv(),
2287 # Check set.
2288 tdStepSessionSetEnv('FOO', 'BAR'),
2289 tdStepSessionCheckEnv(['FOO=BAR',]),
2290 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
2291 tdStepSessionClearEnv(),
2292 tdStepSessionCheckEnv(),
2293 # Check unset.
2294 tdStepSessionUnsetEnv('BAR'),
2295 tdStepSessionCheckEnv(['BAR']),
2296 tdStepSessionClearEnv(),
2297 tdStepSessionCheckEnv(),
2298 # Set + unset.
2299 tdStepSessionSetEnv('FOO', 'BAR'),
2300 tdStepSessionCheckEnv(['FOO=BAR',]),
2301 tdStepSessionUnsetEnv('FOO'),
2302 tdStepSessionCheckEnv(['FOO']),
2303 # Bulk environment changes (via attrib) (shall replace existing 'FOO').
2304 tdStepSessionBulkEnv( ['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
2305 tdStepSessionCheckEnv(['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
2306 ]),
2307 tdTestSessionEx([ # Check that setting the same value several times works.
2308 tdStepSessionSetEnv('FOO','BAR'),
2309 tdStepSessionCheckEnv([ 'FOO=BAR',]),
2310 tdStepSessionSetEnv('FOO','BAR2'),
2311 tdStepSessionCheckEnv([ 'FOO=BAR2',]),
2312 tdStepSessionSetEnv('FOO','BAR3'),
2313 tdStepSessionCheckEnv([ 'FOO=BAR3',]),
2314 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
2315 # Add a little unsetting to the mix.
2316 tdStepSessionSetEnv('BAR', 'BEAR'),
2317 tdStepSessionCheckEnv([ 'FOO=BAR3', 'BAR=BEAR',]),
2318 tdStepSessionUnsetEnv('FOO'),
2319 tdStepSessionCheckEnv([ 'FOO', 'BAR=BEAR',]),
2320 tdStepSessionSetEnv('FOO','BAR4'),
2321 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR',]),
2322 # The environment is case sensitive.
2323 tdStepSessionSetEnv('foo','BAR5'),
2324 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo=BAR5']),
2325 tdStepSessionUnsetEnv('foo'),
2326 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo']),
2327 ]),
2328 tdTestSessionEx([ # Bulk settings merges stuff, last entry standing.
2329 tdStepSessionBulkEnv(['FOO=bar', 'foo=bar', 'FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
2330 tdStepSessionCheckEnv(['FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
2331 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
2332 tdStepSessionBulkEnv(['2=1+1', 'FOO=doofus2', ]),
2333 tdStepSessionCheckEnv(['2=1+1', 'FOO=doofus2' ]),
2334 ]),
2335 # Invalid variable names.
2336 tdTestSessionEx([
2337 tdStepSessionSetEnv('', 'FOO', vbox.ComError.E_INVALIDARG),
2338 tdStepSessionCheckEnv(),
2339 tdStepRequireMinimumApiVer(5.0), # 4.3 is too relaxed checking input!
2340 tdStepSessionBulkEnv(['', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2341 tdStepSessionCheckEnv(),
2342 tdStepSessionSetEnv('FOO=', 'BAR', vbox.ComError.E_INVALIDARG),
2343 tdStepSessionCheckEnv(),
2344 ]),
2345 # A bit more weird keys/values.
2346 tdTestSessionEx([ tdStepSessionSetEnv('$$$', ''),
2347 tdStepSessionCheckEnv([ '$$$=',]), ]),
2348 tdTestSessionEx([ tdStepSessionSetEnv('$$$', '%%%'),
2349 tdStepSessionCheckEnv([ '$$$=%%%',]),
2350 ]),
2351 tdTestSessionEx([ tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
2352 tdStepSessionSetEnv(u'ß$%ß&', ''),
2353 tdStepSessionCheckEnv([ u'ß$%ß&=',]),
2354 ]),
2355 # Misc stuff.
2356 tdTestSessionEx([ tdStepSessionSetEnv('FOO', ''),
2357 tdStepSessionCheckEnv(['FOO=',]),
2358 ]),
2359 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
2360 tdStepSessionCheckEnv(['FOO=BAR',])
2361 ],),
2362 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
2363 tdStepSessionSetEnv('BAR', 'BAZ'),
2364 tdStepSessionCheckEnv([ 'FOO=BAR', 'BAR=BAZ',]),
2365 ]),
2366 ];
2367 # Leading '=' in the name is okay for windows guests in 6.1 and later (for driver letter CWDs).
2368 if (self.oTstDrv.fpApiVer < 6.1 and self.oTstDrv.fpApiVer >= 5.0) or not oTestVm.isWindows():
2369 aoTests.append(tdTestSessionEx([tdStepSessionSetEnv('=', '===', vbox.ComError.E_INVALIDARG),
2370 tdStepSessionCheckEnv(),
2371 tdStepSessionSetEnv('=FOO', 'BAR', vbox.ComError.E_INVALIDARG),
2372 tdStepSessionCheckEnv(),
2373 tdStepSessionBulkEnv(['=', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2374 tdStepSessionCheckEnv(),
2375 tdStepSessionBulkEnv(['=FOO', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2376 tdStepSessionCheckEnv(),
2377 tdStepSessionBulkEnv(['=D:=D:/tmp', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2378 tdStepSessionCheckEnv(),
2379 tdStepSessionSetEnv('=D:', 'D:/temp', vbox.ComError.E_INVALIDARG),
2380 tdStepSessionCheckEnv(),
2381 ]));
2382 elif self.oTstDrv.fpApiVer >= 6.1 and oTestVm.isWindows():
2383 aoTests.append(tdTestSessionEx([tdStepSessionSetEnv('=D:', 'D:/tmp'),
2384 tdStepSessionCheckEnv(['=D:=D:/tmp',]),
2385 tdStepSessionBulkEnv(['=D:=D:/temp', '=FOO', 'foo=bar']),
2386 tdStepSessionCheckEnv(['=D:=D:/temp', '=FOO', 'foo=bar']),
2387 tdStepSessionUnsetEnv('=D:'),
2388 tdStepSessionCheckEnv(['=D:', '=FOO', 'foo=bar']),
2389 ]));
2390
2391 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'SessionEnv');
2392
2393 def testGuestCtrlSession(self, oSession, oTxsSession, oTestVm):
2394 """
2395 Tests the guest session handling.
2396 """
2397
2398 #
2399 # Tests:
2400 #
2401 atTests = [
2402 # Invalid parameters.
2403 [ tdTestSession(sUser = ''), tdTestResultSession() ],
2404 # User account without a passwort - forbidden.
2405 [ tdTestSession(sPassword = "" ), tdTestResultSession() ],
2406 # Various wrong credentials.
2407 # Note! Only windows cares about sDomain, the other guests ignores it.
2408 # Note! On Guest Additions < 4.3 this always succeeds because these don't
2409 # support creating dedicated sessions. Instead, guest process creation
2410 # then will fail. See note below.
2411 [ tdTestSession(sPassword = 'bar'), tdTestResultSession() ],
2412 [ tdTestSession(sUser = 'foo', sPassword = 'bar'), tdTestResultSession() ],
2413 [ tdTestSession(sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
2414 [ tdTestSession(sUser = 'foo', sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
2415 ];
2416 if oTestVm.isWindows(): # domain is ignored elsewhere.
2417 atTests.append([ tdTestSession(sDomain = 'boo'), tdTestResultSession() ]);
2418
2419 # Finally, correct credentials.
2420 atTests.append([ tdTestSession(), tdTestResultSession(fRc = True, cNumSessions = 1) ]);
2421
2422 #
2423 # Run the tests.
2424 #
2425 fRc = True;
2426 for (i, tTest) in enumerate(atTests):
2427 oCurTest = tTest[0] # type: tdTestSession
2428 oCurRes = tTest[1] # type: tdTestResult
2429
2430 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2431 reporter.log('Testing #%d, user="%s", sPassword="%s", sDomain="%s" ...'
2432 % (i, oCurTest.oCreds.sUser, oCurTest.oCreds.sPassword, oCurTest.oCreds.sDomain));
2433 sCurGuestSessionName = 'testGuestCtrlSession: Test #%d' % (i,);
2434 fRc2, oCurGuestSession = oCurTest.createSession(sCurGuestSessionName, fIsError = oCurRes.fRc);
2435
2436 # See note about < 4.3 Guest Additions above.
2437 uProtocolVersion = 2;
2438 if oCurGuestSession is not None:
2439 try:
2440 uProtocolVersion = oCurGuestSession.protocolVersion;
2441 except:
2442 fRc = reporter.errorXcpt('Test #%d' % (i,));
2443
2444 if uProtocolVersion >= 2 and fRc2 is not oCurRes.fRc:
2445 fRc = reporter.error('Test #%d failed: Session creation failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
2446
2447 if fRc2 and oCurGuestSession is None:
2448 fRc = reporter.error('Test #%d failed: no session object' % (i,));
2449 fRc2 = False;
2450
2451 if fRc2:
2452 if uProtocolVersion >= 2: # For Guest Additions < 4.3 getSessionCount() always will return 1.
2453 cCurSessions = oCurTest.getSessionCount(self.oTstDrv.oVBoxMgr);
2454 if cCurSessions != oCurRes.cNumSessions:
2455 fRc = reporter.error('Test #%d failed: Session count does not match: Got %d, expected %d'
2456 % (i, cCurSessions, oCurRes.cNumSessions));
2457 try:
2458 sObjName = oCurGuestSession.name;
2459 except:
2460 fRc = reporter.errorXcpt('Test #%d' % (i,));
2461 else:
2462 if sObjName != sCurGuestSessionName:
2463 fRc = reporter.error('Test #%d failed: Session name does not match: Got "%s", expected "%s"'
2464 % (i, sObjName, sCurGuestSessionName));
2465 fRc2 = oCurTest.closeSession();
2466 if fRc2 is False:
2467 fRc = reporter.error('Test #%d failed: Session could not be closed' % (i,));
2468
2469 if fRc is False:
2470 return (False, oTxsSession);
2471
2472 #
2473 # Multiple sessions.
2474 #
2475 cMaxGuestSessions = 31; # Maximum number of concurrent guest session allowed.
2476 # Actually, this is 32, but we don't test session 0.
2477 aoMultiSessions = {};
2478 reporter.log2('Opening multiple guest tsessions at once ...');
2479 for i in xrange(cMaxGuestSessions + 1):
2480 aoMultiSessions[i] = tdTestSession(sSessionName = 'MultiSession #%d' % (i,));
2481 aoMultiSessions[i].setEnvironment(oSession, oTxsSession, oTestVm);
2482
2483 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
2484 reporter.log2('MultiSession test #%d count is %d' % (i, cCurSessions));
2485 if cCurSessions != i:
2486 return (reporter.error('MultiSession count is %d, expected %d' % (cCurSessions, i)), oTxsSession);
2487 fRc2, _ = aoMultiSessions[i].createSession('MultiSession #%d' % (i,), i < cMaxGuestSessions);
2488 if fRc2 is not True:
2489 if i < cMaxGuestSessions:
2490 return (reporter.error('MultiSession #%d test failed' % (i,)), oTxsSession);
2491 reporter.log('MultiSession #%d exceeded concurrent guest session count, good' % (i,));
2492 break;
2493
2494 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
2495 if cCurSessions is not cMaxGuestSessions:
2496 return (reporter.error('Final session count %d, expected %d ' % (cCurSessions, cMaxGuestSessions,)), oTxsSession);
2497
2498 reporter.log2('Closing MultiSessions ...');
2499 for i in xrange(cMaxGuestSessions):
2500 # Close this session:
2501 oClosedGuestSession = aoMultiSessions[i].oGuestSession;
2502 fRc2 = aoMultiSessions[i].closeSession();
2503 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr)
2504 reporter.log2('MultiSession #%d count is %d' % (i, cCurSessions,));
2505 if fRc2 is False:
2506 fRc = reporter.error('Closing MultiSession #%d failed' % (i,));
2507 elif cCurSessions != cMaxGuestSessions - (i + 1):
2508 fRc = reporter.error('Expected %d session after closing #%d, got %d instead'
2509 % (cMaxGuestSessions - (i + 1), cCurSessions, i,));
2510 assert aoMultiSessions[i].oGuestSession is None or not fRc2;
2511 ## @todo any way to check that the session is closed other than the 'sessions' attribute?
2512
2513 # Try check that none of the remaining sessions got closed.
2514 try:
2515 aoGuestSessions = self.oTstDrv.oVBoxMgr.getArray(atTests[0][0].oGuest, 'sessions');
2516 except:
2517 return (reporter.errorXcpt('i=%d/%d' % (i, cMaxGuestSessions,)), oTxsSession);
2518 if oClosedGuestSession in aoGuestSessions:
2519 fRc = reporter.error('i=%d/%d: %s should not be in %s'
2520 % (i, cMaxGuestSessions, oClosedGuestSession, aoGuestSessions));
2521 if i + 1 < cMaxGuestSessions: # Not sure what xrange(2,2) does...
2522 for j in xrange(i + 1, cMaxGuestSessions):
2523 if aoMultiSessions[j].oGuestSession not in aoGuestSessions:
2524 fRc = reporter.error('i=%d/j=%d/%d: %s should be in %s'
2525 % (i, j, cMaxGuestSessions, aoMultiSessions[j].oGuestSession, aoGuestSessions));
2526 ## @todo any way to check that they work?
2527
2528 ## @todo Test session timeouts.
2529
2530 return (fRc, oTxsSession);
2531
2532 def testGuestCtrlSessionFileRefs(self, oSession, oTxsSession, oTestVm):
2533 """
2534 Tests the guest session file reference handling.
2535 """
2536
2537 # Find a file to play around with:
2538 sFile = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
2539
2540 # Use credential defaults.
2541 oCreds = tdCtxCreds();
2542 oCreds.applyDefaultsIfNotSet(oTestVm);
2543
2544 # Number of stale guest files to create.
2545 cStaleFiles = 10;
2546
2547 #
2548 # Start a session.
2549 #
2550 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2551 try:
2552 oGuest = oSession.o.console.guest;
2553 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionFileRefs");
2554 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2555 except:
2556 return (reporter.errorXcpt(), oTxsSession);
2557
2558 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2559 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2560 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2561 reporter.log('Session successfully started');
2562
2563 #
2564 # Open guest files and "forget" them (stale entries).
2565 # For them we don't have any references anymore intentionally.
2566 #
2567 reporter.log2('Opening stale files');
2568 fRc = True;
2569 for i in xrange(0, cStaleFiles):
2570 try:
2571 if self.oTstDrv.fpApiVer >= 5.0:
2572 oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly, vboxcon.FileOpenAction_OpenExisting, 0);
2573 else:
2574 oGuestSession.fileOpen(sFile, "r", "oe", 0);
2575 # Note: Use a timeout in the call above for not letting the stale processes
2576 # hanging around forever. This can happen if the installed Guest Additions
2577 # do not support terminating guest processes.
2578 except:
2579 fRc = reporter.errorXcpt('Opening stale file #%d failed:' % (i,));
2580 break;
2581
2582 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2583 except: fRc = reporter.errorXcpt();
2584 else:
2585 if cFiles != cStaleFiles:
2586 fRc = reporter.error('Got %d stale files, expected %d' % (cFiles, cStaleFiles));
2587
2588 if fRc is True:
2589 #
2590 # Open non-stale files and close them again.
2591 #
2592 reporter.log2('Opening non-stale files');
2593 aoFiles = [];
2594 for i in xrange(0, cStaleFiles):
2595 try:
2596 if self.oTstDrv.fpApiVer >= 5.0:
2597 oCurFile = oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly,
2598 vboxcon.FileOpenAction_OpenExisting, 0);
2599 else:
2600 oCurFile = oGuestSession.fileOpen(sFile, "r", "oe", 0);
2601 aoFiles.append(oCurFile);
2602 except:
2603 fRc = reporter.errorXcpt('Opening non-stale file #%d failed:' % (i,));
2604 break;
2605
2606 # Check the count.
2607 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2608 except: fRc = reporter.errorXcpt();
2609 else:
2610 if cFiles != cStaleFiles * 2:
2611 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles * 2));
2612
2613 # Close them.
2614 reporter.log2('Closing all non-stale files again ...');
2615 for i, oFile in enumerate(aoFiles):
2616 try:
2617 oFile.close();
2618 except:
2619 fRc = reporter.errorXcpt('Closing non-stale file #%d failed:' % (i,));
2620
2621 # Check the count again.
2622 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2623 except: fRc = reporter.errorXcpt();
2624 # Here we count the stale files (that is, files we don't have a reference
2625 # anymore for) and the opened and then closed non-stale files (that we still keep
2626 # a reference in aoFiles[] for).
2627 if cFiles != cStaleFiles:
2628 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles));
2629
2630 #
2631 # Check that all (referenced) non-stale files are now in the "closed" state.
2632 #
2633 reporter.log2('Checking statuses of all non-stale files ...');
2634 for i, oFile in enumerate(aoFiles):
2635 try:
2636 eFileStatus = aoFiles[i].status;
2637 except:
2638 fRc = reporter.errorXcpt('Checking status of file #%d failed:' % (i,));
2639 else:
2640 if eFileStatus != vboxcon.FileStatus_Closed:
2641 fRc = reporter.error('Non-stale file #%d has status %d, expected %d'
2642 % (i, eFileStatus, vboxcon.FileStatus_Closed));
2643
2644 if fRc is True:
2645 reporter.log2('All non-stale files closed');
2646
2647 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2648 except: fRc = reporter.errorXcpt();
2649 else: reporter.log2('Final guest session file count: %d' % (cFiles,));
2650
2651 #
2652 # Now try to close the session and see what happens.
2653 # Note! Session closing is why we've been doing all the 'if fRc is True' stuff above rather than returning.
2654 #
2655 reporter.log2('Closing guest session ...');
2656 try:
2657 oGuestSession.close();
2658 except:
2659 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2660
2661 return (fRc, oTxsSession);
2662
2663 #def testGuestCtrlSessionDirRefs(self, oSession, oTxsSession, oTestVm):
2664 # """
2665 # Tests the guest session directory reference handling.
2666 # """
2667
2668 # fRc = True;
2669 # return (fRc, oTxsSession);
2670
2671 def testGuestCtrlSessionProcRefs(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2672 """
2673 Tests the guest session process reference handling.
2674 """
2675
2676 sCmd = self.oTstDrv.getGuestSystemShell(oTestVm);
2677 asArgs = [sCmd,];
2678
2679 # Use credential defaults.
2680 oCreds = tdCtxCreds();
2681 oCreds.applyDefaultsIfNotSet(oTestVm);
2682
2683 # Number of stale guest processes to create.
2684 cStaleProcs = 10;
2685
2686 #
2687 # Start a session.
2688 #
2689 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2690 try:
2691 oGuest = oSession.o.console.guest;
2692 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionProcRefs");
2693 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2694 except:
2695 return (reporter.errorXcpt(), oTxsSession);
2696
2697 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2698 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2699 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2700 reporter.log('Session successfully started');
2701
2702 #
2703 # Fire off forever-running processes and "forget" them (stale entries).
2704 # For them we don't have any references anymore intentionally.
2705 #
2706 reporter.log2('Starting stale processes...');
2707 fRc = True;
2708 for i in xrange(0, cStaleProcs):
2709 try:
2710 oGuestSession.processCreate(sCmd,
2711 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], [],
2712 [ vboxcon.ProcessCreateFlag_WaitForStdOut ], 30 * 1000);
2713 # Note: Use a timeout in the call above for not letting the stale processes
2714 # hanging around forever. This can happen if the installed Guest Additions
2715 # do not support terminating guest processes.
2716 except:
2717 fRc = reporter.errorXcpt('Creating stale process #%d failed:' % (i,));
2718 break;
2719
2720 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2721 except: fRc = reporter.errorXcpt();
2722 else:
2723 if cProcesses != cStaleProcs:
2724 fRc = reporter.error('Got %d stale processes, expected %d' % (cProcesses, cStaleProcs));
2725
2726 if fRc is True:
2727 #
2728 # Fire off non-stale processes and wait for termination.
2729 #
2730 if oTestVm.isWindows() or oTestVm.isOS2():
2731 asArgs = [ sCmd, '/C', 'dir', '/S', self.oTstDrv.getGuestSystemDir(oTestVm), ];
2732 else:
2733 asArgs = [ sCmd, '-c', 'ls -la ' + self.oTstDrv.getGuestSystemDir(oTestVm), ];
2734 reporter.log2('Starting non-stale processes...');
2735 aoProcesses = [];
2736 for i in xrange(0, cStaleProcs):
2737 try:
2738 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2739 [], [], 0); # Infinite timeout.
2740 aoProcesses.append(oCurProc);
2741 except:
2742 fRc = reporter.errorXcpt('Creating non-stale process #%d failed:' % (i,));
2743 break;
2744
2745 reporter.log2('Waiting for non-stale processes to terminate...');
2746 for i, oProcess in enumerate(aoProcesses):
2747 try:
2748 eWaitResult = oProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 120 * 1000);
2749 eProcessStatus = oProcess.status;
2750 except:
2751 fRc = reporter.errorXcpt('Waiting for non-stale process #%d failed:' % (i,));
2752 else:
2753 if eProcessStatus != vboxcon.ProcessStatus_TerminatedNormally:
2754 fRc = reporter.error('Waiting for non-stale processes #%d resulted in status %d, expected %d (wr=%d)'
2755 % (i, eProcessStatus, vboxcon.ProcessStatus_TerminatedNormally, eWaitResult));
2756
2757 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2758 except: fRc = reporter.errorXcpt();
2759 else:
2760 # Here we count the stale processes (that is, processes we don't have a reference
2761 # anymore for) and the started + terminated non-stale processes (that we still keep
2762 # a reference in aoProcesses[] for).
2763 if cProcesses != (cStaleProcs * 2):
2764 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2765
2766 if fRc is True:
2767 reporter.log2('All non-stale processes terminated');
2768
2769 #
2770 # Fire off non-stale blocking processes which are terminated via terminate().
2771 #
2772 if oTestVm.isWindows() or oTestVm.isOS2():
2773 asArgs = [ sCmd, '/C', 'pause'];
2774 else:
2775 asArgs = [ sCmd ];
2776 reporter.log2('Starting blocking processes...');
2777 aoProcesses = [];
2778 for i in xrange(0, cStaleProcs):
2779 try:
2780 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2781 [], [], 30 * 1000);
2782 # Note: Use a timeout in the call above for not letting the stale processes
2783 # hanging around forever. This can happen if the installed Guest Additions
2784 # do not support terminating guest processes.
2785 aoProcesses.append(oCurProc);
2786 except:
2787 fRc = reporter.errorXcpt('Creating non-stale blocking process #%d failed:' % (i,));
2788 break;
2789
2790 reporter.log2('Terminating blocking processes...');
2791 for i, oProcess in enumerate(aoProcesses):
2792 try:
2793 oProcess.terminate();
2794 except: # Termination might not be supported, just skip and log it.
2795 reporter.logXcpt('Termination of blocking process #%d failed, skipped:' % (i,));
2796
2797 # There still should be 20 processes because we terminated the 10 newest ones.
2798 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2799 except: fRc = reporter.errorXcpt();
2800 else:
2801 if cProcesses != (cStaleProcs * 2):
2802 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2803 reporter.log2('Final guest session processes count: %d' % (cProcesses,));
2804
2805 #
2806 # Now try to close the session and see what happens.
2807 #
2808 reporter.log2('Closing guest session ...');
2809 try:
2810 oGuestSession.close();
2811 except:
2812 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2813
2814 return (fRc, oTxsSession);
2815
2816 def testGuestCtrlExec(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements
2817 """
2818 Tests the basic execution feature.
2819 """
2820
2821 # Paths:
2822 sVBoxControl = None; ## @todo Get path of installed Guest Additions. Later.
2823 sShell = self.oTstDrv.getGuestSystemShell(oTestVm);
2824 sShellOpt = '/C' if oTestVm.isWindows() or oTestVm.isOS2() else '-c';
2825 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
2826 sFileForReading = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
2827 if oTestVm.isWindows() or oTestVm.isOS2():
2828 sImageOut = self.oTstDrv.getGuestSystemShell(oTestVm);
2829 if oTestVm.isWindows():
2830 sVBoxControl = "C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\VBoxControl.exe";
2831 else:
2832 sImageOut = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'ls');
2833 if oTestVm.isLinux(): ## @todo check solaris and darwin.
2834 sVBoxControl = "/usr/bin/VBoxControl"; # Symlink
2835
2836 # Use credential defaults.
2837 oCreds = tdCtxCreds();
2838 oCreds.applyDefaultsIfNotSet(oTestVm);
2839
2840 atInvalid = [
2841 # Invalid parameters.
2842 [ tdTestExec(), tdTestResultExec() ],
2843 # Non-existent / invalid image.
2844 [ tdTestExec(sCmd = "non-existent"), tdTestResultExec() ],
2845 [ tdTestExec(sCmd = "non-existent2"), tdTestResultExec() ],
2846 # Use an invalid format string.
2847 [ tdTestExec(sCmd = "%$%%%&"), tdTestResultExec() ],
2848 # More stuff.
2849 [ tdTestExec(sCmd = u"ƒ‰‹ˆ÷‹¸"), tdTestResultExec() ],
2850 [ tdTestExec(sCmd = "???://!!!"), tdTestResultExec() ],
2851 [ tdTestExec(sCmd = "<>!\\"), tdTestResultExec() ],
2852 # Enable as soon as ERROR_BAD_DEVICE is implemented.
2853 #[ tdTestExec(sCmd = "CON", tdTestResultExec() ],
2854 ];
2855
2856 atExec = [];
2857 if oTestVm.isWindows() or oTestVm.isOS2():
2858 atExec += [
2859 # Basic execution.
2860 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2861 tdTestResultExec(fRc = True) ],
2862 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sFileForReading ]),
2863 tdTestResultExec(fRc = True) ],
2864 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir + '\\nonexist.dll' ]),
2865 tdTestResultExec(fRc = True, iExitCode = 1) ],
2866 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', '/wrongparam' ]),
2867 tdTestResultExec(fRc = True, iExitCode = 1) ],
2868 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2869 tdTestResultExec(fRc = True, iExitCode = 1) ],
2870 # StdOut.
2871 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2872 tdTestResultExec(fRc = True) ],
2873 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdout-non-existing' ]),
2874 tdTestResultExec(fRc = True, iExitCode = 1) ],
2875 # StdErr.
2876 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2877 tdTestResultExec(fRc = True) ],
2878 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stderr-non-existing' ]),
2879 tdTestResultExec(fRc = True, iExitCode = 1) ],
2880 # StdOut + StdErr.
2881 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2882 tdTestResultExec(fRc = True) ],
2883 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdouterr-non-existing' ]),
2884 tdTestResultExec(fRc = True, iExitCode = 1) ],
2885 ];
2886 # atExec.extend([
2887 # FIXME: Failing tests.
2888 # Environment variables.
2889 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2890 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2891 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2892 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2893 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2894 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2895 # aEnv = [ 'TEST_FOO=BAR' ],
2896 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2897 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2898 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2899 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2900 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2901 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2902
2903 ## @todo Create some files (or get files) we know the output size of to validate output length!
2904 ## @todo Add task which gets killed at some random time while letting the guest output something.
2905 #];
2906 else:
2907 atExec += [
2908 # Basic execution.
2909 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '-R', sSystemDir ]),
2910 tdTestResultExec(fRc = True) ],
2911 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sFileForReading ]),
2912 tdTestResultExec(fRc = True) ],
2913 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '--wrong-parameter' ]),
2914 tdTestResultExec(fRc = True, iExitCode = 2) ],
2915 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/non/existent' ]),
2916 tdTestResultExec(fRc = True, iExitCode = 2) ],
2917 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2918 tdTestResultExec(fRc = True, iExitCode = 127) ],
2919 # StdOut.
2920 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2921 tdTestResultExec(fRc = True) ],
2922 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdout-non-existing' ]),
2923 tdTestResultExec(fRc = True, iExitCode = 2) ],
2924 # StdErr.
2925 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2926 tdTestResultExec(fRc = True) ],
2927 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stderr-non-existing' ]),
2928 tdTestResultExec(fRc = True, iExitCode = 2) ],
2929 # StdOut + StdErr.
2930 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2931 tdTestResultExec(fRc = True) ],
2932 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdouterr-non-existing' ]),
2933 tdTestResultExec(fRc = True, iExitCode = 2) ],
2934 ];
2935 # atExec.extend([
2936 # FIXME: Failing tests.
2937 # Environment variables.
2938 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2939 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2940 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2941 #
2942 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2943 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2944 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2945 # aEnv = [ 'TEST_FOO=BAR' ],
2946 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2947 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2948 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2949 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2950 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2951 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2952
2953 ## @todo Create some files (or get files) we know the output size of to validate output length!
2954 ## @todo Add task which gets killed at some random time while letting the guest output something.
2955 #];
2956
2957 #
2958 #for iExitCode in xrange(0, 127):
2959 # atExec.append([ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'exit %s' % iExitCode ]),
2960 # tdTestResultExec(fRc = True, iExitCode = iExitCode) ]);
2961
2962 if sVBoxControl \
2963 and self.oTstDrv.fpApiVer >= 6.0: # Investigate with this doesn't work on (<) 5.2.
2964 # Paths with spaces on windows.
2965 atExec.append([ tdTestExec(sCmd = sVBoxControl, asArgs = [ sVBoxControl, 'version' ],
2966 afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut,
2967 vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2968 tdTestResultExec(fRc = True) ]);
2969
2970 # Test very long arguments. Be careful when tweaking this to not break the tests.
2971 # Regarding paths:
2972 # - We have RTPATH_BIG_MAX (64K)
2973 # - MSDN says 32K for CreateFileW()
2974 # - On Windows, each path component must not be longer than MAX_PATH (260), see
2975 # https://docs.microsoft.com/en-us/windows/win32/fileio/filesystem-functionality-comparison#limits
2976 #
2977 # Old(er) Windows OSes tend to crash in cmd.exe, so skip this on these OSes.
2978 if self.oTstDrv.fpApiVer >= 6.1 \
2979 and oTestVm.sKind not in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
2980 sEndMarker = '--end-marker';
2981 if oTestVm.isWindows() \
2982 or oTestVm.isOS2():
2983 sCmd = sShell;
2984 else:
2985 sCmd = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'echo');
2986
2987 for _ in xrange(0, 16):
2988 if oTestVm.isWindows() \
2989 or oTestVm.isOS2():
2990 asArgs = [ sShell, sShellOpt, "echo" ];
2991 else:
2992 asArgs = [ sCmd ];
2993
2994 # Append a random number of arguments with random length.
2995 for _ in xrange(0, self.oTestFiles.oRandom.randrange(1, 64)):
2996 asArgs.append(''.join(random.choice(string.ascii_lowercase)
2997 for _ in range(self.oTestFiles.oRandom.randrange(1, 196))));
2998
2999 asArgs.append(sEndMarker);
3000
3001 reporter.log2('asArgs=%s (%d args), type=%s' % (limitString(asArgs), len(asArgs), type(asArgs)));
3002
3003 ## @todo Check limits; on Ubuntu with 256KB IPRT returns VERR_NOT_IMPLEMENTED.
3004 # Use a higher timeout (15 min) than usual for these long checks.
3005 atExec.append([ tdTestExec(sCmd, asArgs,
3006 afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut,
3007 vboxcon.ProcessCreateFlag_WaitForStdErr ],
3008 timeoutMS = 15 * 60 * 1000),
3009 tdTestResultExec(fRc = True) ]);
3010
3011 # Build up the final test array for the first batch.
3012 atTests = atInvalid + atExec;
3013
3014 #
3015 # First batch: One session per guest process.
3016 #
3017 reporter.log('One session per guest process ...');
3018 fRc = True;
3019 for (i, tTest) in enumerate(atTests):
3020 oCurTest = tTest[0] # type: tdTestExec
3021 oCurRes = tTest[1] # type: tdTestResultExec
3022 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3023 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlExec: Test #%d' % (i,));
3024 if fRc2 is not True:
3025 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3026 break;
3027 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession) and fRc;
3028 fRc = oCurTest.closeSession() and fRc;
3029
3030 reporter.log('Execution of all tests done, checking for stale sessions');
3031
3032 # No sessions left?
3033 try:
3034 aSessions = self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions');
3035 except:
3036 fRc = reporter.errorXcpt();
3037 else:
3038 cSessions = len(aSessions);
3039 if cSessions != 0:
3040 fRc = reporter.error('Found %d stale session(s), expected 0:' % (cSessions,));
3041 for (i, aSession) in enumerate(aSessions):
3042 try: reporter.log(' Stale session #%d ("%s")' % (aSession.id, aSession.name));
3043 except: reporter.errorXcpt();
3044
3045 if fRc is not True:
3046 return (fRc, oTxsSession);
3047
3048 reporter.log('Now using one guest session for all tests ...');
3049
3050 #
3051 # Second batch: One session for *all* guest processes.
3052 #
3053
3054 # Create session.
3055 reporter.log('Creating session for all tests ...');
3056 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
3057 try:
3058 oGuest = oSession.o.console.guest;
3059 oCurGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain,
3060 'testGuestCtrlExec: One session for all tests');
3061 except:
3062 return (reporter.errorXcpt(), oTxsSession);
3063
3064 try:
3065 eWaitResult = oCurGuestSession.waitForArray(aeWaitFor, 30 * 1000);
3066 except:
3067 fRc = reporter.errorXcpt('Waiting for guest session to start failed:');
3068 else:
3069 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3070 fRc = reporter.error('Session did not start successfully, returned wait result: %d' % (eWaitResult,));
3071 else:
3072 reporter.log('Session successfully started');
3073
3074 # Do the tests within this session.
3075 for (i, tTest) in enumerate(atTests):
3076 oCurTest = tTest[0] # type: tdTestExec
3077 oCurRes = tTest[1] # type: tdTestResultExec
3078
3079 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3080 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
3081 if fRc is False:
3082 break;
3083
3084 # Close the session.
3085 reporter.log2('Closing guest session ...');
3086 try:
3087 oCurGuestSession.close();
3088 oCurGuestSession = None;
3089 except:
3090 fRc = reporter.errorXcpt('Closing guest session failed:');
3091
3092 # No sessions left?
3093 reporter.log('Execution of all tests done, checking for stale sessions again');
3094 try: cSessions = len(self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions'));
3095 except: fRc = reporter.errorXcpt();
3096 else:
3097 if cSessions != 0:
3098 fRc = reporter.error('Found %d stale session(s), expected 0' % (cSessions,));
3099 return (fRc, oTxsSession);
3100
3101 def threadForTestGuestCtrlSessionReboot(self, oGuestProcess):
3102 """
3103 Thread routine which waits for the stale guest process getting terminated (or some error)
3104 while the main test routine reboots the guest. It then compares the expected guest process result
3105 and logs an error if appropriate.
3106 """
3107 reporter.log('Waiting for process to get terminated at reboot ...');
3108 try:
3109 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate ], 5 * 60 * 1000);
3110 except:
3111 return reporter.errorXcpt('waitForArray failed');
3112 try:
3113 eStatus = oGuestProcess.status
3114 except:
3115 return reporter.errorXcpt('failed to get status (wait result %d)' % (eWaitResult,));
3116
3117 if eWaitResult == vboxcon.ProcessWaitResult_Terminate and eStatus == vboxcon.ProcessStatus_Down:
3118 reporter.log('Stale process was correctly terminated (status: down)');
3119 return True;
3120
3121 return reporter.error('Process wait across reboot failed: eWaitResult=%d, expected %d; eStatus=%d, expected %d'
3122 % (eWaitResult, vboxcon.ProcessWaitResult_Terminate, eStatus, vboxcon.ProcessStatus_Down,));
3123
3124 def testGuestCtrlSessionReboot(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3125 """
3126 Tests guest object notifications when a guest gets rebooted / shutdown.
3127
3128 These notifications gets sent from the guest sessions in order to make API clients
3129 aware of guest session changes.
3130
3131 To test that we create a stale guest process and trigger a reboot of the guest.
3132 """
3133
3134 ## @todo backport fixes to 6.0 and maybe 5.2
3135 if self.oTstDrv.fpApiVer <= 6.0:
3136 reporter.log('Skipping: Required fixes not yet backported!');
3137 return None;
3138
3139 # Use credential defaults.
3140 oCreds = tdCtxCreds();
3141 oCreds.applyDefaultsIfNotSet(oTestVm);
3142
3143 fRc = True;
3144
3145 #
3146 # Start a session.
3147 #
3148 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
3149 try:
3150 oGuest = oSession.o.console.guest;
3151 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionReboot");
3152 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
3153 except:
3154 return (reporter.errorXcpt(), oTxsSession);
3155
3156 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
3157 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3158 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
3159 reporter.log('Session successfully started');
3160
3161 #
3162 # Create a process.
3163 #
3164 sImage = self.oTstDrv.getGuestSystemShell(oTestVm);
3165 asArgs = [ sImage, ];
3166 aEnv = [];
3167 afFlags = [];
3168 try:
3169 oGuestProcess = oGuestSession.processCreate(sImage,
3170 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], aEnv, afFlags,
3171 30 * 1000);
3172 except:
3173 fRc = reporter.error('Failed to start shell process (%s)' % (sImage,));
3174 else:
3175 try:
3176 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3177 except:
3178 fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
3179 else:
3180 # Check the result and state:
3181 try: eStatus = oGuestProcess.status;
3182 except: fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
3183 else:
3184 reporter.log2('Starting process wait result returned: %d; Process status is: %d' % (eWaitResult, eStatus,));
3185 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3186 fRc = reporter.error('wait for ProcessWaitForFlag_Start failed: %d, expected %d (Start)'
3187 % (eWaitResult, vboxcon.ProcessWaitResult_Start,));
3188 elif eStatus != vboxcon.ProcessStatus_Started:
3189 fRc = reporter.error('Unexpected process status after startup: %d, wanted %d (Started)'
3190 % (eStatus, vboxcon.ProcessStatus_Started,));
3191 else:
3192 # Create a thread that waits on the process to terminate
3193 reporter.log('Creating reboot thread ...');
3194 oThreadReboot = threading.Thread(target = self.threadForTestGuestCtrlSessionReboot,
3195 args = (oGuestProcess,),
3196 name = ('threadForTestGuestCtrlSessionReboot'));
3197 oThreadReboot.setDaemon(True);
3198 oThreadReboot.start();
3199
3200 # Not sure why this fudge is needed...
3201 reporter.log('5 second wait fudge before triggering reboot ...');
3202 self.oTstDrv.sleep(5);
3203
3204 # Do the reboot.
3205 reporter.log('Rebooting guest and reconnecting TXS ...');
3206 (oSession, oTxsSession) = self.oTstDrv.txsRebootAndReconnectViaTcp(oSession, oTxsSession,
3207 cMsTimeout = 3 * 60000);
3208 if not oSession or not oTxsSession:
3209 try: oGuestProcess.terminate();
3210 except: reporter.logXcpt();
3211 fRc = False;
3212
3213 reporter.log('Waiting for thread to finish ...');
3214 oThreadReboot.join();
3215
3216 #
3217 # Try make sure we don't leave with a stale process on failure.
3218 #
3219 try: oGuestProcess.terminate();
3220 except: reporter.logXcpt();
3221
3222 #
3223 # Close the session.
3224 #
3225 reporter.log2('Closing guest session ...');
3226 try:
3227 oGuestSession.close();
3228 except:
3229 fRc = reporter.errorXcpt();
3230
3231 return (fRc, oTxsSession);
3232
3233 def testGuestCtrlExecTimeout(self, oSession, oTxsSession, oTestVm):
3234 """
3235 Tests handling of timeouts of started guest processes.
3236 """
3237
3238 sShell = self.oTstDrv.getGuestSystemShell(oTestVm);
3239
3240 # Use credential defaults.
3241 oCreds = tdCtxCreds();
3242 oCreds.applyDefaultsIfNotSet(oTestVm);
3243
3244 #
3245 # Create a session.
3246 #
3247 try:
3248 oGuest = oSession.o.console.guest;
3249 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlExecTimeout");
3250 eWaitResult = oGuestSession.waitForArray([ vboxcon.GuestSessionWaitForFlag_Start, ], 30 * 1000);
3251 except:
3252 return (reporter.errorXcpt(), oTxsSession);
3253
3254 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
3255 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3256 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
3257 reporter.log('Session successfully started');
3258
3259 #
3260 # Create a process which never terminates and should timeout when
3261 # waiting for termination.
3262 #
3263 fRc = True;
3264 try:
3265 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
3266 [], [], 30 * 1000);
3267 except:
3268 fRc = reporter.errorXcpt();
3269 else:
3270 reporter.log('Waiting for process 1 being started ...');
3271 try:
3272 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3273 except:
3274 fRc = reporter.errorXcpt();
3275 else:
3276 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3277 fRc = reporter.error('Waiting for process 1 to start failed, got status %d' % (eWaitResult,));
3278 else:
3279 for msWait in (1, 32, 2000,):
3280 reporter.log('Waiting for process 1 to time out within %sms ...' % (msWait,));
3281 try:
3282 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], msWait);
3283 except:
3284 fRc = reporter.errorXcpt();
3285 break;
3286 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
3287 fRc = reporter.error('Waiting for process 1 did not time out in %sms as expected: %d'
3288 % (msWait, eWaitResult,));
3289 break;
3290 reporter.log('Waiting for process 1 timed out in %u ms, good' % (msWait,));
3291
3292 try:
3293 oCurProcess.terminate();
3294 except:
3295 reporter.errorXcpt();
3296 oCurProcess = None;
3297
3298 #
3299 # Create another process that doesn't terminate, but which will be killed by VBoxService
3300 # because it ran out of execution time (3 seconds).
3301 #
3302 try:
3303 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
3304 [], [], 3 * 1000);
3305 except:
3306 fRc = reporter.errorXcpt();
3307 else:
3308 reporter.log('Waiting for process 2 being started ...');
3309 try:
3310 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3311 except:
3312 fRc = reporter.errorXcpt();
3313 else:
3314 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3315 fRc = reporter.error('Waiting for process 2 to start failed, got status %d' % (eWaitResult,));
3316 else:
3317 reporter.log('Waiting for process 2 to get killed for running out of execution time ...');
3318 try:
3319 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 15 * 1000);
3320 except:
3321 fRc = reporter.errorXcpt();
3322 else:
3323 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
3324 fRc = reporter.error('Waiting for process 2 did not time out when it should, got wait result %d'
3325 % (eWaitResult,));
3326 else:
3327 reporter.log('Waiting for process 2 did not time out, good: %s' % (eWaitResult,));
3328 try:
3329 eStatus = oCurProcess.status;
3330 except:
3331 fRc = reporter.errorXcpt();
3332 else:
3333 if eStatus != vboxcon.ProcessStatus_TimedOutKilled:
3334 fRc = reporter.error('Status of process 2 wrong; excepted %d, got %d'
3335 % (vboxcon.ProcessStatus_TimedOutKilled, eStatus));
3336 else:
3337 reporter.log('Status of process 2 is TimedOutKilled (%d) is it should be.'
3338 % (vboxcon.ProcessStatus_TimedOutKilled,));
3339 try:
3340 oCurProcess.terminate();
3341 except:
3342 reporter.logXcpt();
3343 oCurProcess = None;
3344
3345 #
3346 # Clean up the session.
3347 #
3348 try:
3349 oGuestSession.close();
3350 except:
3351 fRc = reporter.errorXcpt();
3352
3353 return (fRc, oTxsSession);
3354
3355 def testGuestCtrlDirCreate(self, oSession, oTxsSession, oTestVm):
3356 """
3357 Tests creation of guest directories.
3358 """
3359
3360 sScratch = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'testGuestCtrlDirCreate');
3361
3362 atTests = [
3363 # Invalid stuff.
3364 [ tdTestDirCreate(sDirectory = '' ), tdTestResultFailure() ],
3365 # More unusual stuff.
3366 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '.') ), tdTestResultFailure() ],
3367 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '..') ), tdTestResultFailure() ],
3368 [ tdTestDirCreate(sDirectory = '..' ), tdTestResultFailure() ],
3369 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
3370 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
3371 [ tdTestDirCreate(sDirectory = '/' ), tdTestResultFailure() ],
3372 [ tdTestDirCreate(sDirectory = '/..' ), tdTestResultFailure() ],
3373 [ tdTestDirCreate(sDirectory = '/../' ), tdTestResultFailure() ],
3374 ];
3375 if oTestVm.isWindows() or oTestVm.isOS2():
3376 atTests.extend([
3377 [ tdTestDirCreate(sDirectory = 'C:\\' ), tdTestResultFailure() ],
3378 [ tdTestDirCreate(sDirectory = 'C:\\..' ), tdTestResultFailure() ],
3379 [ tdTestDirCreate(sDirectory = 'C:\\..\\' ), tdTestResultFailure() ],
3380 [ tdTestDirCreate(sDirectory = 'C:/' ), tdTestResultFailure() ],
3381 [ tdTestDirCreate(sDirectory = 'C:/.' ), tdTestResultFailure() ],
3382 [ tdTestDirCreate(sDirectory = 'C:/./' ), tdTestResultFailure() ],
3383 [ tdTestDirCreate(sDirectory = 'C:/..' ), tdTestResultFailure() ],
3384 [ tdTestDirCreate(sDirectory = 'C:/../' ), tdTestResultFailure() ],
3385 [ tdTestDirCreate(sDirectory = '\\\\uncrulez\\foo' ), tdTestResultFailure() ],
3386 ]);
3387 atTests.extend([
3388 # Existing directories and files.
3389 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemDir(oTestVm) ), tdTestResultFailure() ],
3390 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemShell(oTestVm) ), tdTestResultFailure() ],
3391 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemFileForReading(oTestVm) ), tdTestResultFailure() ],
3392 # Creating directories.
3393 [ tdTestDirCreate(sDirectory = sScratch ), tdTestResultSuccess() ],
3394 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
3395 afFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
3396 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
3397 afFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
3398 # Try format strings as directories.
3399 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo%sbar%sbaz%d' )), tdTestResultSuccess() ],
3400 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, '%f%%boo%%bar%RI32' )), tdTestResultSuccess() ],
3401 # Long random names.
3402 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(36, 28))),
3403 tdTestResultSuccess() ],
3404 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(140, 116))),
3405 tdTestResultSuccess() ],
3406 # Too long names. ASSUMES a guests has a 255 filename length limitation.
3407 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
3408 tdTestResultFailure() ],
3409 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
3410 tdTestResultFailure() ],
3411 # Missing directory in path.
3412 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo1', 'bar') ), tdTestResultFailure() ],
3413 ]);
3414
3415 fRc = True;
3416 for (i, tTest) in enumerate(atTests):
3417 oCurTest = tTest[0] # type: tdTestDirCreate
3418 oCurRes = tTest[1] # type: tdTestResult
3419 reporter.log('Testing #%d, sDirectory="%s" ...' % (i, limitString(oCurTest.sDirectory)));
3420
3421 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3422 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreate: Test #%d' % (i,));
3423 if fRc is False:
3424 return reporter.error('Test #%d failed: Could not create session' % (i,));
3425
3426 fRc = self.gctrlCreateDir(oCurTest, oCurRes, oCurGuestSession);
3427
3428 fRc = oCurTest.closeSession() and fRc;
3429 if fRc is False:
3430 fRc = reporter.error('Test #%d failed' % (i,));
3431
3432 return (fRc, oTxsSession);
3433
3434 def testGuestCtrlDirCreateTemp(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3435 """
3436 Tests creation of temporary directories.
3437 """
3438
3439 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3440 atTests = [
3441 # Invalid stuff (template must have one or more trailin 'X'es (upper case only), or a cluster of three or more).
3442 [ tdTestDirCreateTemp(sDirectory = ''), tdTestResultFailure() ],
3443 [ tdTestDirCreateTemp(sDirectory = sSystemDir, fMode = 1234), tdTestResultFailure() ],
3444 [ tdTestDirCreateTemp(sTemplate = 'xXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3445 [ tdTestDirCreateTemp(sTemplate = 'xxx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3446 [ tdTestDirCreateTemp(sTemplate = 'XXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3447 [ tdTestDirCreateTemp(sTemplate = 'bar', sDirectory = 'whatever', fMode = 0o700), tdTestResultFailure() ],
3448 [ tdTestDirCreateTemp(sTemplate = 'foo', sDirectory = 'it is not used', fMode = 0o700), tdTestResultFailure() ],
3449 [ tdTestDirCreateTemp(sTemplate = 'X,so', sDirectory = 'pointless test', fMode = 0o700), tdTestResultFailure() ],
3450 # Non-existing stuff.
3451 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX',
3452 sDirectory = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'non', 'existing')),
3453 tdTestResultFailure() ],
3454 # Working stuff:
3455 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3456 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3457 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3458 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3459 tdTestResultFailure() ],
3460 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3461 tdTestResultFailure() ],
3462 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3463 tdTestResultFailure() ],
3464 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3465 tdTestResultFailure() ],
3466 ## @todo test fSecure and pass weird fMode values once these parameters are implemented in the API.
3467 ];
3468
3469 fRc = True;
3470 for (i, tTest) in enumerate(atTests):
3471 oCurTest = tTest[0] # type: tdTestDirCreateTemp
3472 oCurRes = tTest[1] # type: tdTestResult
3473 reporter.log('Testing #%d, sTemplate="%s", fMode=%#o, path="%s", secure="%s" ...' %
3474 (i, oCurTest.sTemplate, oCurTest.fMode, oCurTest.sDirectory, oCurTest.fSecure));
3475
3476 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3477 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreateTemp: Test #%d' % (i,));
3478 if fRc is False:
3479 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3480 break;
3481
3482 sDirTemp = '';
3483 try:
3484 sDirTemp = oCurGuestSession.directoryCreateTemp(oCurTest.sTemplate, oCurTest.fMode,
3485 oCurTest.sDirectory, oCurTest.fSecure);
3486 except:
3487 if oCurRes.fRc is True:
3488 fRc = reporter.errorXcpt('Creating temp directory "%s" failed:' % (oCurTest.sDirectory,));
3489 else:
3490 reporter.logXcpt('Creating temp directory "%s" failed expectedly, skipping:' % (oCurTest.sDirectory,));
3491 else:
3492 reporter.log2('Temporary directory is: "%s"' % (limitString(sDirTemp),));
3493 if not sDirTemp:
3494 fRc = reporter.error('Resulting directory is empty!');
3495 else:
3496 ## @todo This does not work for some unknown reason.
3497 #try:
3498 # if self.oTstDrv.fpApiVer >= 5.0:
3499 # fExists = oCurGuestSession.directoryExists(sDirTemp, False);
3500 # else:
3501 # fExists = oCurGuestSession.directoryExists(sDirTemp);
3502 #except:
3503 # fRc = reporter.errorXcpt('sDirTemp=%s' % (sDirTemp,));
3504 #else:
3505 # if fExists is not True:
3506 # fRc = reporter.error('Test #%d failed: Temporary directory "%s" does not exists (%s)'
3507 # % (i, sDirTemp, fExists));
3508 try:
3509 oFsObjInfo = oCurGuestSession.fsObjQueryInfo(sDirTemp, False);
3510 eType = oFsObjInfo.type;
3511 except:
3512 fRc = reporter.errorXcpt('sDirTemp="%s"' % (sDirTemp,));
3513 else:
3514 reporter.log2('%s: eType=%s (dir=%d)' % (limitString(sDirTemp), eType, vboxcon.FsObjType_Directory,));
3515 if eType != vboxcon.FsObjType_Directory:
3516 fRc = reporter.error('Temporary directory "%s" not created as a directory: eType=%d'
3517 % (sDirTemp, eType));
3518 fRc = oCurTest.closeSession() and fRc;
3519 return (fRc, oTxsSession);
3520
3521 def testGuestCtrlDirRead(self, oSession, oTxsSession, oTestVm):
3522 """
3523 Tests opening and reading (enumerating) guest directories.
3524 """
3525
3526 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3527 atTests = [
3528 # Invalid stuff.
3529 [ tdTestDirRead(sDirectory = ''), tdTestResultDirRead() ],
3530 [ tdTestDirRead(sDirectory = sSystemDir, afFlags = [ 1234 ]), tdTestResultDirRead() ],
3531 [ tdTestDirRead(sDirectory = sSystemDir, sFilter = '*.foo'), tdTestResultDirRead() ],
3532 # Non-existing stuff.
3533 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'really-no-such-subdir')), tdTestResultDirRead() ],
3534 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'non', 'existing')), tdTestResultDirRead() ],
3535 ];
3536
3537 if oTestVm.isWindows() or oTestVm.isOS2():
3538 atTests.extend([
3539 # More unusual stuff.
3540 [ tdTestDirRead(sDirectory = 'z:\\'), tdTestResultDirRead() ],
3541 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
3542 ]);
3543
3544 # Read the system directory (ASSUMES at least 5 files in it):
3545 # Windows 7+ has inaccessible system32/com/dmp directory that screws up this test, so skip it on windows:
3546 if not oTestVm.isWindows():
3547 atTests.append([ tdTestDirRead(sDirectory = sSystemDir),
3548 tdTestResultDirRead(fRc = True, cFiles = -5, cDirs = None) ]);
3549 ## @todo trailing slash
3550
3551 # Read from the test file set.
3552 atTests.extend([
3553 [ tdTestDirRead(sDirectory = self.oTestFiles.oEmptyDir.sPath),
3554 tdTestResultDirRead(fRc = True, cFiles = 0, cDirs = 0, cOthers = 0) ],
3555 [ tdTestDirRead(sDirectory = self.oTestFiles.oManyDir.sPath),
3556 tdTestResultDirRead(fRc = True, cFiles = len(self.oTestFiles.oManyDir.aoChildren), cDirs = 0, cOthers = 0) ],
3557 [ tdTestDirRead(sDirectory = self.oTestFiles.oTreeDir.sPath),
3558 tdTestResultDirRead(fRc = True, cFiles = self.oTestFiles.cTreeFiles, cDirs = self.oTestFiles.cTreeDirs,
3559 cOthers = self.oTestFiles.cTreeOthers) ],
3560 ]);
3561
3562
3563 fRc = True;
3564 for (i, tTest) in enumerate(atTests):
3565 oCurTest = tTest[0] # type: tdTestExec
3566 oCurRes = tTest[1] # type: tdTestResultDirRead
3567
3568 reporter.log('Testing #%d, dir="%s" ...' % (i, oCurTest.sDirectory));
3569 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3570 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: Test #%d' % (i,));
3571 if fRc is not True:
3572 break;
3573 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc);
3574 fRc = oCurTest.closeSession() and fRc;
3575
3576 reporter.log2('Test #%d: Returned %d directories, %d files total' % (i, cDirs, cFiles));
3577 if fRc2 is oCurRes.fRc:
3578 if fRc2 is True:
3579 if oCurRes.cFiles is None:
3580 pass; # ignore
3581 elif oCurRes.cFiles >= 0 and cFiles != oCurRes.cFiles:
3582 fRc = reporter.error('Test #%d failed: Got %d files, expected %d' % (i, cFiles, oCurRes.cFiles));
3583 elif oCurRes.cFiles < 0 and cFiles < -oCurRes.cFiles:
3584 fRc = reporter.error('Test #%d failed: Got %d files, expected at least %d'
3585 % (i, cFiles, -oCurRes.cFiles));
3586 if oCurRes.cDirs is None:
3587 pass; # ignore
3588 elif oCurRes.cDirs >= 0 and cDirs != oCurRes.cDirs:
3589 fRc = reporter.error('Test #%d failed: Got %d directories, expected %d' % (i, cDirs, oCurRes.cDirs));
3590 elif oCurRes.cDirs < 0 and cDirs < -oCurRes.cDirs:
3591 fRc = reporter.error('Test #%d failed: Got %d directories, expected at least %d'
3592 % (i, cDirs, -oCurRes.cDirs));
3593 if oCurRes.cOthers is None:
3594 pass; # ignore
3595 elif oCurRes.cOthers >= 0 and cOthers != oCurRes.cOthers:
3596 fRc = reporter.error('Test #%d failed: Got %d other types, expected %d' % (i, cOthers, oCurRes.cOthers));
3597 elif oCurRes.cOthers < 0 and cOthers < -oCurRes.cOthers:
3598 fRc = reporter.error('Test #%d failed: Got %d other types, expected at least %d'
3599 % (i, cOthers, -oCurRes.cOthers));
3600
3601 else:
3602 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3603
3604
3605 #
3606 # Go over a few directories in the test file set and compare names,
3607 # types and sizes rather than just the counts like we did above.
3608 #
3609 if fRc is True:
3610 oCurTest = tdTestDirRead();
3611 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3612 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: gctrlReadDirTree2');
3613 if fRc is True:
3614 for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir):
3615 reporter.log('Checking "%s" ...' % (oDir.sPath,));
3616 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir) and fRc;
3617 fRc = oCurTest.closeSession() and fRc;
3618
3619 return (fRc, oTxsSession);
3620
3621
3622 def testGuestCtrlFileRemove(self, oSession, oTxsSession, oTestVm):
3623 """
3624 Tests removing guest files.
3625 """
3626
3627 #
3628 # Create a directory with a few files in it using TXS that we'll use for the initial tests.
3629 #
3630 asTestDirs = [
3631 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1'), # [0]
3632 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1', 'subdir-1'), # [1]
3633 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1', 'subdir-1', 'subsubdir-1'), # [2]
3634 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2'), # [3]
3635 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2', 'subdir-2'), # [4]
3636 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2', 'subdir-2', 'subsbudir-2'), # [5]
3637 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-3'), # [6]
3638 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-4'), # [7]
3639 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-5'), # [8]
3640 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-5', 'subdir-5'), # [9]
3641 ]
3642 asTestFiles = [
3643 oTestVm.pathJoin(asTestDirs[0], 'file-0'), # [0]
3644 oTestVm.pathJoin(asTestDirs[0], 'file-1'), # [1]
3645 oTestVm.pathJoin(asTestDirs[0], 'file-2'), # [2]
3646 oTestVm.pathJoin(asTestDirs[1], 'file-3'), # [3] - subdir-1
3647 oTestVm.pathJoin(asTestDirs[1], 'file-4'), # [4] - subdir-1
3648 oTestVm.pathJoin(asTestDirs[2], 'file-5'), # [5] - subsubdir-1
3649 oTestVm.pathJoin(asTestDirs[3], 'file-6'), # [6] - rmtestdir-2
3650 oTestVm.pathJoin(asTestDirs[4], 'file-7'), # [7] - subdir-2
3651 oTestVm.pathJoin(asTestDirs[5], 'file-8'), # [8] - subsubdir-2
3652 ];
3653 for sDir in asTestDirs:
3654 if oTxsSession.syncMkDir(sDir, 0o777) is not True:
3655 return reporter.error('Failed to create test dir "%s"!' % (sDir,));
3656 for sFile in asTestFiles:
3657 if oTxsSession.syncUploadString(sFile, sFile, 0o666) is not True:
3658 return reporter.error('Failed to create test file "%s"!' % (sFile,));
3659
3660 #
3661 # Tear down the directories and files.
3662 #
3663 aoTests = [
3664 # Negative tests first:
3665 tdTestRemoveFile(asTestDirs[0], fRcExpect = False),
3666 tdTestRemoveDir(asTestDirs[0], fRcExpect = False),
3667 tdTestRemoveDir(asTestFiles[0], fRcExpect = False),
3668 tdTestRemoveFile(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-file'), fRcExpect = False),
3669 tdTestRemoveDir(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir'), fRcExpect = False),
3670 tdTestRemoveFile(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir', 'no-file'), fRcExpect = False),
3671 tdTestRemoveDir(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir', 'no-subdir'), fRcExpect = False),
3672 tdTestRemoveTree(asTestDirs[0], afFlags = [], fRcExpect = False), # Only removes empty dirs, this isn't empty.
3673 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_None,], fRcExpect = False), # ditto
3674 # Empty paths:
3675 tdTestRemoveFile('', fRcExpect = False),
3676 tdTestRemoveDir('', fRcExpect = False),
3677 tdTestRemoveTree('', fRcExpect = False),
3678 # Now actually remove stuff:
3679 tdTestRemoveDir(asTestDirs[7], fRcExpect = True),
3680 tdTestRemoveFile(asTestDirs[6], fRcExpect = False),
3681 tdTestRemoveDir(asTestDirs[6], fRcExpect = True),
3682 tdTestRemoveFile(asTestFiles[0], fRcExpect = True),
3683 tdTestRemoveFile(asTestFiles[0], fRcExpect = False),
3684 # 17:
3685 tdTestRemoveTree(asTestDirs[8], fRcExpect = True), # Removes empty subdirs and leaves the dir itself.
3686 tdTestRemoveDir(asTestDirs[8], fRcExpect = True),
3687 tdTestRemoveTree(asTestDirs[3], fRcExpect = False), # Have subdirs & files,
3688 tdTestRemoveTree(asTestDirs[3], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,], fRcExpect = True),
3689 tdTestRemoveDir(asTestDirs[3], fRcExpect = True),
3690 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,], fRcExpect = True),
3691 # No error if already delete (RTDirRemoveRecursive artifact).
3692 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,], fRcExpect = True),
3693 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,],
3694 fNotExist = True, fRcExpect = True),
3695 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_None,], fNotExist = True, fRcExpect = True),
3696 ];
3697
3698 #
3699 # Execution loop
3700 #
3701 fRc = True;
3702 for (i, oTest) in enumerate(aoTests): # int, tdTestRemoveBase
3703 reporter.log('Testing #%d, path="%s" %s ...' % (i, oTest.sPath, oTest.__class__.__name__));
3704 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
3705 fRc, _ = oTest.createSession('testGuestCtrlFileRemove: Test #%d' % (i,));
3706 if fRc is False:
3707 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3708 break;
3709 fRc = oTest.execute(self) and fRc;
3710 fRc = oTest.closeSession() and fRc;
3711
3712 if fRc is True:
3713 oCurTest = tdTestDirRead();
3714 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3715 fRc, oCurGuestSession = oCurTest.createSession('remove final');
3716 if fRc is True:
3717
3718 #
3719 # Delete all the files in the many subdir of the test set.
3720 #
3721 reporter.log('Deleting the file in "%s" ...' % (self.oTestFiles.oManyDir.sPath,));
3722 for oFile in self.oTestFiles.oManyDir.aoChildren:
3723 reporter.log2('"%s"' % (limitString(oFile.sPath),));
3724 try:
3725 if self.oTstDrv.fpApiVer >= 5.0:
3726 oCurGuestSession.fsObjRemove(oFile.sPath);
3727 else:
3728 oCurGuestSession.fileRemove(oFile.sPath);
3729 except:
3730 fRc = reporter.errorXcpt('Removing "%s" failed' % (oFile.sPath,));
3731
3732 # Remove the directory itself to verify that we've removed all the files in it:
3733 reporter.log('Removing the directory "%s" ...' % (self.oTestFiles.oManyDir.sPath,));
3734 try:
3735 oCurGuestSession.directoryRemove(self.oTestFiles.oManyDir.sPath);
3736 except:
3737 fRc = reporter.errorXcpt('Removing directory "%s" failed' % (self.oTestFiles.oManyDir.sPath,));
3738
3739 #
3740 # Recursively delete the entire test file tree from the root up.
3741 #
3742 # Note! On unix we cannot delete the root dir itself since it is residing
3743 # in /var/tmp where only the owner may delete it. Root is the owner.
3744 #
3745 if oTestVm.isWindows() or oTestVm.isOS2():
3746 afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,];
3747 else:
3748 afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,];
3749 try:
3750 oProgress = oCurGuestSession.directoryRemoveRecursive(self.oTestFiles.oRoot.sPath, afFlags);
3751 except:
3752 fRc = reporter.errorXcpt('Removing tree "%s" failed' % (self.oTestFiles.oRoot.sPath,));
3753 else:
3754 oWrappedProgress = vboxwrappers.ProgressWrapper(oProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv,
3755 "remove-tree-root: %s" % (self.oTestFiles.oRoot.sPath,));
3756 reporter.log2('waiting ...')
3757 oWrappedProgress.wait();
3758 reporter.log2('isSuccess=%s' % (oWrappedProgress.isSuccess(),));
3759 if not oWrappedProgress.isSuccess():
3760 fRc = oWrappedProgress.logResult();
3761
3762 fRc = oCurTest.closeSession() and fRc;
3763
3764 return (fRc, oTxsSession);
3765
3766
3767 def testGuestCtrlFileStat(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3768 """
3769 Tests querying file information through stat.
3770 """
3771
3772 # Basic stuff, existing stuff.
3773 aoTests = [
3774 tdTestSessionEx([
3775 tdStepStatDir('.'),
3776 tdStepStatDir('..'),
3777 tdStepStatDir(self.oTstDrv.getGuestTempDir(oTestVm)),
3778 tdStepStatDir(self.oTstDrv.getGuestSystemDir(oTestVm)),
3779 tdStepStatDirEx(self.oTestFiles.oRoot),
3780 tdStepStatDirEx(self.oTestFiles.oEmptyDir),
3781 tdStepStatDirEx(self.oTestFiles.oTreeDir),
3782 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3783 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3784 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3785 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3786 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3787 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3788 tdStepStatFile(self.oTstDrv.getGuestSystemFileForReading(oTestVm)),
3789 tdStepStatFile(self.oTstDrv.getGuestSystemShell(oTestVm)),
3790 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3791 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3792 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3793 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3794 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3795 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3796 ]),
3797 ];
3798
3799 # None existing stuff.
3800 sSysDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3801 sSep = oTestVm.pathSep();
3802 aoTests += [
3803 tdTestSessionEx([
3804 tdStepStatFileNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory')),
3805 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory') + sSep),
3806 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', '.')),
3807 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory')),
3808 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory') + sSep),
3809 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory', '.')),
3810 #tdStepStatPathNotFound('N:\\'), # ASSUMES nothing mounted on N:!
3811 #tdStepStatPathNotFound('\\\\NoSuchUncServerName\\NoSuchShare'),
3812 ]),
3813 ];
3814 # Invalid parameter check.
3815 aoTests += [ tdTestSessionEx([ tdStepStat('', vbox.ComError.E_INVALIDARG), ]), ];
3816
3817 #
3818 # Execute the tests.
3819 #
3820 fRc, oTxsSession = tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession,
3821 oTestVm, 'FsStat');
3822 #
3823 # Test the full test file set.
3824 #
3825 if self.oTstDrv.fpApiVer < 5.0:
3826 return (fRc, oTxsSession);
3827
3828 oTest = tdTestGuestCtrlBase();
3829 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
3830 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet');
3831 if fRc2 is not True:
3832 return (False, oTxsSession);
3833
3834 for sPath in self.oTestFiles.dPaths:
3835 oFsObj = self.oTestFiles.dPaths[sPath];
3836 reporter.log2('testGuestCtrlFileStat: %s sPath=%s'
3837 % ('file' if isinstance(oFsObj, testfileset.TestFile) else 'dir ', limitString(oFsObj.sPath),));
3838
3839 # Query the information:
3840 try:
3841 oFsInfo = oGuestSession.fsObjQueryInfo(oFsObj.sPath, False);
3842 except:
3843 fRc = reporter.errorXcpt('sPath=%s type=%s: fsObjQueryInfo trouble!' % (oFsObj.sPath, type(oFsObj),));
3844 continue;
3845 if oFsInfo is None:
3846 fRc = reporter.error('sPath=%s type=%s: No info object returned!' % (oFsObj.sPath, type(oFsObj),));
3847 continue;
3848
3849 # Check attributes:
3850 try:
3851 eType = oFsInfo.type;
3852 cbObject = oFsInfo.objectSize;
3853 except:
3854 fRc = reporter.errorXcpt('sPath=%s type=%s: attribute access trouble!' % (oFsObj.sPath, type(oFsObj),));
3855 continue;
3856
3857 if isinstance(oFsObj, testfileset.TestFile):
3858 if eType != vboxcon.FsObjType_File:
3859 fRc = reporter.error('sPath=%s type=file: eType=%s, expected %s!'
3860 % (oFsObj.sPath, eType, vboxcon.FsObjType_File));
3861 if cbObject != oFsObj.cbContent:
3862 fRc = reporter.error('sPath=%s type=file: cbObject=%s, expected %s!'
3863 % (oFsObj.sPath, cbObject, oFsObj.cbContent));
3864 fFileExists = True;
3865 fDirExists = False;
3866 elif isinstance(oFsObj, testfileset.TestDir):
3867 if eType != vboxcon.FsObjType_Directory:
3868 fRc = reporter.error('sPath=%s type=dir: eType=%s, expected %s!'
3869 % (oFsObj.sPath, eType, vboxcon.FsObjType_Directory));
3870 fFileExists = False;
3871 fDirExists = True;
3872 else:
3873 fRc = reporter.error('sPath=%s type=%s: Unexpected oFsObj type!' % (oFsObj.sPath, type(oFsObj),));
3874 continue;
3875
3876 # Check the directoryExists and fileExists results too.
3877 try:
3878 fExistsResult = oGuestSession.fileExists(oFsObj.sPath, False);
3879 except:
3880 fRc = reporter.errorXcpt('sPath=%s type=%s: fileExists trouble!' % (oFsObj.sPath, type(oFsObj),));
3881 else:
3882 if fExistsResult != fFileExists:
3883 fRc = reporter.error('sPath=%s type=%s: fileExists returned %s, expected %s!'
3884 % (oFsObj.sPath, type(oFsObj), fExistsResult, fFileExists));
3885 try:
3886 fExistsResult = oGuestSession.directoryExists(oFsObj.sPath, False);
3887 except:
3888 fRc = reporter.errorXcpt('sPath=%s type=%s: directoryExists trouble!' % (oFsObj.sPath, type(oFsObj),));
3889 else:
3890 if fExistsResult != fDirExists:
3891 fRc = reporter.error('sPath=%s type=%s: directoryExists returned %s, expected %s!'
3892 % (oFsObj.sPath, type(oFsObj), fExistsResult, fDirExists));
3893
3894 fRc = oTest.closeSession() and fRc;
3895 return (fRc, oTxsSession);
3896
3897 def testGuestCtrlFileOpen(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3898 """
3899 Tests opening guest files.
3900 """
3901 if self.oTstDrv.fpApiVer < 5.0:
3902 reporter.log('Skipping because of pre 5.0 API');
3903 return None;
3904
3905 #
3906 # Paths.
3907 #
3908 sTempDir = self.oTstDrv.getGuestTempDir(oTestVm);
3909 sFileForReading = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
3910 asFiles = [
3911 oTestVm.pathJoin(sTempDir, 'file-open-0'),
3912 oTestVm.pathJoin(sTempDir, 'file-open-1'),
3913 oTestVm.pathJoin(sTempDir, 'file-open-2'),
3914 oTestVm.pathJoin(sTempDir, 'file-open-3'),
3915 oTestVm.pathJoin(sTempDir, 'file-open-4'),
3916 ];
3917 asNonEmptyFiles = [
3918 oTestVm.pathJoin(sTempDir, 'file-open-10'),
3919 oTestVm.pathJoin(sTempDir, 'file-open-11'),
3920 oTestVm.pathJoin(sTempDir, 'file-open-12'),
3921 oTestVm.pathJoin(sTempDir, 'file-open-13'),
3922 ];
3923 sContent = 'abcdefghijklmnopqrstuvwxyz0123456789';
3924 for sFile in asNonEmptyFiles:
3925 if oTxsSession.syncUploadString(sContent, sFile, 0o666) is not True:
3926 return reporter.error('Failed to create "%s" via TXS' % (sFile,));
3927
3928 #
3929 # The tests.
3930 #
3931 atTests = [
3932 # Invalid stuff.
3933 [ tdTestFileOpen(sFile = ''), tdTestResultFailure() ],
3934 # Wrong open mode.
3935 [ tdTestFileOpen(sFile = sFileForReading, eAccessMode = -1), tdTestResultFailure() ],
3936 # Wrong disposition.
3937 [ tdTestFileOpen(sFile = sFileForReading, eAction = -1), tdTestResultFailure() ],
3938 # Non-existing file or path.
3939 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir')), tdTestResultFailure() ],
3940 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
3941 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
3942 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
3943 eAccessMode = vboxcon.FileAccessMode_WriteOnly,
3944 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
3945 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
3946 eAccessMode = vboxcon.FileAccessMode_ReadWrite,
3947 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
3948 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-dir', 'no-such-file')), tdTestResultFailure() ],
3949 ];
3950 if self.oTstDrv.fpApiVer > 5.2: # Fixed since 6.0.
3951 atTests.extend([
3952 # Wrong type:
3953 [ tdTestFileOpen(sFile = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3954 [ tdTestFileOpen(sFile = self.oTstDrv.getGuestSystemDir(oTestVm)), tdTestResultFailure() ],
3955 ]);
3956 atTests.extend([
3957 # O_EXCL and such:
3958 [ tdTestFileOpen(sFile = sFileForReading, eAction = vboxcon.FileOpenAction_CreateNew,
3959 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultFailure() ],
3960 [ tdTestFileOpen(sFile = sFileForReading, eAction = vboxcon.FileOpenAction_CreateNew), tdTestResultFailure() ],
3961 # Open a file.
3962 [ tdTestFileOpen(sFile = sFileForReading), tdTestResultSuccess() ],
3963 [ tdTestFileOpen(sFile = sFileForReading,
3964 eAction = vboxcon.FileOpenAction_OpenOrCreate), tdTestResultSuccess() ],
3965 # Create a new file.
3966 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateNew,
3967 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3968 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateNew,
3969 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultFailure() ],
3970 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenExisting,
3971 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3972 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateOrReplace,
3973 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3974 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenOrCreate,
3975 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3976 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenExistingTruncated,
3977 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3978 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_AppendOrCreate,
3979 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3980 # Open or create a new file.
3981 [ tdTestFileOpenCheckSize(sFile = asFiles[1], eAction = vboxcon.FileOpenAction_OpenOrCreate,
3982 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3983 # Create or replace a new file.
3984 [ tdTestFileOpenCheckSize(sFile = asFiles[2], eAction = vboxcon.FileOpenAction_CreateOrReplace,
3985 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3986 # Create and append to file (weird stuff).
3987 [ tdTestFileOpenCheckSize(sFile = asFiles[3], eAction = vboxcon.FileOpenAction_AppendOrCreate,
3988 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3989 [ tdTestFileOpenCheckSize(sFile = asFiles[4], eAction = vboxcon.FileOpenAction_AppendOrCreate,
3990 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3991 # Open the non-empty files in non-destructive modes.
3992 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent)), tdTestResultSuccess() ],
3993 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
3994 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3995 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
3996 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3997
3998 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent),
3999 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4000 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4001 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
4002 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4003 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4004 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
4005 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4006 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4007
4008 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent),
4009 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4010 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4011 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
4012 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4013 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4014 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
4015 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4016 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4017
4018 # Now the destructive stuff:
4019 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], eAccessMode = vboxcon.FileAccessMode_WriteOnly,
4020 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultSuccess() ],
4021 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], eAccessMode = vboxcon.FileAccessMode_WriteOnly,
4022 eAction = vboxcon.FileOpenAction_CreateOrReplace), tdTestResultSuccess() ],
4023 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], eAction = vboxcon.FileOpenAction_CreateOrReplace,
4024 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4025 ]);
4026
4027 #
4028 # Do the testing.
4029 #
4030 fRc = True;
4031 for (i, tTest) in enumerate(atTests):
4032 oCurTest = tTest[0] # type: tdTestFileOpen
4033 oCurRes = tTest[1] # type: tdTestResult
4034
4035 reporter.log('Testing #%d: %s - sFile="%s", eAccessMode=%d, eAction=%d, (%s, %s, %s) ...'
4036 % (i, oCurTest.__class__.__name__, oCurTest.sFile, oCurTest.eAccessMode, oCurTest.eAction,
4037 oCurTest.eSharing, oCurTest.fCreationMode, oCurTest.afOpenFlags,));
4038
4039 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4040 fRc, _ = oCurTest.createSession('testGuestCtrlFileOpen: Test #%d' % (i,));
4041 if fRc is not True:
4042 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4043 break;
4044
4045 fRc2 = oCurTest.doSteps(oCurRes.fRc, self);
4046 if fRc2 != oCurRes.fRc:
4047 fRc = reporter.error('Test #%d result mismatch: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
4048
4049 fRc = oCurTest.closeSession() and fRc;
4050
4051 return (fRc, oTxsSession);
4052
4053
4054 def testGuestCtrlFileRead(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-branches,too-many-statements
4055 """
4056 Tests reading from guest files.
4057 """
4058 if self.oTstDrv.fpApiVer < 5.0:
4059 reporter.log('Skipping because of pre 5.0 API');
4060 return None;
4061
4062 #
4063 # Do everything in one session.
4064 #
4065 oTest = tdTestGuestCtrlBase();
4066 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
4067 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet');
4068 if fRc2 is not True:
4069 return (False, oTxsSession);
4070
4071 #
4072 # Create a really big zero filled, up to 1 GiB, adding it to the list of
4073 # files from the set.
4074 #
4075 # Note! This code sucks a bit because we don't have a working setSize nor
4076 # any way to figure out how much free space there is in the guest.
4077 #
4078 aoExtraFiles = [];
4079 sBigName = self.oTestFiles.generateFilenameEx();
4080 sBigPath = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sBigName);
4081 fRc = True;
4082 try:
4083 oFile = oGuestSession.fileOpenEx(sBigPath, vboxcon.FileAccessMode_ReadWrite, vboxcon.FileOpenAction_CreateOrReplace,
4084 vboxcon.FileSharingMode_All, 0, []);
4085 except:
4086 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4087 else:
4088 # Does setSize work now?
4089 fUseFallback = True;
4090 try:
4091 oFile.setSize(0);
4092 oFile.setSize(64);
4093 fUseFallback = False;
4094 except Exception as oXcpt:
4095 reporter.logXcpt();
4096
4097 # Grow the file till we hit trouble, typical VERR_DISK_FULL, then
4098 # reduce the file size if we have a working setSize.
4099 cbBigFile = 0;
4100 while cbBigFile < (1024 + 32)*1024*1024:
4101 if not fUseFallback:
4102 cbBigFile += 16*1024*1024;
4103 try:
4104 oFile.setSize(cbBigFile);
4105 except Exception as oXcpt:
4106 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4107 try:
4108 cbBigFile -= 16*1024*1024;
4109 oFile.setSize(cbBigFile);
4110 except:
4111 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4112 break;
4113 else:
4114 cbBigFile += 32*1024*1024;
4115 try:
4116 oFile.seek(cbBigFile, vboxcon.FileSeekOrigin_Begin);
4117 oFile.write(bytearray(1), 60*1000);
4118 except:
4119 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4120 break;
4121 try:
4122 cbBigFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
4123 except:
4124 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4125 try:
4126 oFile.close();
4127 except:
4128 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4129 if fRc is True:
4130 reporter.log('Big file: %s bytes: %s' % (cbBigFile, sBigPath,));
4131 aoExtraFiles.append(testfileset.TestFileZeroFilled(None, sBigPath, cbBigFile));
4132 else:
4133 try:
4134 oGuestSession.fsObjRemove(sBigPath);
4135 except:
4136 reporter.errorXcpt('fsObjRemove(sBigName=%s)' % (sBigPath,));
4137
4138 #
4139 # Open and read all the files in the test file set.
4140 #
4141 for oTestFile in aoExtraFiles + self.oTestFiles.aoFiles: # type: testfileset.TestFile
4142 reporter.log2('Test file: %s bytes, "%s" ...' % (oTestFile.cbContent, limitString(oTestFile.sPath),));
4143
4144 #
4145 # Open it:
4146 #
4147 try:
4148 oFile = oGuestSession.fileOpenEx(oTestFile.sPath, vboxcon.FileAccessMode_ReadOnly,
4149 vboxcon.FileOpenAction_OpenExisting, vboxcon.FileSharingMode_All, 0, []);
4150 except:
4151 fRc = reporter.errorXcpt('sPath=%s' % (oTestFile.sPath, ));
4152 continue;
4153
4154 #
4155 # Read the file in different sized chunks:
4156 #
4157 if oTestFile.cbContent < 128:
4158 acbChunks = xrange(1,128);
4159 elif oTestFile.cbContent < 1024:
4160 acbChunks = (2048, 127, 63, 32, 29, 17, 16, 15, 9);
4161 elif oTestFile.cbContent < 8*1024*1024:
4162 acbChunks = (128*1024, 32*1024, 8191, 255);
4163 else:
4164 acbChunks = (768*1024, 128*1024);
4165
4166 for cbChunk in acbChunks:
4167 # Read the whole file straight thru:
4168 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... cbChunk=%s' % (cbChunk,));
4169 offFile = 0;
4170 cReads = 0;
4171 while offFile <= oTestFile.cbContent:
4172 try:
4173 abRead = oFile.read(cbChunk, 30*1000);
4174 except:
4175 fRc = reporter.errorXcpt('%s: offFile=%s cbChunk=%s cbContent=%s'
4176 % (oTestFile.sPath, offFile, cbChunk, oTestFile.cbContent));
4177 break;
4178 cbRead = len(abRead);
4179 if cbRead == 0 and offFile == oTestFile.cbContent:
4180 break;
4181 if cbRead <= 0:
4182 fRc = reporter.error('%s @%s: cbRead=%s, cbContent=%s'
4183 % (oTestFile.sPath, offFile, cbRead, oTestFile.cbContent));
4184 break;
4185 if not oTestFile.equalMemory(abRead, offFile):
4186 fRc = reporter.error('%s: read mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead));
4187 break;
4188 offFile += cbRead;
4189 cReads += 1;
4190 if cReads > 8192:
4191 break;
4192
4193 # Seek to start of file.
4194 try:
4195 offFile = oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
4196 except:
4197 fRc = reporter.errorXcpt('%s: error seeking to start of file' % (oTestFile.sPath,));
4198 break;
4199 if offFile != 0:
4200 fRc = reporter.error('%s: seek to start of file returned %u, expected 0' % (oTestFile.sPath, offFile));
4201 break;
4202
4203 #
4204 # Random reads.
4205 #
4206 for _ in xrange(8):
4207 offFile = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
4208 cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
4209 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s' % (offFile, cbToRead,));
4210
4211 try:
4212 offActual = oFile.seek(offFile, vboxcon.FileSeekOrigin_Begin);
4213 except:
4214 fRc = reporter.errorXcpt('%s: error seeking to %s' % (oTestFile.sPath, offFile));
4215 break;
4216 if offActual != offFile:
4217 fRc = reporter.error('%s: seek(%s,Begin) -> %s, expected %s'
4218 % (oTestFile.sPath, offFile, offActual, offFile));
4219 break;
4220
4221 try:
4222 abRead = oFile.read(cbToRead, 30*1000);
4223 except:
4224 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s'
4225 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4226 cbRead = 0;
4227 else:
4228 cbRead = len(abRead);
4229 if not oTestFile.equalMemory(abRead, offFile):
4230 fRc = reporter.error('%s: random read mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
4231
4232 try:
4233 offActual = oFile.offset;
4234 except:
4235 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#1)'
4236 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4237 else:
4238 if offActual != offFile + cbRead:
4239 fRc = reporter.error('%s: IFile.offset is %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#1)'
4240 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4241 try:
4242 offActual = oFile.seek(0, vboxcon.FileSeekOrigin_Current);
4243 except:
4244 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#1)'
4245 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4246 else:
4247 if offActual != offFile + cbRead:
4248 fRc = reporter.error('%s: seek(0,cur) -> %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#1)'
4249 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4250
4251 #
4252 # Random reads using readAt.
4253 #
4254 for _ in xrange(12):
4255 offFile = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
4256 cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
4257 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s (readAt)' % (offFile, cbToRead,));
4258
4259 try:
4260 abRead = oFile.readAt(offFile, cbToRead, 30*1000);
4261 except:
4262 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s'
4263 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4264 cbRead = 0;
4265 else:
4266 cbRead = len(abRead);
4267 if not oTestFile.equalMemory(abRead, offFile):
4268 fRc = reporter.error('%s: random readAt mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
4269
4270 try:
4271 offActual = oFile.offset;
4272 except:
4273 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#2)'
4274 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4275 else:
4276 if offActual != offFile + cbRead:
4277 fRc = reporter.error('%s: IFile.offset is %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#2)'
4278 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4279
4280 try:
4281 offActual = oFile.seek(0, vboxcon.FileSeekOrigin_Current);
4282 except:
4283 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#2)'
4284 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4285 else:
4286 if offActual != offFile + cbRead:
4287 fRc = reporter.error('%s: seek(0,cur) -> %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#2)'
4288 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4289
4290 #
4291 # A few negative things.
4292 #
4293
4294 # Zero byte reads -> E_INVALIDARG.
4295 try:
4296 abRead = oFile.read(0, 30*1000);
4297 except Exception as oXcpt:
4298 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
4299 fRc = reporter.errorXcpt('read(0,30s) did not raise E_INVALIDARG as expected!');
4300 else:
4301 fRc = reporter.error('read(0,30s) did not fail!');
4302
4303 try:
4304 abRead = oFile.readAt(0, 0, 30*1000);
4305 except Exception as oXcpt:
4306 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
4307 fRc = reporter.errorXcpt('readAt(0,0,30s) did not raise E_INVALIDARG as expected!');
4308 else:
4309 fRc = reporter.error('readAt(0,0,30s) did not fail!');
4310
4311 # See what happens when we read 1GiB. We should get a max of 1MiB back.
4312 ## @todo Document this behaviour in VirtualBox.xidl.
4313 try:
4314 oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
4315 except:
4316 fRc = reporter.error('seek(0)');
4317 try:
4318 abRead = oFile.read(1024*1024*1024, 30*1000);
4319 except:
4320 fRc = reporter.errorXcpt('read(1GiB,30s)');
4321 else:
4322 if len(abRead) != min(oTestFile.cbContent, 1024*1024):
4323 fRc = reporter.error('Expected read(1GiB,30s) to return %s bytes, got %s bytes instead'
4324 % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
4325
4326 try:
4327 abRead = oFile.readAt(0, 1024*1024*1024, 30*1000);
4328 except:
4329 fRc = reporter.errorXcpt('readAt(0,1GiB,30s)');
4330 else:
4331 if len(abRead) != min(oTestFile.cbContent, 1024*1024):
4332 reporter.error('Expected readAt(0, 1GiB,30s) to return %s bytes, got %s bytes instead'
4333 % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
4334
4335 #
4336 # Check stat info on the file as well as querySize.
4337 #
4338 if self.oTstDrv.fpApiVer > 5.2:
4339 try:
4340 oFsObjInfo = oFile.queryInfo();
4341 except:
4342 fRc = reporter.errorXcpt('%s: queryInfo()' % (oTestFile.sPath,));
4343 else:
4344 if oFsObjInfo is None:
4345 fRc = reporter.error('IGuestFile::queryInfo returned None');
4346 else:
4347 try:
4348 cbFile = oFsObjInfo.objectSize;
4349 except:
4350 fRc = reporter.errorXcpt();
4351 else:
4352 if cbFile != oTestFile.cbContent:
4353 fRc = reporter.error('%s: queryInfo returned incorrect file size: %s, expected %s'
4354 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4355
4356 try:
4357 cbFile = oFile.querySize();
4358 except:
4359 fRc = reporter.errorXcpt('%s: querySize()' % (oTestFile.sPath,));
4360 else:
4361 if cbFile != oTestFile.cbContent:
4362 fRc = reporter.error('%s: querySize returned incorrect file size: %s, expected %s'
4363 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4364
4365 #
4366 # Use seek to test the file size and do a few other end-relative seeks.
4367 #
4368 try:
4369 cbFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
4370 except:
4371 fRc = reporter.errorXcpt('%s: seek(0,End)' % (oTestFile.sPath,));
4372 else:
4373 if cbFile != oTestFile.cbContent:
4374 fRc = reporter.error('%s: seek(0,End) returned incorrect file size: %s, expected %s'
4375 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4376 if oTestFile.cbContent > 0:
4377 for _ in xrange(5):
4378 offSeek = self.oTestFiles.oRandom.randrange(oTestFile.cbContent + 1);
4379 try:
4380 offFile = oFile.seek(-offSeek, vboxcon.FileSeekOrigin_End);
4381 except:
4382 fRc = reporter.errorXcpt('%s: seek(%s,End)' % (oTestFile.sPath, -offSeek,));
4383 else:
4384 if offFile != oTestFile.cbContent - offSeek:
4385 fRc = reporter.error('%s: seek(%s,End) returned incorrect offset: %s, expected %s (cbContent=%s)'
4386 % (oTestFile.sPath, -offSeek, offSeek, oTestFile.cbContent - offSeek,
4387 oTestFile.cbContent,));
4388
4389 #
4390 # Close it and we're done with this file.
4391 #
4392 try:
4393 oFile.close();
4394 except:
4395 fRc = reporter.errorXcpt('%s: error closing the file' % (oTestFile.sPath,));
4396
4397 #
4398 # Clean up.
4399 #
4400 for oTestFile in aoExtraFiles:
4401 try:
4402 oGuestSession.fsObjRemove(sBigPath);
4403 except:
4404 fRc = reporter.errorXcpt('fsObjRemove(%s)' % (sBigPath,));
4405
4406 fRc = oTest.closeSession() and fRc;
4407
4408 return (fRc, oTxsSession);
4409
4410
4411 def testGuestCtrlFileWrite(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4412 """
4413 Tests writing to guest files.
4414 """
4415 if self.oTstDrv.fpApiVer < 5.0:
4416 reporter.log('Skipping because of pre 5.0 API');
4417 return None;
4418
4419 #
4420 # The test file and its content.
4421 #
4422 sFile = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'gctrl-write-1');
4423 abContent = bytearray(0);
4424
4425 #
4426 # The tests.
4427 #
4428 def randBytes(cbHowMany):
4429 """ Returns an bytearray of random bytes. """
4430 return bytearray(self.oTestFiles.oRandom.getrandbits(8) for _ in xrange(cbHowMany));
4431
4432 aoTests = [
4433 # Write at end:
4434 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_CreateNew, abContent = abContent,
4435 atChunks = [(None, randBytes(1)), (None, randBytes(77)), (None, randBytes(98)),]),
4436 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1+77+98), # 176
4437 # Appending:
4438 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_AppendOrCreate, abContent = abContent,
4439 atChunks = [(None, randBytes(255)), (None, randBytes(33)),]),
4440 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 176 + 255+33), # 464
4441 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_AppendOrCreate, abContent = abContent,
4442 atChunks = [(10, randBytes(44)),]),
4443 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 464 + 44), # 508
4444 # Write within existing:
4445 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_OpenExisting, abContent = abContent,
4446 atChunks = [(0, randBytes(1)), (50, randBytes(77)), (255, randBytes(199)),]),
4447 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 508),
4448 # Writing around and over the end:
4449 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent,
4450 atChunks = [(500, randBytes(9)), (508, randBytes(15)), (512, randBytes(12)),]),
4451 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 512+12),
4452
4453 # writeAt appending:
4454 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4455 atChunks = [(0, randBytes(23)), (6, randBytes(1018)),]),
4456 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 6+1018), # 1024
4457 # writeAt within existing:
4458 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4459 atChunks = [(1000, randBytes(23)), (1, randBytes(990)),]),
4460 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1024),
4461 # writeAt around and over the end:
4462 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4463 atChunks = [(1024, randBytes(63)), (1080, randBytes(968)),]),
4464 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1080+968), # 2048
4465
4466 # writeAt beyond the end (gap is filled with zeros):
4467 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True, atChunks = [(3070, randBytes(2)),]),
4468 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 3072),
4469 # write beyond the end (gap is filled with zeros):
4470 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, atChunks = [(4090, randBytes(6)),]),
4471 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 4096),
4472 ];
4473
4474 for (i, oCurTest) in enumerate(aoTests):
4475 reporter.log('Testing #%d: %s ...' % (i, oCurTest.toString(),));
4476
4477 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4478 fRc, _ = oCurTest.createSession('testGuestCtrlFileWrite: Test #%d' % (i,));
4479 if fRc is not True:
4480 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4481 break;
4482
4483 fRc2 = oCurTest.doSteps(True, self);
4484 if fRc2 is not True:
4485 fRc = reporter.error('Test #%d failed!' % (i,));
4486
4487 fRc = oCurTest.closeSession() and fRc;
4488
4489 #
4490 # Cleanup
4491 #
4492 if oTxsSession.syncRmFile(sFile) is not True:
4493 fRc = reporter.error('Failed to remove write-test file: %s' % (sFile, ));
4494
4495 return (fRc, oTxsSession);
4496
4497 @staticmethod
4498 def __generateFile(sName, cbFile):
4499 """ Helper for generating a file with a given size. """
4500 oFile = open(sName, 'wb');
4501 while cbFile > 0:
4502 cb = cbFile if cbFile < 256*1024 else 256*1024;
4503 oFile.write(bytearray(random.getrandbits(8) for _ in xrange(cb)));
4504 cbFile -= cb;
4505 oFile.close();
4506
4507 def testGuestCtrlCopyTo(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4508 """
4509 Tests copying files from host to the guest.
4510 """
4511
4512 #
4513 # Paths and test files.
4514 #
4515 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, 'copyto');
4516 sScratchTestFilesHst = os.path.join(sScratchHst, self.oTestFiles.sSubDir);
4517 sScratchEmptyDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oEmptyDir.sName);
4518 sScratchNonEmptyDirHst = self.oTestFiles.chooseRandomDirFromTree().buildPath(sScratchHst, os.path.sep);
4519 sScratchTreeDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oTreeDir.sName);
4520
4521 sScratchGst = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'copyto');
4522 sScratchDstDir1Gst = oTestVm.pathJoin(sScratchGst, 'dstdir1');
4523 sScratchDstDir2Gst = oTestVm.pathJoin(sScratchGst, 'dstdir2');
4524 sScratchDstDir3Gst = oTestVm.pathJoin(sScratchGst, 'dstdir3');
4525 sScratchDstDir4Gst = oTestVm.pathJoin(sScratchGst, 'dstdir4');
4526 #sScratchGstNotExist = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'no-such-file-or-directory');
4527 sScratchHstNotExist = os.path.join(self.oTstDrv.sScratchPath, 'no-such-file-or-directory');
4528 sScratchGstPathNotFound = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'no-such-directory', 'or-file');
4529 #sScratchHstPathNotFound = os.path.join(self.oTstDrv.sScratchPath, 'no-such-directory', 'or-file');
4530
4531 if oTestVm.isWindows() or oTestVm.isOS2():
4532 sScratchGstInvalid = "?*|<invalid-name>";
4533 else:
4534 sScratchGstInvalid = None;
4535 if utils.getHostOs() in ('win', 'os2'):
4536 sScratchHstInvalid = "?*|<invalid-name>";
4537 else:
4538 sScratchHstInvalid = None;
4539
4540 for sDir in (sScratchGst, sScratchDstDir1Gst, sScratchDstDir2Gst, sScratchDstDir3Gst, sScratchDstDir4Gst):
4541 if oTxsSession.syncMkDir(sDir, 0o777) is not True:
4542 return reporter.error('TXS failed to create directory "%s"!' % (sDir,));
4543
4544 # Put the test file set under sScratchHst.
4545 if os.path.exists(sScratchHst):
4546 if base.wipeDirectory(sScratchHst) != 0:
4547 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
4548 else:
4549 try:
4550 os.mkdir(sScratchHst);
4551 except:
4552 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
4553 if self.oTestFiles.writeToDisk(sScratchHst) is not True:
4554 return reporter.error('Filed to write test files to "%s" on the host!' % (sScratchHst,));
4555
4556 # Generate a test file in 32MB to 64 MB range.
4557 sBigFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-random.data');
4558 cbBigFileHst = random.randrange(32*1024*1024, 64*1024*1024);
4559 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
4560 cbLeft = cbBigFileHst;
4561 try:
4562 self.__generateFile(sBigFileHst, cbBigFileHst);
4563 except:
4564 return reporter.errorXcpt('sBigFileHst=%s cbBigFileHst=%s cbLeft=%s' % (sBigFileHst, cbBigFileHst, cbLeft,));
4565 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
4566
4567 # Generate an empty file on the host that we can use to save space in the guest.
4568 sEmptyFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-empty.data');
4569 try:
4570 oFile = open(sEmptyFileHst, "wb");
4571 oFile.close();
4572 except:
4573 return reporter.errorXcpt('sEmptyFileHst=%s' % (sEmptyFileHst,));
4574
4575 #
4576 # Tests.
4577 #
4578 atTests = [
4579 # Nothing given:
4580 [ tdTestCopyToFile(), tdTestResultFailure() ],
4581 [ tdTestCopyToDir(), tdTestResultFailure() ],
4582 # Only source given:
4583 [ tdTestCopyToFile(sSrc = sBigFileHst), tdTestResultFailure() ],
4584 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst), tdTestResultFailure() ],
4585 # Only destination given:
4586 [ tdTestCopyToFile(sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')), tdTestResultFailure() ],
4587 [ tdTestCopyToDir( sDst = sScratchGst), tdTestResultFailure() ],
4588 # Both given, but invalid flags.
4589 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst, afFlags = [ 0x40000000] ), tdTestResultFailure() ],
4590 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGst, afFlags = [ 0x40000000] ),
4591 tdTestResultFailure() ],
4592 ];
4593 atTests.extend([
4594 # Non-existing source, but no destination:
4595 [ tdTestCopyToFile(sSrc = sScratchHstNotExist), tdTestResultFailure() ],
4596 [ tdTestCopyToDir( sSrc = sScratchHstNotExist), tdTestResultFailure() ],
4597 # Valid sources, but destination path not found:
4598 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
4599 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
4600 # Valid destination, but source file/dir not found:
4601 [ tdTestCopyToFile(sSrc = sScratchHstNotExist, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
4602 tdTestResultFailure() ],
4603 [ tdTestCopyToDir( sSrc = sScratchHstNotExist, sDst = sScratchGst), tdTestResultFailure() ],
4604 # Wrong type:
4605 [ tdTestCopyToFile(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
4606 tdTestResultFailure() ],
4607 [ tdTestCopyToDir( sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultFailure() ],
4608 ]);
4609 # Invalid characters in destination or source path:
4610 if sScratchGstInvalid is not None:
4611 atTests.extend([
4612 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
4613 tdTestResultFailure() ],
4614 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
4615 tdTestResultFailure() ],
4616 ]);
4617 if sScratchHstInvalid is not None:
4618 atTests.extend([
4619 [ tdTestCopyToFile(sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
4620 tdTestResultFailure() ],
4621 [ tdTestCopyToDir( sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
4622 tdTestResultFailure() ],
4623 ]);
4624
4625 #
4626 # Single file handling.
4627 #
4628 atTests.extend([
4629 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')),
4630 tdTestResultSuccess() ],
4631 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
4632 tdTestResultSuccess() ],
4633 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
4634 tdTestResultSuccess() ],
4635 ]);
4636 if self.oTstDrv.fpApiVer > 5.2: # Copying files into directories via Main is supported only 6.0 and later.
4637 atTests.extend([
4638 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ],
4639 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ], # Overwrite
4640 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, os.path.split(sBigFileHst)[1])),
4641 tdTestResultSuccess() ], # Overwrite
4642 ]);
4643
4644 if oTestVm.isWindows():
4645 # Copy to a Windows alternative data stream (ADS).
4646 atTests.extend([
4647 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat:ADS-Test')),
4648 tdTestResultSuccess() ],
4649 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat:ADS-Test')),
4650 tdTestResultSuccess() ],
4651 ]);
4652
4653 #
4654 # Directory handling.
4655 #
4656 if self.oTstDrv.fpApiVer > 5.2: # Copying directories via Main is supported only in versions > 5.2.
4657 atTests.extend([
4658 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
4659 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4660 # Try again.
4661 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
4662 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4663 # Should fail, as destination directory already exists.
4664 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultFailure() ],
4665 # Try again with trailing slash, should yield the same result:
4666 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep(),
4667 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4668 # Try again.
4669 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep(),
4670 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4671 # Should fail, as destination directory already exists.
4672 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
4673 tdTestResultFailure() ],
4674 # Copy with a different destination name just for the heck of it:
4675 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchDstDir1Gst, 'empty2')),
4676 tdTestResultSuccess() ],
4677 ]);
4678 atTests.extend([
4679 # Now the same using a directory with files in it:
4680 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
4681 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4682 # Again.
4683 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
4684 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4685 # Should fail, as directory is existing already.
4686 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst), tdTestResultFailure() ],
4687 ]);
4688 atTests.extend([
4689 # Copy the entire test tree:
4690 [ tdTestCopyToDir(sSrc = sScratchTreeDirHst, sDst = sScratchDstDir4Gst,
4691 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4692 ]);
4693
4694 fRc = True;
4695 for (i, tTest) in enumerate(atTests):
4696 oCurTest = tTest[0]; # tdTestCopyTo
4697 oCurRes = tTest[1]; # tdTestResult
4698 reporter.log('Testing #%d, sSrc=%s, sDst=%s, afFlags=%s ...'
4699 % (i, limitString(oCurTest.sSrc), limitString(oCurTest.sDst), oCurTest.afFlags));
4700
4701 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4702 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyTo: Test #%d' % (i,));
4703 if fRc is not True:
4704 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4705 break;
4706
4707 fRc2 = False;
4708 if isinstance(oCurTest, tdTestCopyToFile):
4709 fRc2 = self.gctrlCopyFileTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags, oCurRes.fRc);
4710 else:
4711 fRc2 = self.gctrlCopyDirTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags, oCurRes.fRc);
4712 if fRc2 is not oCurRes.fRc:
4713 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
4714
4715 fRc = oCurTest.closeSession() and fRc;
4716
4717 return (fRc, oTxsSession);
4718
4719 def testGuestCtrlCopyFrom(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4720 """
4721 Tests copying files from guest to the host.
4722 """
4723
4724 #
4725 # Paths.
4726 #
4727 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom");
4728 sScratchDstDir1Hst = os.path.join(sScratchHst, "dstdir1");
4729 sScratchDstDir2Hst = os.path.join(sScratchHst, "dstdir2");
4730 sScratchDstDir3Hst = os.path.join(sScratchHst, "dstdir3");
4731 oExistingFileGst = self.oTestFiles.chooseRandomFile();
4732 oNonEmptyDirGst = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True);
4733 oEmptyDirGst = self.oTestFiles.oEmptyDir;
4734
4735 if oTestVm.isWindows() or oTestVm.isOS2():
4736 sScratchGstInvalid = "?*|<invalid-name>";
4737 else:
4738 sScratchGstInvalid = None;
4739 if utils.getHostOs() in ('win', 'os2'):
4740 sScratchHstInvalid = "?*|<invalid-name>";
4741 else:
4742 sScratchHstInvalid = None;
4743
4744 if os.path.exists(sScratchHst):
4745 if base.wipeDirectory(sScratchHst) != 0:
4746 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
4747 else:
4748 try:
4749 os.mkdir(sScratchHst);
4750 except:
4751 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
4752
4753 for sSubDir in (sScratchDstDir1Hst, sScratchDstDir2Hst, sScratchDstDir3Hst):
4754 try:
4755 os.mkdir(sSubDir);
4756 except:
4757 return reporter.errorXcpt('os.mkdir(%s)' % (sSubDir, ));
4758
4759 #
4760 # Bad parameter tests.
4761 #
4762 atTests = [
4763 # Missing both source and destination:
4764 [ tdTestCopyFromFile(), tdTestResultFailure() ],
4765 [ tdTestCopyFromDir(), tdTestResultFailure() ],
4766 # Missing source.
4767 [ tdTestCopyFromFile(sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4768 [ tdTestCopyFromDir( sDst = sScratchHst), tdTestResultFailure() ],
4769 # Missing destination.
4770 [ tdTestCopyFromFile(oSrc = oExistingFileGst), tdTestResultFailure() ],
4771 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath), tdTestResultFailure() ],
4772 # Invalid flags:
4773 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somefile'), afFlags = [0x40000000]),
4774 tdTestResultFailure() ],
4775 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'somedir'), afFlags = [ 0x40000000] ),
4776 tdTestResultFailure() ],
4777 # Non-existing sources:
4778 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
4779 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4780 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
4781 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4782 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-file'),
4783 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4784 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-subdir'),
4785 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4786 # Non-existing destinations:
4787 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
4788 sDst = os.path.join(sScratchHst, 'no-such-directory', 'somefile') ), tdTestResultFailure() ],
4789 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'no-such-directory', 'somedir') ),
4790 tdTestResultFailure() ],
4791 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
4792 sDst = os.path.join(sScratchHst, 'no-such-directory-slash' + os.path.sep)),
4793 tdTestResultFailure() ],
4794 # Wrong source type:
4795 [ tdTestCopyFromFile(oSrc = oNonEmptyDirGst, sDst = os.path.join(sScratchHst, 'somefile') ), tdTestResultFailure() ],
4796 [ tdTestCopyFromDir(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somedir') ), tdTestResultFailure() ],
4797 ];
4798 # Bogus names:
4799 if sScratchHstInvalid:
4800 atTests.extend([
4801 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
4802 tdTestResultFailure() ],
4803 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
4804 tdTestResultFailure() ],
4805 ]);
4806 if sScratchGstInvalid:
4807 atTests.extend([
4808 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
4809 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4810 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
4811 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4812 ]);
4813
4814 #
4815 # Single file copying.
4816 #
4817 atTests.extend([
4818 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')),
4819 tdTestResultSuccess() ],
4820 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')), # Overwrite it
4821 tdTestResultSuccess() ],
4822 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile2')),
4823 tdTestResultSuccess() ],
4824 ]);
4825 if self.oTstDrv.fpApiVer > 5.2:
4826 # Copy into a directory.
4827 atTests.extend([
4828 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst), tdTestResultSuccess() ],
4829 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst + os.path.sep), tdTestResultSuccess() ],
4830 ]);
4831
4832 #
4833 # Directory tree copying:
4834 #
4835 atTests.extend([
4836 # Copy the empty guest directory (should end up as sScratchHst/empty):
4837 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultSuccess() ],
4838 # Repeat -- this time it should fail, as the destination directory already exists (and
4839 # DirectoryCopyFlag_CopyIntoExisting is not specified):
4840 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultFailure() ],
4841 # Add the DirectoryCopyFlag_CopyIntoExisting flag being set and it should work.
4842 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst,
4843 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4844 # Try again with trailing slash, should yield the same result:
4845 [ tdTestRemoveHostDir(os.path.join(sScratchDstDir1Hst, 'empty')), tdTestResult() ],
4846 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
4847 tdTestResultSuccess() ],
4848 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
4849 tdTestResultFailure() ],
4850 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep,
4851 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4852 # Copy with a different destination name just for the heck of it:
4853 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'empty2'), fIntoDst = True),
4854 tdTestResultFailure() ],
4855 # Now the same using a directory with files in it:
4856 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultSuccess() ],
4857 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultFailure() ],
4858 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst,
4859 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4860 # Copy the entire test tree:
4861 [ tdTestCopyFromDir(sSrc = self.oTestFiles.oTreeDir.sPath, sDst = sScratchDstDir3Hst), tdTestResultSuccess() ],
4862 ]);
4863
4864 #
4865 # Execute the tests.
4866 #
4867 fRc = True;
4868 for (i, tTest) in enumerate(atTests):
4869 oCurTest = tTest[0]
4870 oCurRes = tTest[1] # type: tdTestResult
4871 if isinstance(oCurTest, tdTestCopyFrom):
4872 reporter.log('Testing #%d, %s: sSrc="%s", sDst="%s", afFlags="%s" ...'
4873 % (i, "directory" if isinstance(oCurTest, tdTestCopyFromDir) else "file",
4874 limitString(oCurTest.sSrc), limitString(oCurTest.sDst), oCurTest.afFlags,));
4875 else:
4876 reporter.log('Testing #%d, tdTestRemoveHostDir "%s" ...' % (i, oCurTest.sDir,));
4877 if isinstance(oCurTest, tdTestCopyFromDir) and self.oTstDrv.fpApiVer < 6.0:
4878 reporter.log('Skipping directoryCopyFromGuest test, not implemented in %s' % (self.oTstDrv.fpApiVer,));
4879 continue;
4880
4881 if isinstance(oCurTest, tdTestRemoveHostDir):
4882 fRc = oCurTest.execute(self.oTstDrv, oSession, oTxsSession, oTestVm, 'testing #%d' % (i,));
4883 else:
4884 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4885 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyFrom: Test #%d' % (i,));
4886 if fRc2 is not True:
4887 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4888 break;
4889
4890 if isinstance(oCurTest, tdTestCopyFromFile):
4891 fRc2 = self.gctrlCopyFileFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
4892 else:
4893 fRc2 = self.gctrlCopyDirFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
4894
4895 if fRc2 != oCurRes.fRc:
4896 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
4897
4898 fRc = oCurTest.closeSession() and fRc;
4899
4900 return (fRc, oTxsSession);
4901
4902 def testGuestCtrlUpdateAdditions(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4903 """
4904 Tests updating the Guest Additions inside the guest.
4905
4906 """
4907
4908 ## @todo currently disabled everywhere.
4909 if self.oTstDrv.fpApiVer < 100.0:
4910 reporter.log("Skipping updating GAs everywhere for now...");
4911 return None;
4912
4913 # Skip test for updating Guest Additions if we run on a too old (Windows) guest.
4914 ##
4915 ## @todo make it work everywhere!
4916 ##
4917 if oTestVm.sKind in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
4918 reporter.log("Skipping updating GAs on old windows vm (sKind=%s)" % (oTestVm.sKind,));
4919 return (None, oTxsSession);
4920 if oTestVm.isOS2():
4921 reporter.log("Skipping updating GAs on OS/2 guest");
4922 return (None, oTxsSession);
4923
4924 sVBoxValidationKitIso = self.oTstDrv.sVBoxValidationKitIso;
4925 if not os.path.isfile(sVBoxValidationKitIso):
4926 return reporter.log('Validation Kit .ISO not found at "%s"' % (sVBoxValidationKitIso,));
4927
4928 sScratch = os.path.join(self.oTstDrv.sScratchPath, "testGctrlUpdateAdditions");
4929 try:
4930 os.makedirs(sScratch);
4931 except OSError as e:
4932 if e.errno != errno.EEXIST:
4933 return reporter.error('Failed: Unable to create scratch directory \"%s\"' % (sScratch,));
4934 reporter.log('Scratch path is: %s' % (sScratch,));
4935
4936 atTests = [];
4937 if oTestVm.isWindows():
4938 atTests.extend([
4939 # Source is missing.
4940 [ tdTestUpdateAdditions(sSrc = ''), tdTestResultFailure() ],
4941
4942 # Wrong flags.
4943 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
4944 afFlags = [ 1234 ]), tdTestResultFailure() ],
4945
4946 # Non-existing .ISO.
4947 [ tdTestUpdateAdditions(sSrc = "non-existing.iso"), tdTestResultFailure() ],
4948
4949 # Wrong .ISO.
4950 [ tdTestUpdateAdditions(sSrc = sVBoxValidationKitIso), tdTestResultFailure() ],
4951
4952 # The real thing.
4953 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso()),
4954 tdTestResultSuccess() ],
4955 # Test the (optional) installer arguments. This will extract the
4956 # installer into our guest's scratch directory.
4957 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
4958 asArgs = [ '/extract', '/D=' + sScratch ]),
4959 tdTestResultSuccess() ]
4960 # Some debg ISO. Only enable locally.
4961 #[ tdTestUpdateAdditions(
4962 # sSrc = "V:\\Downloads\\VBoxGuestAdditions-r80354.iso"),
4963 # tdTestResultSuccess() ]
4964 ]);
4965 else:
4966 reporter.log('No OS-specific tests for non-Windows yet!');
4967
4968 fRc = True;
4969 for (i, tTest) in enumerate(atTests):
4970 oCurTest = tTest[0] # type: tdTestUpdateAdditions
4971 oCurRes = tTest[1] # type: tdTestResult
4972 reporter.log('Testing #%d, sSrc="%s", afFlags="%s" ...' % (i, oCurTest.sSrc, oCurTest.afFlags,));
4973
4974 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4975 fRc, _ = oCurTest.createSession('Test #%d' % (i,));
4976 if fRc is not True:
4977 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4978 break;
4979
4980 try:
4981 oCurProgress = oCurTest.oGuest.updateGuestAdditions(oCurTest.sSrc, oCurTest.asArgs, oCurTest.afFlags);
4982 except:
4983 reporter.maybeErrXcpt(oCurRes.fRc, 'Updating Guest Additions exception for sSrc="%s", afFlags="%s":'
4984 % (oCurTest.sSrc, oCurTest.afFlags,));
4985 fRc = False;
4986 else:
4987 if oCurProgress is not None:
4988 oWrapperProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr,
4989 self.oTstDrv, "gctrlUpGA");
4990 oWrapperProgress.wait();
4991 if not oWrapperProgress.isSuccess():
4992 oWrapperProgress.logResult(fIgnoreErrors = not oCurRes.fRc);
4993 fRc = False;
4994 else:
4995 fRc = reporter.error('No progress object returned');
4996
4997 oCurTest.closeSession();
4998 if fRc is oCurRes.fRc:
4999 if fRc:
5000 ## @todo Verify if Guest Additions were really updated (build, revision, ...).
5001 ## @todo r=bird: Not possible since you're installing the same GAs as before...
5002 ## Maybe check creation dates on certain .sys/.dll/.exe files?
5003 pass;
5004 else:
5005 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
5006 break;
5007
5008 return (fRc, oTxsSession);
5009
5010
5011
5012class tdAddGuestCtrl(vbox.TestDriver): # pylint: disable=too-many-instance-attributes,too-many-public-methods
5013 """
5014 Guest control using VBoxService on the guest.
5015 """
5016
5017 def __init__(self):
5018 vbox.TestDriver.__init__(self);
5019 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
5020 self.asRsrcs = None;
5021 self.fQuick = False; # Don't skip lengthly tests by default.
5022 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
5023
5024 #
5025 # Overridden methods.
5026 #
5027 def showUsage(self):
5028 """
5029 Shows the testdriver usage.
5030 """
5031 rc = vbox.TestDriver.showUsage(self);
5032 reporter.log('');
5033 reporter.log('tdAddGuestCtrl Options:');
5034 reporter.log(' --quick');
5035 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
5036 return rc;
5037
5038 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
5039 """
5040 Parses the testdriver arguments from the command line.
5041 """
5042 if asArgs[iArg] == '--quick':
5043 self.parseOption(['--virt-modes', 'hwvirt'], 0);
5044 self.parseOption(['--cpu-counts', '1'], 0);
5045 self.fQuick = True;
5046 else:
5047 return vbox.TestDriver.parseOption(self, asArgs, iArg);
5048 return iArg + 1;
5049
5050 def actionConfig(self):
5051 if not self.importVBoxApi(): # So we can use the constant below.
5052 return False;
5053
5054 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
5055 sGaIso = self.getGuestAdditionsIso();
5056 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
5057
5058 def actionExecute(self):
5059 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
5060
5061 #
5062 # Test execution helpers.
5063 #
5064 def testOneCfg(self, oVM, oTestVm): # pylint: disable=too-many-statements
5065 """
5066 Runs the specified VM thru the tests.
5067
5068 Returns a success indicator on the general test execution. This is not
5069 the actual test result.
5070 """
5071
5072 self.logVmInfo(oVM);
5073
5074 fRc = True;
5075 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False);
5076 reporter.log("TxsSession: %s" % (oTxsSession,));
5077 if oSession is not None:
5078 self.addTask(oTxsSession);
5079
5080 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
5081
5082 # Cleanup.
5083 self.removeTask(oTxsSession);
5084 if not self.aoSubTstDrvs[0].oDebug.fNoExit:
5085 self.terminateVmBySession(oSession);
5086 else:
5087 fRc = False;
5088 return fRc;
5089
5090 def onExit(self, iRc):
5091 if self.aoSubTstDrvs[0].oDebug.fNoExit:
5092 return True
5093 return vbox.TestDriver.onExit(self, iRc);
5094
5095 def gctrlReportError(self, progress):
5096 """
5097 Helper function to report an error of a
5098 given progress object.
5099 """
5100 if progress is None:
5101 reporter.log('No progress object to print error for');
5102 else:
5103 errInfo = progress.errorInfo;
5104 if errInfo:
5105 reporter.log('%s' % (errInfo.text,));
5106 return False;
5107
5108 def gctrlGetRemainingTime(self, msTimeout, msStart):
5109 """
5110 Helper function to return the remaining time (in ms)
5111 based from a timeout value and the start time (both in ms).
5112 """
5113 if msTimeout == 0:
5114 return 0xFFFFFFFE; # Wait forever.
5115 msElapsed = base.timestampMilli() - msStart;
5116 if msElapsed > msTimeout:
5117 return 0; # No time left.
5118 return msTimeout - msElapsed;
5119
5120 def testGuestCtrlManual(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements,unused-argument,unused-variable
5121 """
5122 For manually testing certain bits.
5123 """
5124
5125 reporter.log('Manual testing ...');
5126 fRc = True;
5127
5128 sUser = 'Administrator';
5129 sPassword = 'password';
5130
5131 oGuest = oSession.o.console.guest;
5132 oGuestSession = oGuest.createSession(sUser,
5133 sPassword,
5134 "", "Manual Test");
5135
5136 aWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
5137 _ = oGuestSession.waitForArray(aWaitFor, 30 * 1000);
5138
5139 sCmd = self.getGuestSystemShell(oTestVm);
5140 asArgs = [ sCmd, '/C', 'dir', '/S', 'c:\\windows' ];
5141 aEnv = [];
5142 afFlags = [];
5143
5144 for _ in xrange(100):
5145 oProc = oGuestSession.processCreate(sCmd, asArgs if self.fpApiVer >= 5.0 else asArgs[1:],
5146 aEnv, afFlags, 30 * 1000);
5147
5148 aWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate ];
5149 _ = oProc.waitForArray(aWaitFor, 30 * 1000);
5150
5151 oGuestSession.close();
5152 oGuestSession = None;
5153
5154 time.sleep(5);
5155
5156 oSession.o.console.PowerDown();
5157
5158 return (fRc, oTxsSession);
5159
5160if __name__ == '__main__':
5161 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