VirtualBox

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

Last change on this file since 92948 was 92948, checked in by vboxsync, 3 years ago

ValKit/tdAddGuestCtrl.py: Temporarily disabled the last 4 sub-tests in the 'Copy from guest' test as these seems to be failing pretty constantly. bugref:9320

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 257.6 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: 92948 $"
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 ## @todo bird (2021-12-12): Disabled the testGuestCtrlSessionReboot test because it fails most of the time both
1454 # against trunk and 6.1.31 without being able to immediately spot why this happens. Because it seems to succeed
1455 # sometimes, it's probably not due to missing code, perhaps some race or dropping of client disconnect messages?
1456 #( False, self.testGuestCtrlSessionReboot, 'session_reboot', 'Session w/ Guest Reboot',), # May zap /tmp.
1457 ( False, self.testGuestCtrlUpdateAdditions, 'update_additions', 'Updating Guest Additions',),
1458 ];
1459
1460 fRc = True;
1461 for fMustSucceed, fnHandler, sShortNm, sTestNm in atTests:
1462 reporter.testStart(sTestNm);
1463
1464 if sShortNm is None or sShortNm in self.asTests:
1465 # Returns (fRc, oTxsSession, oSession) - but only the first one is mandatory.
1466 aoResult = fnHandler(oSession, oTxsSession, oTestVm);
1467 if aoResult is None or isinstance(aoResult, bool):
1468 fRcTest = aoResult;
1469 else:
1470 fRcTest = aoResult[0];
1471 if len(aoResult) > 1:
1472 oTxsSession = aoResult[1];
1473 if len(aoResult) > 2:
1474 oSession = aoResult[2];
1475 assert len(aoResult) == 3;
1476 else:
1477 fRcTest = None;
1478
1479 if fRcTest is False and reporter.testErrorCount() == 0:
1480 fRcTest = reporter.error('Buggy test! Returned False w/o logging the error!');
1481 if reporter.testDone(fRcTest is None)[1] != 0:
1482 fRcTest = False;
1483 fRc = False;
1484
1485 # Stop execution if this is a must-succeed test and it failed.
1486 if fRcTest is False and fMustSucceed is True:
1487 reporter.log('Skipping any remaining tests since the previous one failed.');
1488 break;
1489
1490 # Upload VBoxService logs on failure.
1491 if reporter.testErrorCount() > 0 \
1492 and self.oDebug.sGstVBoxServiceLogPath:
1493 sVBoxServiceLogsTarGz = 'ga-vboxservice-logs-%s.tar.gz' % oTestVm.sVmName;
1494 sGstVBoxServiceLogsTarGz = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), sVBoxServiceLogsTarGz);
1495 if self.oTstDrv.txsPackFile(oSession, oTxsSession, \
1496 sGstVBoxServiceLogsTarGz, self.oDebug.sGstVBoxServiceLogPath, fIgnoreErrors = True):
1497 self.oTstDrv.txsDownloadFiles(oSession, oTxsSession, [ (sGstVBoxServiceLogsTarGz, sVBoxServiceLogsTarGz) ], \
1498 fIgnoreErrors = True);
1499
1500 return (fRc, oTxsSession);
1501
1502 def prepareGuestForDebugging(self, oSession, oTxsSession, oTestVm): # pylint: disable=unused-argument
1503 """
1504 Prepares a guest for (manual) debugging.
1505
1506 This involves copying over and invoking a the locally built VBoxService binary.
1507 """
1508
1509 if self.oDebug.sImgPath is None: # If no debugging enabled, bail out.
1510 reporter.log('Skipping debugging');
1511 return True
1512
1513 reporter.log('Preparing for debugging ...');
1514
1515 try:
1516
1517 self.vboxServiceControl(oTxsSession, oTestVm, fStart = False);
1518
1519 if oTestVm.isLinux():
1520 reporter.log('Uploading %s ...' % self.oDebug.sImgPath);
1521 sFileVBoxServiceHst = self.oDebug.sImgPath;
1522 sFileVBoxServiceGst = "/tmp/VBoxService-txs";
1523 oTxsSession.syncUploadFile(sFileVBoxServiceHst, sFileVBoxServiceGst);
1524 oTxsSession.syncChMod(sFileVBoxServiceGst, 0o755);
1525 reporter.log('Executing VBoxService (in background)...');
1526 oTxsSession.syncExec(sFileVBoxServiceGst, (sFileVBoxServiceGst, "-vvvv", "--only-control", \
1527 "--control-dump-stdout", "--control-dump-stderr", \
1528 "--logfile", "/tmp/VBoxService-txs.log") );
1529 elif oTestVm.isWindows():
1530 reporter.log('Uploading %s ...' % self.oDebug.sImgPath);
1531 sFileVBoxServiceHst = self.oDebug.sImgPath;
1532 sFileVBoxServiceGst = os.path.join(self.oTstDrv.getGuestSystemDir(oTestVm), 'VBoxService.exe');
1533 oTxsSession.syncUploadFile(sFileVBoxServiceHst, sFileVBoxServiceGst);
1534 sPathSC = os.path.join(self.oTstDrv.getGuestSystemDir(oTestVm), 'sc.exe');
1535 oTxsSession.syncExec(sPathSC, (sPathSC, "stop", "VBoxService") );
1536 time.sleep(5);
1537 oTxsSession.syncExec(sPathSC, (sPathSC, "start", "VBoxService") );
1538
1539 else: ## @todo Implement others.
1540 reporter.log('Debugging not available on this guest OS yet, skipping ...');
1541
1542 self.vboxServiceControl(oTxsSession, oTestVm, fStart = True);
1543
1544 except:
1545 return reporter.errorXcpt('Unable to prepare for debugging');
1546
1547 return True;
1548
1549 #
1550 # VBoxService handling.
1551 #
1552 def vboxServiceControl(self, oTxsSession, oTestVm, fStart):
1553 """
1554 Controls VBoxService on the guest by starting or stopping the service.
1555 Returns success indicator.
1556 """
1557
1558 fRc = True;
1559
1560 if oTestVm.isWindows():
1561 sPathSC = os.path.join(self.oTstDrv.getGuestSystemDir(oTestVm), 'sc.exe');
1562 if fStart is True:
1563 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Starting VBoxService with verbose logging', 30 * 1000, \
1564 sPathSC, (sPathSC, 'start', 'VBoxService'));
1565 else:
1566 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Stopping VBoxService', 30 * 1000, \
1567 sPathSC, (sPathSC, 'stop', 'VBoxService'));
1568 elif oTestVm.isLinux():
1569 sPathService = "/sbin/rcvboxadd-service";
1570 if fStart is True:
1571 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Starting VBoxService with verbose logging', 30 * 1000, \
1572 sPathService, (sPathService, 'start'));
1573 else:
1574 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Stopping VBoxService', 30 * 1000, \
1575 sPathService, (sPathService, 'stop'));
1576 else:
1577 reporter.log('Controlling VBoxService not supported for this guest yet');
1578
1579 return fRc;
1580
1581 def waitForGuestFacility(self, oSession, eFacilityType, sDesc,
1582 eFacilityStatus, cMsTimeout = 30 * 1000):
1583 """
1584 Waits for a guest facility to enter a certain status.
1585 By default the "Active" status is being used.
1586
1587 Returns success status.
1588 """
1589
1590 reporter.log('Waiting for Guest Additions facility "%s" to change to status %s (%dms timeout)...'
1591 % (sDesc, str(eFacilityStatus), cMsTimeout));
1592
1593 fRc = False;
1594
1595 eStatusOld = None;
1596 tsStart = base.timestampMilli();
1597 while base.timestampMilli() - tsStart < cMsTimeout:
1598 try:
1599 eStatus, _ = oSession.o.console.guest.getFacilityStatus(eFacilityType);
1600 reporter.log('Current status is %s' % (str(eStatus)));
1601 if eStatusOld is None:
1602 eStatusOld = eStatus;
1603 except:
1604 reporter.errorXcpt('Getting facility status failed');
1605 break;
1606 if eStatus != eStatusOld:
1607 reporter.log('Status changed to %s' % (str(eStatus)));
1608 eStatusOld = eStatus;
1609 if eStatus == eFacilityStatus:
1610 fRc = True;
1611 break;
1612 self.oTstDrv.sleep(5); # Do some busy waiting.
1613
1614 if not fRc:
1615 reporter.error('Waiting for Guest Additions facility "%s" timed out' % (sDesc));
1616 else:
1617 reporter.log('Guest Additions facility "%s" reached requested status %s after %dms'
1618 % (sDesc, str(eFacilityStatus), base.timestampMilli() - tsStart));
1619
1620 return fRc;
1621
1622 #
1623 # Guest test files.
1624 #
1625
1626 def prepareGuestForTesting(self, oSession, oTxsSession, oTestVm):
1627 """
1628 Prepares the VM for testing, uploading a bunch of files and stuff via TXS.
1629 Returns success indicator.
1630 """
1631 _ = oSession;
1632
1633 #
1634 # Make sure the temporary directory exists.
1635 #
1636 for sDir in [self.oTstDrv.getGuestTempDir(oTestVm), ]:
1637 if oTxsSession.syncMkDirPath(sDir, 0o777) is not True:
1638 return reporter.error('Failed to create directory "%s"!' % (sDir,));
1639
1640 # Query the TestExecService (TXS) version first to find out on what we run.
1641 sTxsVer = self.oTstDrv.txsVer(oSession, oTxsSession, 30 * 100, fIgnoreErrors = True);
1642
1643 # Whether to enable verbose logging for VBoxService.
1644 fEnableVerboseLogging = False;
1645
1646 # Old TXS versions had a bug which caused an infinite loop when executing stuff containing "$xxx",
1647 # so check the version here first and skip enabling verbose logging if needed.
1648 if sTxsVer:
1649 fEnableVerboseLogging = True;
1650
1651 # On Windows guests we always can enable verbose logging.
1652 if oTestVm.isWindows():
1653 fEnableVerboseLogging = True;
1654
1655 # If debugging mode is disabled, enable logging -- otherwise a manually set up logging could clash here.
1656 if not self.oDebug.sImgPath:
1657 fEnableVerboseLogging = True;
1658
1659 #
1660 # Enable VBoxService verbose logging.
1661 #
1662 if fEnableVerboseLogging:
1663 self.oDebug.sGstVBoxServiceLogPath = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), "VBoxService");
1664 if oTxsSession.syncMkDirPath(self.oDebug.sGstVBoxServiceLogPath, 0o777) is not True:
1665 return reporter.error('Failed to create directory "%s"!' % (self.oDebug.sGstVBoxServiceLogPath,));
1666 sPathLogFile = oTestVm.pathJoin(self.oDebug.sGstVBoxServiceLogPath, 'VBoxService.log');
1667
1668 reporter.log('VBoxService logs will be stored in "%s"' % (self.oDebug.sGstVBoxServiceLogPath,));
1669
1670 fRestartVBoxService = False;
1671 if oTestVm.isWindows():
1672 sPathRegExe = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'reg.exe');
1673 sPathVBoxServiceExe = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'VBoxService.exe');
1674 sImagePath = '%s -vvvv --logfile %s' % (sPathVBoxServiceExe, sPathLogFile);
1675 fRestartVBoxService = self.oTstDrv.txsRunTest(oTxsSession, 'Enabling VBoxService verbose logging (via registry)',
1676 30 * 1000,
1677 sPathRegExe,
1678 (sPathRegExe, 'add',
1679 'HKLM\\SYSTEM\\CurrentControlSet\\Services\\VBoxService',
1680 '/v', 'ImagePath', '/t', 'REG_SZ', '/d', sImagePath, '/f'));
1681 elif oTestVm.isLinux():
1682 sPathSed = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'sed');
1683 fRestartVBoxService = self.oTstDrv.txsRunTest(oTxsSession, 'Enabling VBoxService verbose logging', 30 * 1000,
1684 sPathSed,
1685 (sPathSed, '-i', '-e', 's/'
1686 '\\$2 \\$3'
1687 '/'
1688 '\\$2 \\$3 -vvvv --logfile \\/var\\/tmp\\/VBoxService\\/VBoxService.log'
1689 '/g',
1690 '/sbin/rcvboxadd-service'));
1691 else:
1692 reporter.log('Verbose logging for VBoxService not supported for this guest yet');
1693
1694 if fRestartVBoxService:
1695 self.vboxServiceControl(oTxsSession, oTestVm, fStart = False);
1696 time.sleep(5);
1697 self.vboxServiceControl(oTxsSession, oTestVm, fStart = True);
1698 else:
1699 reporter.testStart('Waiting for VBoxService to get started');
1700 fRc = self.waitForGuestFacility(oSession, vboxcon.AdditionsFacilityType_VBoxService, "VBoxService",
1701 vboxcon.AdditionsFacilityStatus_Active);
1702 reporter.testDone();
1703 if not fRc:
1704 return False;
1705
1706 #
1707 # Generate and upload some random files and dirs to the guest.
1708 # Note! Make sure we don't run into too-long-path issues when using
1709 # the test files on the host if.
1710 #
1711 cchGst = len(self.oTstDrv.getGuestTempDir(oTestVm)) + 1 + len('addgst-1') + 1;
1712 cchHst = len(self.oTstDrv.sScratchPath) + 1 + len('copyto/addgst-1') + 1;
1713 cchMaxPath = 230;
1714 if cchHst > cchGst:
1715 cchMaxPath -= cchHst - cchGst;
1716 reporter.log('cchMaxPath=%s (cchHst=%s, cchGst=%s)' % (cchMaxPath, cchHst, cchGst,));
1717 self.oTestFiles = vboxtestfileset.TestFileSet(oTestVm,
1718 self.oTstDrv.getGuestTempDir(oTestVm), 'addgst-1',
1719 cchMaxPath = cchMaxPath, asCompatibleWith = [ oTestVm.getGuestOs() ]);
1720 return self.oTestFiles.upload(oTxsSession, self.oTstDrv);
1721
1722
1723 #
1724 # gctrlXxxx stuff.
1725 #
1726
1727 def gctrlCopyFileFrom(self, oGuestSession, oTest, fExpected):
1728 """
1729 Helper function to copy a single file from the guest to the host.
1730 """
1731
1732 # As we pass-in randomly generated file names, the source sometimes can be empty, which
1733 # in turn will result in a (correct) error by the API. Simply skip this function then.
1734 if not oTest.sSrc:
1735 reporter.log2('Skipping guest file "%s"' % (limitString(oTest.sSrc)));
1736 return fExpected;
1737
1738 #
1739 # Do the copying.
1740 #
1741 reporter.log2('Copying guest file "%s" to host "%s"' % (limitString(oTest.sSrc), limitString(oTest.sDst)));
1742 try:
1743 if self.oTstDrv.fpApiVer >= 5.0:
1744 oCurProgress = oGuestSession.fileCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.afFlags);
1745 else:
1746 oCurProgress = oGuestSession.copyFrom(oTest.sSrc, oTest.sDst, oTest.afFlags);
1747 except:
1748 reporter.maybeErrXcpt(fExpected, 'Copy from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1749 return False;
1750 if oCurProgress is None:
1751 return reporter.error('No progress object returned');
1752 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlFileCopyFrom");
1753 oProgress.wait();
1754 if not oProgress.isSuccess():
1755 oProgress.logResult(fIgnoreErrors = not fExpected);
1756 return False;
1757
1758 #
1759 # Check the result if we can.
1760 #
1761 if oTest.oSrc:
1762 assert isinstance(oTest.oSrc, testfileset.TestFile);
1763 sDst = oTest.sDst;
1764 if os.path.isdir(sDst):
1765 sDst = os.path.join(sDst, oTest.oSrc.sName);
1766 try:
1767 oFile = open(sDst, 'rb');
1768 except:
1769 return reporter.errorXcpt('open(%s) failed during verfication' % (sDst,));
1770 fEqual = oTest.oSrc.equalFile(oFile);
1771 oFile.close();
1772 if not fEqual:
1773 return reporter.error('Content differs for "%s"' % (sDst,));
1774
1775 return True;
1776
1777 def __compareTestDir(self, oDir, sHostPath): # type: (testfileset.TestDir, str) -> bool
1778 """
1779 Recursively compare the content of oDir and sHostPath.
1780
1781 Returns True on success, False + error logging on failure.
1782
1783 Note! This ASSUMES that nothing else was copied to sHostPath!
1784 """
1785 #
1786 # First check out all the entries and files in the directory.
1787 #
1788 dLeftUpper = dict(oDir.dChildrenUpper);
1789 try:
1790 asEntries = os.listdir(sHostPath);
1791 except:
1792 return reporter.errorXcpt('os.listdir(%s) failed' % (sHostPath,));
1793
1794 fRc = True;
1795 for sEntry in asEntries:
1796 sEntryUpper = sEntry.upper();
1797 if sEntryUpper not in dLeftUpper:
1798 fRc = reporter.error('Unexpected entry "%s" in "%s"' % (sEntry, sHostPath,));
1799 else:
1800 oFsObj = dLeftUpper[sEntryUpper];
1801 del dLeftUpper[sEntryUpper];
1802
1803 if isinstance(oFsObj, testfileset.TestFile):
1804 sFilePath = os.path.join(sHostPath, oFsObj.sName);
1805 try:
1806 oFile = open(sFilePath, 'rb');
1807 except:
1808 fRc = reporter.errorXcpt('open(%s) failed during verfication' % (sFilePath,));
1809 else:
1810 fEqual = oFsObj.equalFile(oFile);
1811 oFile.close();
1812 if not fEqual:
1813 fRc = reporter.error('Content differs for "%s"' % (sFilePath,));
1814
1815 # List missing entries:
1816 for sKey in dLeftUpper:
1817 oEntry = dLeftUpper[sKey];
1818 fRc = reporter.error('%s: Missing %s "%s" (src path: %s)'
1819 % (sHostPath, oEntry.sName,
1820 'file' if isinstance(oEntry, testfileset.TestFile) else 'directory', oEntry.sPath));
1821
1822 #
1823 # Recurse into subdirectories.
1824 #
1825 for oFsObj in oDir.aoChildren:
1826 if isinstance(oFsObj, testfileset.TestDir):
1827 fRc = self.__compareTestDir(oFsObj, os.path.join(sHostPath, oFsObj.sName)) and fRc;
1828 return fRc;
1829
1830 def gctrlCopyDirFrom(self, oGuestSession, oTest, fExpected):
1831 """
1832 Helper function to copy a directory from the guest to the host.
1833 """
1834
1835 # As we pass-in randomly generated directories, the source sometimes can be empty, which
1836 # in turn will result in a (correct) error by the API. Simply skip this function then.
1837 if not oTest.sSrc:
1838 reporter.log2('Skipping guest dir "%s"' % (limitString(oTest.sSrc)));
1839 return fExpected;
1840
1841 #
1842 # Do the copying.
1843 #
1844 reporter.log2('Copying guest dir "%s" to host "%s"' % (limitString(oTest.sSrc), limitString(oTest.sDst)));
1845 try:
1846 if self.oTstDrv.fpApiVer >= 7.0:
1847 ## @todo Make the following new flags implicit for 7.0 for now. Develop dedicated tests for this later and remove.
1848 if not oTest.afFlags:
1849 oTest.afFlags = [ vboxcon.DirectoryCopyFlag_Recursive, ];
1850 elif vboxcon.DirectoryCopyFlag_Recursive not in oTest.afFlags:
1851 oTest.afFlags.append(vboxcon.DirectoryCopyFlag_Recursive);
1852 ## @todo Ditto.
1853 if not oTest.afFlags:
1854 oTest.afFlags = [ vboxcon.DirectoryCopyFlag_FollowLinks, ];
1855 elif vboxcon.DirectoryCopyFlag_FollowLinks not in oTest.afFlags:
1856 oTest.afFlags.append(vboxcon.DirectoryCopyFlag_FollowLinks);
1857 oCurProgress = oGuestSession.directoryCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.afFlags);
1858 except:
1859 reporter.maybeErrXcpt(fExpected, 'Copy dir from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1860 return False;
1861 if oCurProgress is None:
1862 return reporter.error('No progress object returned');
1863
1864 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlDirCopyFrom");
1865 oProgress.wait();
1866 if not oProgress.isSuccess():
1867 oProgress.logResult(fIgnoreErrors = not fExpected);
1868 return False;
1869
1870 #
1871 # Check the result if we can.
1872 #
1873 if oTest.oSrc:
1874 assert isinstance(oTest.oSrc, testfileset.TestDir);
1875 sDst = oTest.sDst;
1876 if oTest.fIntoDst:
1877 return self.__compareTestDir(oTest.oSrc, os.path.join(sDst, oTest.oSrc.sName));
1878 oDummy = testfileset.TestDir(None, 'dummy');
1879 oDummy.aoChildren = [oTest.oSrc,]
1880 oDummy.dChildrenUpper = { oTest.oSrc.sName.upper(): oTest.oSrc, };
1881 return self.__compareTestDir(oDummy, sDst);
1882 return True;
1883
1884 def gctrlCopyFileTo(self, oGuestSession, sSrc, sDst, afFlags, fIsError):
1885 """
1886 Helper function to copy a single file from the host to the guest.
1887
1888 afFlags is either None or an array of vboxcon.DirectoryCopyFlag_Xxxx values.
1889 """
1890 reporter.log2('Copying host file "%s" to guest "%s" (flags %s)' % (limitString(sSrc), limitString(sDst), afFlags));
1891 try:
1892 if self.oTstDrv.fpApiVer >= 5.0:
1893 oCurProgress = oGuestSession.fileCopyToGuest(sSrc, sDst, afFlags);
1894 else:
1895 oCurProgress = oGuestSession.copyTo(sSrc, sDst, afFlags);
1896 except:
1897 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1898 return False;
1899
1900 if oCurProgress is None:
1901 return reporter.error('No progress object returned');
1902 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1903
1904 try:
1905 oProgress.wait();
1906 if not oProgress.isSuccess():
1907 oProgress.logResult(fIgnoreErrors = not fIsError);
1908 return False;
1909 except:
1910 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1911 return False;
1912 return True;
1913
1914 def gctrlCopyDirTo(self, oGuestSession, sSrc, sDst, afFlags, fIsError):
1915 """
1916 Helper function to copy a directory (tree) from the host to the guest.
1917
1918 afFlags is either None or an array of vboxcon.DirectoryCopyFlag_Xxxx values.
1919 """
1920 reporter.log2('Copying host directory "%s" to guest "%s" (flags %s)' % (limitString(sSrc), limitString(sDst), afFlags));
1921 try:
1922 if self.oTstDrv.fpApiVer >= 7.0:
1923 ## @todo Make the following new flags implicit for 7.0 for now. Develop dedicated tests for this later and remove.
1924 if not afFlags:
1925 afFlags = [ vboxcon.DirectoryCopyFlag_Recursive, ];
1926 elif vboxcon.DirectoryCopyFlag_Recursive not in afFlags:
1927 afFlags.append(vboxcon.DirectoryCopyFlag_Recursive);
1928 ## @todo Ditto.
1929 if not afFlags:
1930 afFlags = [vboxcon.DirectoryCopyFlag_FollowLinks,];
1931 elif vboxcon.DirectoryCopyFlag_FollowLinks not in afFlags:
1932 afFlags.append(vboxcon.DirectoryCopyFlag_FollowLinks);
1933 oCurProgress = oGuestSession.directoryCopyToGuest(sSrc, sDst, afFlags);
1934 except:
1935 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1936 return False;
1937
1938 if oCurProgress is None:
1939 return reporter.error('No progress object returned');
1940 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1941
1942 try:
1943 oProgress.wait();
1944 if not oProgress.isSuccess():
1945 oProgress.logResult(fIgnoreErrors = not fIsError);
1946 return False;
1947 except:
1948 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1949 return False;
1950 return True;
1951
1952 def gctrlCreateDir(self, oTest, oRes, oGuestSession):
1953 """
1954 Helper function to create a guest directory specified in the current test.
1955 """
1956 reporter.log2('Creating directory "%s"' % (limitString(oTest.sDirectory),));
1957 try:
1958 oGuestSession.directoryCreate(oTest.sDirectory, oTest.fMode, oTest.afFlags);
1959 except:
1960 reporter.maybeErrXcpt(oRes.fRc, 'Failed to create "%s" fMode=%o afFlags=%s'
1961 % (oTest.sDirectory, oTest.fMode, oTest.afFlags,));
1962 return not oRes.fRc;
1963 if oRes.fRc is not True:
1964 return reporter.error('Did not expect to create directory "%s"!' % (oTest.sDirectory,));
1965
1966 # Check if the directory now exists.
1967 try:
1968 if self.oTstDrv.fpApiVer >= 5.0:
1969 fDirExists = oGuestSession.directoryExists(oTest.sDirectory, False);
1970 else:
1971 fDirExists = oGuestSession.directoryExists(oTest.sDirectory);
1972 except:
1973 return reporter.errorXcpt('directoryExists failed on "%s"!' % (oTest.sDirectory,));
1974 if not fDirExists:
1975 return reporter.errorXcpt('directoryExists returned False on "%s" after directoryCreate succeeded!'
1976 % (oTest.sDirectory,));
1977 return True;
1978
1979 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, sSubDir = None):
1980 """
1981 Helper function to recursively read a guest directory tree specified in the current test.
1982 """
1983 sDir = oTest.sDirectory;
1984 sFilter = oTest.sFilter;
1985 afFlags = oTest.afFlags;
1986 oTestVm = oTest.oCreds.oTestVm;
1987 sCurDir = oTestVm.pathJoin(sDir, sSubDir) if sSubDir else sDir;
1988
1989 fRc = True; # Be optimistic.
1990 cDirs = 0; # Number of directories read.
1991 cFiles = 0; # Number of files read.
1992 cOthers = 0; # Other files.
1993
1994 # Open the directory:
1995 reporter.log2('Directory="%s", filter="%s", afFlags="%s"' % (limitString(sCurDir), sFilter, afFlags));
1996 try:
1997 oCurDir = oGuestSession.directoryOpen(sCurDir, sFilter, afFlags);
1998 except:
1999 reporter.maybeErrXcpt(fIsError, 'sCurDir=%s sFilter=%s afFlags=%s' % (sCurDir, sFilter, afFlags,))
2000 return (False, 0, 0, 0);
2001
2002 # Read the directory.
2003 while fRc is True:
2004 try:
2005 oFsObjInfo = oCurDir.read();
2006 except Exception as oXcpt:
2007 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
2008 if self.oTstDrv.fpApiVer > 5.2:
2009 reporter.errorXcpt('Error reading directory "%s":' % (sCurDir,));
2010 else:
2011 # Unlike fileOpen, directoryOpen will not fail if the directory does not exist.
2012 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,));
2013 fRc = False;
2014 else:
2015 reporter.log2('\tNo more directory entries for "%s"' % (limitString(sCurDir),));
2016 break;
2017
2018 try:
2019 sName = oFsObjInfo.name;
2020 eType = oFsObjInfo.type;
2021 except:
2022 fRc = reporter.errorXcpt();
2023 break;
2024
2025 if sName in ('.', '..', ):
2026 if eType != vboxcon.FsObjType_Directory:
2027 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
2028 % (sName, eType, vboxcon.FsObjType_Directory));
2029 elif eType == vboxcon.FsObjType_Directory:
2030 reporter.log2(' Directory "%s"' % limitString(oFsObjInfo.name));
2031 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError,
2032 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName);
2033 fRc = aSubResult[0];
2034 cDirs += aSubResult[1] + 1;
2035 cFiles += aSubResult[2];
2036 cOthers += aSubResult[3];
2037 elif eType is vboxcon.FsObjType_File:
2038 reporter.log4(' File "%s"' % oFsObjInfo.name);
2039 cFiles += 1;
2040 elif eType is vboxcon.FsObjType_Symlink:
2041 reporter.log4(' Symlink "%s" -- not tested yet' % oFsObjInfo.name);
2042 cOthers += 1;
2043 elif oTestVm.isWindows() \
2044 or oTestVm.isOS2() \
2045 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock,
2046 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut):
2047 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' %
2048 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,));
2049 else:
2050 cOthers += 1;
2051
2052 # Close the directory
2053 try:
2054 oCurDir.close();
2055 except:
2056 fRc = reporter.errorXcpt('sCurDir=%s' % (sCurDir));
2057
2058 return (fRc, cDirs, cFiles, cOthers);
2059
2060 def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (testfileset.TestDir) -> bool
2061 """
2062 Helper function to recursively read a guest directory tree specified in the current test.
2063 """
2064
2065 #
2066 # Process the directory.
2067 #
2068
2069 # Open the directory:
2070 try:
2071 oCurDir = oGuestSession.directoryOpen(oDir.sPath, '', None);
2072 except:
2073 return reporter.errorXcpt('sPath=%s' % (oDir.sPath,));
2074
2075 # Read the directory.
2076 dLeftUpper = dict(oDir.dChildrenUpper);
2077 cDot = 0;
2078 cDotDot = 0;
2079 fRc = True;
2080 while True:
2081 try:
2082 oFsObjInfo = oCurDir.read();
2083 except Exception as oXcpt:
2084 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
2085 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath,));
2086 break;
2087
2088 try:
2089 sName = oFsObjInfo.name;
2090 eType = oFsObjInfo.type;
2091 cbFile = oFsObjInfo.objectSize;
2092 ## @todo check further attributes.
2093 except:
2094 fRc = reporter.errorXcpt();
2095 break;
2096
2097 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment:
2098 if sName in ('.', '..', ):
2099 if eType != vboxcon.FsObjType_Directory:
2100 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
2101 % (sName, eType, vboxcon.FsObjType_Directory));
2102 if sName == '.': cDot += 1;
2103 else: cDotDot += 1;
2104 else:
2105 # Find the child and remove it from the dictionary.
2106 sNameUpper = sName.upper();
2107 oFsObj = dLeftUpper.get(sNameUpper);
2108 if oFsObj is None:
2109 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!'
2110 % (sName, oDir.sPath, eType, cbFile,));
2111 else:
2112 del dLeftUpper[sNameUpper];
2113
2114 # Check type
2115 if isinstance(oFsObj, testfileset.TestDir):
2116 if eType != vboxcon.FsObjType_Directory:
2117 fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
2118 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
2119 elif isinstance(oFsObj, testfileset.TestFile):
2120 if eType != vboxcon.FsObjType_File:
2121 fRc = reporter.error('%s: expected file (%d), got eType=%d!'
2122 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,));
2123 else:
2124 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),));
2125
2126 # Check the name.
2127 if oFsObj.sName != sName:
2128 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,));
2129
2130 # Check the size if a file.
2131 if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent:
2132 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,));
2133
2134 ## @todo check timestamps and attributes.
2135
2136 # Close the directory
2137 try:
2138 oCurDir.close();
2139 except:
2140 fRc = reporter.errorXcpt('oDir.sPath=%s' % (oDir.sPath,));
2141
2142 # Any files left over?
2143 for sKey in dLeftUpper:
2144 oFsObj = dLeftUpper[sKey];
2145 fRc = reporter.error('%s: Was not returned! (%s)' % (oFsObj.sPath, type(oFsObj),));
2146
2147 # Check the dot and dot-dot counts.
2148 if cDot != 1:
2149 fRc = reporter.error('%s: Found %s "." entries, expected exactly 1!' % (oDir.sPath, cDot,));
2150 if cDotDot != 1:
2151 fRc = reporter.error('%s: Found %s ".." entries, expected exactly 1!' % (oDir.sPath, cDotDot,));
2152
2153 #
2154 # Recurse into subdirectories using info from oDir.
2155 #
2156 for oFsObj in oDir.aoChildren:
2157 if isinstance(oFsObj, testfileset.TestDir):
2158 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc;
2159
2160 return fRc;
2161
2162 def gctrlExecDoTest(self, i, oTest, oRes, oGuestSession):
2163 """
2164 Wrapper function around gctrlExecute to provide more sanity checking
2165 when needed in actual execution tests.
2166 """
2167 reporter.log('Testing #%d, cmd="%s" ...' % (i, oTest.sCmd));
2168 fRcExec = self.gctrlExecute(oTest, oGuestSession, oRes.fRc);
2169 if fRcExec == oRes.fRc:
2170 fRc = True;
2171 if fRcExec is True:
2172 # Compare exit status / code on successful process execution.
2173 if oTest.uExitStatus != oRes.uExitStatus \
2174 or oTest.iExitCode != oRes.iExitCode:
2175 fRc = reporter.error('Test #%d (%s) failed: Got exit status + code %d,%d, expected %d,%d'
2176 % (i, oTest.asArgs, oTest.uExitStatus, oTest.iExitCode,
2177 oRes.uExitStatus, oRes.iExitCode));
2178
2179 # Compare test / result buffers on successful process execution.
2180 if oTest.sBuf is not None and oRes.sBuf is not None:
2181 if not utils.areBytesEqual(oTest.sBuf, oRes.sBuf):
2182 fRc = reporter.error('Test #%d (%s) failed: Got buffer\n%s (%d bytes), expected\n%s (%d bytes)'
2183 % (i, oTest.asArgs,
2184 map(hex, map(ord, oTest.sBuf)), len(oTest.sBuf),
2185 map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf)));
2186 reporter.log2('Test #%d passed: Buffers match (%d bytes)' % (i, len(oRes.sBuf)));
2187 elif oRes.sBuf and not oTest.sBuf:
2188 fRc = reporter.error('Test #%d (%s) failed: Got no buffer data, expected\n%s (%dbytes)' %
2189 (i, oTest.asArgs, map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf),));
2190
2191 if oRes.cbStdOut is not None and oRes.cbStdOut != oTest.cbStdOut:
2192 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stdout data, expected %d'
2193 % (i, oTest.asArgs, oTest.cbStdOut, oRes.cbStdOut));
2194 if oRes.cbStdErr is not None and oRes.cbStdErr != oTest.cbStdErr:
2195 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stderr data, expected %d'
2196 % (i, oTest.asArgs, oTest.cbStdErr, oRes.cbStdErr));
2197 else:
2198 fRc = reporter.error('Test #%d (%s) failed: Got %s, expected %s' % (i, oTest.asArgs, fRcExec, oRes.fRc));
2199 return fRc;
2200
2201 def gctrlExecute(self, oTest, oGuestSession, fIsError): # pylint: disable=too-many-statements
2202 """
2203 Helper function to execute a program on a guest, specified in the current test.
2204
2205 Note! This weirdo returns results (process exitcode and status) in oTest.
2206 """
2207 fRc = True; # Be optimistic.
2208
2209 # Reset the weird result stuff:
2210 oTest.cbStdOut = 0;
2211 oTest.cbStdErr = 0;
2212 oTest.sBuf = '';
2213 oTest.uExitStatus = 0;
2214 oTest.iExitCode = 0;
2215
2216 ## @todo Compare execution timeouts!
2217 #tsStart = base.timestampMilli();
2218
2219 try:
2220 reporter.log2('Using session user=%s, sDomain=%s, name=%s, timeout=%d'
2221 % (oGuestSession.user, oGuestSession.domain, oGuestSession.name, oGuestSession.timeout,));
2222 except:
2223 return reporter.errorXcpt();
2224
2225 #
2226 # Start the process:
2227 #
2228 reporter.log2('Executing sCmd=%s, afFlags=%s, timeoutMS=%d, asArgs=%s, asEnv=%s'
2229 % (oTest.sCmd, oTest.afFlags, oTest.timeoutMS, limitString(oTest.asArgs), limitString(oTest.aEnv),));
2230 try:
2231 oProcess = oGuestSession.processCreate(oTest.sCmd,
2232 oTest.asArgs if self.oTstDrv.fpApiVer >= 5.0 else oTest.asArgs[1:],
2233 oTest.aEnv, oTest.afFlags, oTest.timeoutMS);
2234 except:
2235 reporter.maybeErrXcpt(fIsError, 'type=%s, asArgs=%s' % (type(oTest.asArgs), oTest.asArgs,));
2236 return False;
2237 if oProcess is None:
2238 return reporter.error('oProcess is None! (%s)' % (oTest.asArgs,));
2239
2240 #time.sleep(5); # try this if you want to see races here.
2241
2242 # Wait for the process to start properly:
2243 reporter.log2('Process start requested, waiting for start (%dms) ...' % (oTest.timeoutMS,));
2244 iPid = -1;
2245 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Start, ];
2246 try:
2247 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
2248 except:
2249 reporter.maybeErrXcpt(fIsError, 'waitforArray failed for asArgs=%s' % (oTest.asArgs,));
2250 fRc = False;
2251 else:
2252 try:
2253 eStatus = oProcess.status;
2254 iPid = oProcess.PID;
2255 except:
2256 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2257 else:
2258 reporter.log2('Wait result returned: %d, current process status is: %d' % (eWaitResult, eStatus,));
2259
2260 #
2261 # Wait for the process to run to completion if necessary.
2262 #
2263 # Note! The above eWaitResult return value can be ignored as it will
2264 # (mostly) reflect the process status anyway.
2265 #
2266 if eStatus == vboxcon.ProcessStatus_Started:
2267
2268 # What to wait for:
2269 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate, ];
2270 if vboxcon.ProcessCreateFlag_WaitForStdOut in oTest.afFlags:
2271 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdOut);
2272 if vboxcon.ProcessCreateFlag_WaitForStdErr in oTest.afFlags:
2273 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdErr);
2274 ## @todo Add vboxcon.ProcessWaitForFlag_StdIn.
2275
2276 reporter.log2('Process (PID %d) started, waiting for termination (%dms), aeWaitFor=%s ...'
2277 % (iPid, oTest.timeoutMS, aeWaitFor));
2278 acbFdOut = [0,0,0];
2279 while True:
2280 try:
2281 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
2282 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
2283 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
2284 try: oProcess.close();
2285 except: pass;
2286 break;
2287 except:
2288 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2289 break;
2290 #reporter.log2('Wait returned: %d' % (eWaitResult,));
2291
2292 # Process output:
2293 for eFdResult, iFd, sFdNm in [ (vboxcon.ProcessWaitResult_StdOut, 1, 'stdout'),
2294 (vboxcon.ProcessWaitResult_StdErr, 2, 'stderr'), ]:
2295 if eWaitResult in (eFdResult, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
2296 try:
2297 abBuf = oProcess.read(iFd, 64 * 1024, oTest.timeoutMS);
2298 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
2299 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
2300 try: oProcess.close();
2301 except: pass;
2302 except:
2303 reporter.maybeErrXcpt(fIsError, 'asArgs=%s' % (oTest.asArgs,));
2304 else:
2305 if abBuf:
2306 reporter.log2('Process (PID %d) got %d bytes of %s data (type: %s)'
2307 % (iPid, len(abBuf), sFdNm, type(abBuf)));
2308 if reporter.getVerbosity() >= 4:
2309 sBuf = '';
2310 if sys.version_info >= (2, 7):
2311 if isinstance(abBuf, memoryview): ## @todo Why is this happening?
2312 abBuf = abBuf.tobytes();
2313 sBuf = abBuf.decode("utf-8");
2314 if sys.version_info <= (2, 7):
2315 if isinstance(abBuf, buffer): # (for 3.0+) pylint: disable=undefined-variable
2316 sBuf = str(abBuf);
2317 for sLine in sBuf.splitlines():
2318 reporter.log4('%s: %s' % (sFdNm, sLine));
2319 acbFdOut[iFd] += len(abBuf);
2320 oTest.sBuf = abBuf; ## @todo Figure out how to uniform + append!
2321
2322 ## Process input (todo):
2323 #if eWaitResult in (vboxcon.ProcessWaitResult_StdIn, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
2324 # reporter.log2('Process (PID %d) needs stdin data' % (iPid,));
2325
2326 # Termination or error?
2327 if eWaitResult in (vboxcon.ProcessWaitResult_Terminate,
2328 vboxcon.ProcessWaitResult_Error,
2329 vboxcon.ProcessWaitResult_Timeout,):
2330 try: eStatus = oProcess.status;
2331 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2332 reporter.log2('Process (PID %d) reported terminate/error/timeout: %d, status: %d'
2333 % (iPid, eWaitResult, eStatus,));
2334 break;
2335
2336 # End of the wait loop.
2337 _, oTest.cbStdOut, oTest.cbStdErr = acbFdOut;
2338
2339 try: eStatus = oProcess.status;
2340 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2341 reporter.log2('Final process status (PID %d) is: %d' % (iPid, eStatus));
2342 reporter.log2('Process (PID %d) %d stdout, %d stderr' % (iPid, oTest.cbStdOut, oTest.cbStdErr));
2343
2344 #
2345 # Get the final status and exit code of the process.
2346 #
2347 try:
2348 oTest.uExitStatus = oProcess.status;
2349 oTest.iExitCode = oProcess.exitCode;
2350 except:
2351 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2352 reporter.log2('Process (PID %d) has exit code: %d; status: %d ' % (iPid, oTest.iExitCode, oTest.uExitStatus));
2353 return fRc;
2354
2355 def testGuestCtrlSessionEnvironment(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2356 """
2357 Tests the guest session environment changes.
2358 """
2359 aoTests = [
2360 # Check basic operations.
2361 tdTestSessionEx([ # Initial environment is empty.
2362 tdStepSessionCheckEnv(),
2363 # Check clearing empty env.
2364 tdStepSessionClearEnv(),
2365 tdStepSessionCheckEnv(),
2366 # Check set.
2367 tdStepSessionSetEnv('FOO', 'BAR'),
2368 tdStepSessionCheckEnv(['FOO=BAR',]),
2369 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
2370 tdStepSessionClearEnv(),
2371 tdStepSessionCheckEnv(),
2372 # Check unset.
2373 tdStepSessionUnsetEnv('BAR'),
2374 tdStepSessionCheckEnv(['BAR']),
2375 tdStepSessionClearEnv(),
2376 tdStepSessionCheckEnv(),
2377 # Set + unset.
2378 tdStepSessionSetEnv('FOO', 'BAR'),
2379 tdStepSessionCheckEnv(['FOO=BAR',]),
2380 tdStepSessionUnsetEnv('FOO'),
2381 tdStepSessionCheckEnv(['FOO']),
2382 # Bulk environment changes (via attrib) (shall replace existing 'FOO').
2383 tdStepSessionBulkEnv( ['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
2384 tdStepSessionCheckEnv(['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
2385 ]),
2386 tdTestSessionEx([ # Check that setting the same value several times works.
2387 tdStepSessionSetEnv('FOO','BAR'),
2388 tdStepSessionCheckEnv([ 'FOO=BAR',]),
2389 tdStepSessionSetEnv('FOO','BAR2'),
2390 tdStepSessionCheckEnv([ 'FOO=BAR2',]),
2391 tdStepSessionSetEnv('FOO','BAR3'),
2392 tdStepSessionCheckEnv([ 'FOO=BAR3',]),
2393 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
2394 # Add a little unsetting to the mix.
2395 tdStepSessionSetEnv('BAR', 'BEAR'),
2396 tdStepSessionCheckEnv([ 'FOO=BAR3', 'BAR=BEAR',]),
2397 tdStepSessionUnsetEnv('FOO'),
2398 tdStepSessionCheckEnv([ 'FOO', 'BAR=BEAR',]),
2399 tdStepSessionSetEnv('FOO','BAR4'),
2400 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR',]),
2401 # The environment is case sensitive.
2402 tdStepSessionSetEnv('foo','BAR5'),
2403 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo=BAR5']),
2404 tdStepSessionUnsetEnv('foo'),
2405 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo']),
2406 ]),
2407 tdTestSessionEx([ # Bulk settings merges stuff, last entry standing.
2408 tdStepSessionBulkEnv(['FOO=bar', 'foo=bar', 'FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
2409 tdStepSessionCheckEnv(['FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
2410 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
2411 tdStepSessionBulkEnv(['2=1+1', 'FOO=doofus2', ]),
2412 tdStepSessionCheckEnv(['2=1+1', 'FOO=doofus2' ]),
2413 ]),
2414 # Invalid variable names.
2415 tdTestSessionEx([
2416 tdStepSessionSetEnv('', 'FOO', vbox.ComError.E_INVALIDARG),
2417 tdStepSessionCheckEnv(),
2418 tdStepRequireMinimumApiVer(5.0), # 4.3 is too relaxed checking input!
2419 tdStepSessionBulkEnv(['', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2420 tdStepSessionCheckEnv(),
2421 tdStepSessionSetEnv('FOO=', 'BAR', vbox.ComError.E_INVALIDARG),
2422 tdStepSessionCheckEnv(),
2423 ]),
2424 # A bit more weird keys/values.
2425 tdTestSessionEx([ tdStepSessionSetEnv('$$$', ''),
2426 tdStepSessionCheckEnv([ '$$$=',]), ]),
2427 tdTestSessionEx([ tdStepSessionSetEnv('$$$', '%%%'),
2428 tdStepSessionCheckEnv([ '$$$=%%%',]),
2429 ]),
2430 tdTestSessionEx([ tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
2431 tdStepSessionSetEnv(u'ß$%ß&', ''),
2432 tdStepSessionCheckEnv([ u'ß$%ß&=',]),
2433 ]),
2434 # Misc stuff.
2435 tdTestSessionEx([ tdStepSessionSetEnv('FOO', ''),
2436 tdStepSessionCheckEnv(['FOO=',]),
2437 ]),
2438 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
2439 tdStepSessionCheckEnv(['FOO=BAR',])
2440 ],),
2441 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
2442 tdStepSessionSetEnv('BAR', 'BAZ'),
2443 tdStepSessionCheckEnv([ 'FOO=BAR', 'BAR=BAZ',]),
2444 ]),
2445 ];
2446 # Leading '=' in the name is okay for windows guests in 6.1 and later (for driver letter CWDs).
2447 if (self.oTstDrv.fpApiVer < 6.1 and self.oTstDrv.fpApiVer >= 5.0) or not oTestVm.isWindows():
2448 aoTests.append(tdTestSessionEx([tdStepSessionSetEnv('=', '===', vbox.ComError.E_INVALIDARG),
2449 tdStepSessionCheckEnv(),
2450 tdStepSessionSetEnv('=FOO', 'BAR', vbox.ComError.E_INVALIDARG),
2451 tdStepSessionCheckEnv(),
2452 tdStepSessionBulkEnv(['=', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2453 tdStepSessionCheckEnv(),
2454 tdStepSessionBulkEnv(['=FOO', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2455 tdStepSessionCheckEnv(),
2456 tdStepSessionBulkEnv(['=D:=D:/tmp', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2457 tdStepSessionCheckEnv(),
2458 tdStepSessionSetEnv('=D:', 'D:/temp', vbox.ComError.E_INVALIDARG),
2459 tdStepSessionCheckEnv(),
2460 ]));
2461 elif self.oTstDrv.fpApiVer >= 6.1 and oTestVm.isWindows():
2462 aoTests.append(tdTestSessionEx([tdStepSessionSetEnv('=D:', 'D:/tmp'),
2463 tdStepSessionCheckEnv(['=D:=D:/tmp',]),
2464 tdStepSessionBulkEnv(['=D:=D:/temp', '=FOO', 'foo=bar']),
2465 tdStepSessionCheckEnv(['=D:=D:/temp', '=FOO', 'foo=bar']),
2466 tdStepSessionUnsetEnv('=D:'),
2467 tdStepSessionCheckEnv(['=D:', '=FOO', 'foo=bar']),
2468 ]));
2469
2470 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'SessionEnv');
2471
2472 def testGuestCtrlSession(self, oSession, oTxsSession, oTestVm):
2473 """
2474 Tests the guest session handling.
2475 """
2476
2477 #
2478 # Tests:
2479 #
2480 atTests = [
2481 # Invalid parameters.
2482 [ tdTestSession(sUser = ''), tdTestResultSession() ],
2483 # User account without a passwort - forbidden.
2484 [ tdTestSession(sPassword = "" ), tdTestResultSession() ],
2485 # Various wrong credentials.
2486 # Note! Only windows cares about sDomain, the other guests ignores it.
2487 # Note! On Guest Additions < 4.3 this always succeeds because these don't
2488 # support creating dedicated sessions. Instead, guest process creation
2489 # then will fail. See note below.
2490 [ tdTestSession(sPassword = 'bar'), tdTestResultSession() ],
2491 [ tdTestSession(sUser = 'foo', sPassword = 'bar'), tdTestResultSession() ],
2492 [ tdTestSession(sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
2493 [ tdTestSession(sUser = 'foo', sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
2494 ];
2495 if oTestVm.isWindows(): # domain is ignored elsewhere.
2496 atTests.append([ tdTestSession(sDomain = 'boo'), tdTestResultSession() ]);
2497
2498 # Finally, correct credentials.
2499 atTests.append([ tdTestSession(), tdTestResultSession(fRc = True, cNumSessions = 1) ]);
2500
2501 #
2502 # Run the tests.
2503 #
2504 fRc = True;
2505 for (i, tTest) in enumerate(atTests):
2506 oCurTest = tTest[0] # type: tdTestSession
2507 oCurRes = tTest[1] # type: tdTestResult
2508
2509 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2510 reporter.log('Testing #%d, user="%s", sPassword="%s", sDomain="%s" ...'
2511 % (i, oCurTest.oCreds.sUser, oCurTest.oCreds.sPassword, oCurTest.oCreds.sDomain));
2512 sCurGuestSessionName = 'testGuestCtrlSession: Test #%d' % (i,);
2513 fRc2, oCurGuestSession = oCurTest.createSession(sCurGuestSessionName, fIsError = oCurRes.fRc);
2514
2515 # See note about < 4.3 Guest Additions above.
2516 uProtocolVersion = 2;
2517 if oCurGuestSession is not None:
2518 try:
2519 uProtocolVersion = oCurGuestSession.protocolVersion;
2520 except:
2521 fRc = reporter.errorXcpt('Test #%d' % (i,));
2522
2523 if uProtocolVersion >= 2 and fRc2 is not oCurRes.fRc:
2524 fRc = reporter.error('Test #%d failed: Session creation failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
2525
2526 if fRc2 and oCurGuestSession is None:
2527 fRc = reporter.error('Test #%d failed: no session object' % (i,));
2528 fRc2 = False;
2529
2530 if fRc2:
2531 if uProtocolVersion >= 2: # For Guest Additions < 4.3 getSessionCount() always will return 1.
2532 cCurSessions = oCurTest.getSessionCount(self.oTstDrv.oVBoxMgr);
2533 if cCurSessions != oCurRes.cNumSessions:
2534 fRc = reporter.error('Test #%d failed: Session count does not match: Got %d, expected %d'
2535 % (i, cCurSessions, oCurRes.cNumSessions));
2536 try:
2537 sObjName = oCurGuestSession.name;
2538 except:
2539 fRc = reporter.errorXcpt('Test #%d' % (i,));
2540 else:
2541 if sObjName != sCurGuestSessionName:
2542 fRc = reporter.error('Test #%d failed: Session name does not match: Got "%s", expected "%s"'
2543 % (i, sObjName, sCurGuestSessionName));
2544 fRc2 = oCurTest.closeSession();
2545 if fRc2 is False:
2546 fRc = reporter.error('Test #%d failed: Session could not be closed' % (i,));
2547
2548 if fRc is False:
2549 return (False, oTxsSession);
2550
2551 #
2552 # Multiple sessions.
2553 #
2554 cMaxGuestSessions = 31; # Maximum number of concurrent guest session allowed.
2555 # Actually, this is 32, but we don't test session 0.
2556 aoMultiSessions = {};
2557 reporter.log2('Opening multiple guest tsessions at once ...');
2558 for i in xrange(cMaxGuestSessions + 1):
2559 aoMultiSessions[i] = tdTestSession(sSessionName = 'MultiSession #%d' % (i,));
2560 aoMultiSessions[i].setEnvironment(oSession, oTxsSession, oTestVm);
2561
2562 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
2563 reporter.log2('MultiSession test #%d count is %d' % (i, cCurSessions));
2564 if cCurSessions != i:
2565 return (reporter.error('MultiSession count is %d, expected %d' % (cCurSessions, i)), oTxsSession);
2566 fRc2, _ = aoMultiSessions[i].createSession('MultiSession #%d' % (i,), i < cMaxGuestSessions);
2567 if fRc2 is not True:
2568 if i < cMaxGuestSessions:
2569 return (reporter.error('MultiSession #%d test failed' % (i,)), oTxsSession);
2570 reporter.log('MultiSession #%d exceeded concurrent guest session count, good' % (i,));
2571 break;
2572
2573 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
2574 if cCurSessions is not cMaxGuestSessions:
2575 return (reporter.error('Final session count %d, expected %d ' % (cCurSessions, cMaxGuestSessions,)), oTxsSession);
2576
2577 reporter.log2('Closing MultiSessions ...');
2578 for i in xrange(cMaxGuestSessions):
2579 # Close this session:
2580 oClosedGuestSession = aoMultiSessions[i].oGuestSession;
2581 fRc2 = aoMultiSessions[i].closeSession();
2582 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr)
2583 reporter.log2('MultiSession #%d count is %d' % (i, cCurSessions,));
2584 if fRc2 is False:
2585 fRc = reporter.error('Closing MultiSession #%d failed' % (i,));
2586 elif cCurSessions != cMaxGuestSessions - (i + 1):
2587 fRc = reporter.error('Expected %d session after closing #%d, got %d instead'
2588 % (cMaxGuestSessions - (i + 1), cCurSessions, i,));
2589 assert aoMultiSessions[i].oGuestSession is None or not fRc2;
2590 ## @todo any way to check that the session is closed other than the 'sessions' attribute?
2591
2592 # Try check that none of the remaining sessions got closed.
2593 try:
2594 aoGuestSessions = self.oTstDrv.oVBoxMgr.getArray(atTests[0][0].oGuest, 'sessions');
2595 except:
2596 return (reporter.errorXcpt('i=%d/%d' % (i, cMaxGuestSessions,)), oTxsSession);
2597 if oClosedGuestSession in aoGuestSessions:
2598 fRc = reporter.error('i=%d/%d: %s should not be in %s'
2599 % (i, cMaxGuestSessions, oClosedGuestSession, aoGuestSessions));
2600 if i + 1 < cMaxGuestSessions: # Not sure what xrange(2,2) does...
2601 for j in xrange(i + 1, cMaxGuestSessions):
2602 if aoMultiSessions[j].oGuestSession not in aoGuestSessions:
2603 fRc = reporter.error('i=%d/j=%d/%d: %s should be in %s'
2604 % (i, j, cMaxGuestSessions, aoMultiSessions[j].oGuestSession, aoGuestSessions));
2605 ## @todo any way to check that they work?
2606
2607 ## @todo Test session timeouts.
2608
2609 return (fRc, oTxsSession);
2610
2611 def testGuestCtrlSessionFileRefs(self, oSession, oTxsSession, oTestVm):
2612 """
2613 Tests the guest session file reference handling.
2614 """
2615
2616 # Find a file to play around with:
2617 sFile = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
2618
2619 # Use credential defaults.
2620 oCreds = tdCtxCreds();
2621 oCreds.applyDefaultsIfNotSet(oTestVm);
2622
2623 # Number of stale guest files to create.
2624 cStaleFiles = 10;
2625
2626 #
2627 # Start a session.
2628 #
2629 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2630 try:
2631 oGuest = oSession.o.console.guest;
2632 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionFileRefs");
2633 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2634 except:
2635 return (reporter.errorXcpt(), oTxsSession);
2636
2637 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2638 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2639 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2640 reporter.log('Session successfully started');
2641
2642 #
2643 # Open guest files and "forget" them (stale entries).
2644 # For them we don't have any references anymore intentionally.
2645 #
2646 reporter.log2('Opening stale files');
2647 fRc = True;
2648 for i in xrange(0, cStaleFiles):
2649 try:
2650 if self.oTstDrv.fpApiVer >= 5.0:
2651 oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly, vboxcon.FileOpenAction_OpenExisting, 0);
2652 else:
2653 oGuestSession.fileOpen(sFile, "r", "oe", 0);
2654 # Note: Use a timeout in the call above for not letting the stale processes
2655 # hanging around forever. This can happen if the installed Guest Additions
2656 # do not support terminating guest processes.
2657 except:
2658 fRc = reporter.errorXcpt('Opening stale file #%d failed:' % (i,));
2659 break;
2660
2661 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2662 except: fRc = reporter.errorXcpt();
2663 else:
2664 if cFiles != cStaleFiles:
2665 fRc = reporter.error('Got %d stale files, expected %d' % (cFiles, cStaleFiles));
2666
2667 if fRc is True:
2668 #
2669 # Open non-stale files and close them again.
2670 #
2671 reporter.log2('Opening non-stale files');
2672 aoFiles = [];
2673 for i in xrange(0, cStaleFiles):
2674 try:
2675 if self.oTstDrv.fpApiVer >= 5.0:
2676 oCurFile = oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly,
2677 vboxcon.FileOpenAction_OpenExisting, 0);
2678 else:
2679 oCurFile = oGuestSession.fileOpen(sFile, "r", "oe", 0);
2680 aoFiles.append(oCurFile);
2681 except:
2682 fRc = reporter.errorXcpt('Opening non-stale file #%d failed:' % (i,));
2683 break;
2684
2685 # Check the count.
2686 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2687 except: fRc = reporter.errorXcpt();
2688 else:
2689 if cFiles != cStaleFiles * 2:
2690 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles * 2));
2691
2692 # Close them.
2693 reporter.log2('Closing all non-stale files again ...');
2694 for i, oFile in enumerate(aoFiles):
2695 try:
2696 oFile.close();
2697 except:
2698 fRc = reporter.errorXcpt('Closing non-stale file #%d failed:' % (i,));
2699
2700 # Check the count again.
2701 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2702 except: fRc = reporter.errorXcpt();
2703 # Here we count the stale files (that is, files we don't have a reference
2704 # anymore for) and the opened and then closed non-stale files (that we still keep
2705 # a reference in aoFiles[] for).
2706 if cFiles != cStaleFiles:
2707 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles));
2708
2709 #
2710 # Check that all (referenced) non-stale files are now in the "closed" state.
2711 #
2712 reporter.log2('Checking statuses of all non-stale files ...');
2713 for i, oFile in enumerate(aoFiles):
2714 try:
2715 eFileStatus = aoFiles[i].status;
2716 except:
2717 fRc = reporter.errorXcpt('Checking status of file #%d failed:' % (i,));
2718 else:
2719 if eFileStatus != vboxcon.FileStatus_Closed:
2720 fRc = reporter.error('Non-stale file #%d has status %d, expected %d'
2721 % (i, eFileStatus, vboxcon.FileStatus_Closed));
2722
2723 if fRc is True:
2724 reporter.log2('All non-stale files closed');
2725
2726 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2727 except: fRc = reporter.errorXcpt();
2728 else: reporter.log2('Final guest session file count: %d' % (cFiles,));
2729
2730 #
2731 # Now try to close the session and see what happens.
2732 # Note! Session closing is why we've been doing all the 'if fRc is True' stuff above rather than returning.
2733 #
2734 reporter.log2('Closing guest session ...');
2735 try:
2736 oGuestSession.close();
2737 except:
2738 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2739
2740 return (fRc, oTxsSession);
2741
2742 #def testGuestCtrlSessionDirRefs(self, oSession, oTxsSession, oTestVm):
2743 # """
2744 # Tests the guest session directory reference handling.
2745 # """
2746
2747 # fRc = True;
2748 # return (fRc, oTxsSession);
2749
2750 def testGuestCtrlSessionProcRefs(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2751 """
2752 Tests the guest session process reference handling.
2753 """
2754
2755 sCmd = self.oTstDrv.getGuestSystemShell(oTestVm);
2756 asArgs = [sCmd,];
2757
2758 # Use credential defaults.
2759 oCreds = tdCtxCreds();
2760 oCreds.applyDefaultsIfNotSet(oTestVm);
2761
2762 # Number of stale guest processes to create.
2763 cStaleProcs = 10;
2764
2765 #
2766 # Start a session.
2767 #
2768 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2769 try:
2770 oGuest = oSession.o.console.guest;
2771 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionProcRefs");
2772 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2773 except:
2774 return (reporter.errorXcpt(), oTxsSession);
2775
2776 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2777 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2778 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2779 reporter.log('Session successfully started');
2780
2781 #
2782 # Fire off forever-running processes and "forget" them (stale entries).
2783 # For them we don't have any references anymore intentionally.
2784 #
2785 reporter.log2('Starting stale processes...');
2786 fRc = True;
2787 for i in xrange(0, cStaleProcs):
2788 try:
2789 oGuestSession.processCreate(sCmd,
2790 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], [],
2791 [ vboxcon.ProcessCreateFlag_WaitForStdOut ], 30 * 1000);
2792 # Note: Use a timeout in the call above for not letting the stale processes
2793 # hanging around forever. This can happen if the installed Guest Additions
2794 # do not support terminating guest processes.
2795 except:
2796 fRc = reporter.errorXcpt('Creating stale process #%d failed:' % (i,));
2797 break;
2798
2799 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2800 except: fRc = reporter.errorXcpt();
2801 else:
2802 if cProcesses != cStaleProcs:
2803 fRc = reporter.error('Got %d stale processes, expected %d' % (cProcesses, cStaleProcs));
2804
2805 if fRc is True:
2806 #
2807 # Fire off non-stale processes and wait for termination.
2808 #
2809 if oTestVm.isWindows() or oTestVm.isOS2():
2810 asArgs = [ sCmd, '/C', 'dir', '/S', self.oTstDrv.getGuestSystemDir(oTestVm), ];
2811 else:
2812 asArgs = [ sCmd, '-c', 'ls -la ' + self.oTstDrv.getGuestSystemDir(oTestVm), ];
2813 reporter.log2('Starting non-stale processes...');
2814 aoProcesses = [];
2815 for i in xrange(0, cStaleProcs):
2816 try:
2817 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2818 [], [], 0); # Infinite timeout.
2819 aoProcesses.append(oCurProc);
2820 except:
2821 fRc = reporter.errorXcpt('Creating non-stale process #%d failed:' % (i,));
2822 break;
2823
2824 reporter.log2('Waiting for non-stale processes to terminate...');
2825 for i, oProcess in enumerate(aoProcesses):
2826 try:
2827 eWaitResult = oProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 120 * 1000);
2828 eProcessStatus = oProcess.status;
2829 except:
2830 fRc = reporter.errorXcpt('Waiting for non-stale process #%d failed:' % (i,));
2831 else:
2832 if eProcessStatus != vboxcon.ProcessStatus_TerminatedNormally:
2833 fRc = reporter.error('Waiting for non-stale processes #%d resulted in status %d, expected %d (wr=%d)'
2834 % (i, eProcessStatus, vboxcon.ProcessStatus_TerminatedNormally, eWaitResult));
2835
2836 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2837 except: fRc = reporter.errorXcpt();
2838 else:
2839 # Here we count the stale processes (that is, processes we don't have a reference
2840 # anymore for) and the started + terminated non-stale processes (that we still keep
2841 # a reference in aoProcesses[] for).
2842 if cProcesses != (cStaleProcs * 2):
2843 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2844
2845 if fRc is True:
2846 reporter.log2('All non-stale processes terminated');
2847
2848 #
2849 # Fire off non-stale blocking processes which are terminated via terminate().
2850 #
2851 if oTestVm.isWindows() or oTestVm.isOS2():
2852 asArgs = [ sCmd, '/C', 'pause'];
2853 else:
2854 asArgs = [ sCmd ];
2855 reporter.log2('Starting blocking processes...');
2856 aoProcesses = [];
2857 for i in xrange(0, cStaleProcs):
2858 try:
2859 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2860 [], [], 30 * 1000);
2861 # Note: Use a timeout in the call above for not letting the stale processes
2862 # hanging around forever. This can happen if the installed Guest Additions
2863 # do not support terminating guest processes.
2864 aoProcesses.append(oCurProc);
2865 except:
2866 fRc = reporter.errorXcpt('Creating non-stale blocking process #%d failed:' % (i,));
2867 break;
2868
2869 reporter.log2('Terminating blocking processes...');
2870 for i, oProcess in enumerate(aoProcesses):
2871 try:
2872 oProcess.terminate();
2873 except: # Termination might not be supported, just skip and log it.
2874 reporter.logXcpt('Termination of blocking process #%d failed, skipped:' % (i,));
2875
2876 # There still should be 20 processes because we terminated the 10 newest ones.
2877 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2878 except: fRc = reporter.errorXcpt();
2879 else:
2880 if cProcesses != (cStaleProcs * 2):
2881 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2882 reporter.log2('Final guest session processes count: %d' % (cProcesses,));
2883
2884 #
2885 # Now try to close the session and see what happens.
2886 #
2887 reporter.log2('Closing guest session ...');
2888 try:
2889 oGuestSession.close();
2890 except:
2891 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2892
2893 return (fRc, oTxsSession);
2894
2895 def testGuestCtrlExec(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements
2896 """
2897 Tests the basic execution feature.
2898 """
2899
2900 # Paths:
2901 sVBoxControl = None; ## @todo Get path of installed Guest Additions. Later.
2902 sShell = self.oTstDrv.getGuestSystemShell(oTestVm);
2903 sShellOpt = '/C' if oTestVm.isWindows() or oTestVm.isOS2() else '-c';
2904 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
2905 sFileForReading = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
2906 if oTestVm.isWindows() or oTestVm.isOS2():
2907 sImageOut = self.oTstDrv.getGuestSystemShell(oTestVm);
2908 if oTestVm.isWindows():
2909 sVBoxControl = "C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\VBoxControl.exe";
2910 else:
2911 sImageOut = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'ls');
2912 if oTestVm.isLinux(): ## @todo check solaris and darwin.
2913 sVBoxControl = "/usr/bin/VBoxControl"; # Symlink
2914
2915 # Use credential defaults.
2916 oCreds = tdCtxCreds();
2917 oCreds.applyDefaultsIfNotSet(oTestVm);
2918
2919 atInvalid = [
2920 # Invalid parameters.
2921 [ tdTestExec(), tdTestResultExec() ],
2922 # Non-existent / invalid image.
2923 [ tdTestExec(sCmd = "non-existent"), tdTestResultExec() ],
2924 [ tdTestExec(sCmd = "non-existent2"), tdTestResultExec() ],
2925 # Use an invalid format string.
2926 [ tdTestExec(sCmd = "%$%%%&"), tdTestResultExec() ],
2927 # More stuff.
2928 [ tdTestExec(sCmd = u"ƒ‰‹ˆ÷‹¸"), tdTestResultExec() ],
2929 [ tdTestExec(sCmd = "???://!!!"), tdTestResultExec() ],
2930 [ tdTestExec(sCmd = "<>!\\"), tdTestResultExec() ],
2931 # Enable as soon as ERROR_BAD_DEVICE is implemented.
2932 #[ tdTestExec(sCmd = "CON", tdTestResultExec() ],
2933 ];
2934
2935 atExec = [];
2936 if oTestVm.isWindows() or oTestVm.isOS2():
2937 atExec += [
2938 # Basic execution.
2939 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2940 tdTestResultExec(fRc = True) ],
2941 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sFileForReading ]),
2942 tdTestResultExec(fRc = True) ],
2943 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir + '\\nonexist.dll' ]),
2944 tdTestResultExec(fRc = True, iExitCode = 1) ],
2945 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', '/wrongparam' ]),
2946 tdTestResultExec(fRc = True, iExitCode = 1) ],
2947 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2948 tdTestResultExec(fRc = True, iExitCode = 1) ],
2949 # StdOut.
2950 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2951 tdTestResultExec(fRc = True) ],
2952 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdout-non-existing' ]),
2953 tdTestResultExec(fRc = True, iExitCode = 1) ],
2954 # StdErr.
2955 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2956 tdTestResultExec(fRc = True) ],
2957 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stderr-non-existing' ]),
2958 tdTestResultExec(fRc = True, iExitCode = 1) ],
2959 # StdOut + StdErr.
2960 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2961 tdTestResultExec(fRc = True) ],
2962 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdouterr-non-existing' ]),
2963 tdTestResultExec(fRc = True, iExitCode = 1) ],
2964 ];
2965 # atExec.extend([
2966 # FIXME: Failing tests.
2967 # Environment variables.
2968 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2969 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2970 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2971 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2972 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2973 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2974 # aEnv = [ 'TEST_FOO=BAR' ],
2975 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2976 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2977 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2978 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2979 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2980 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2981
2982 ## @todo Create some files (or get files) we know the output size of to validate output length!
2983 ## @todo Add task which gets killed at some random time while letting the guest output something.
2984 #];
2985 else:
2986 atExec += [
2987 # Basic execution.
2988 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '-R', sSystemDir ]),
2989 tdTestResultExec(fRc = True) ],
2990 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sFileForReading ]),
2991 tdTestResultExec(fRc = True) ],
2992 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '--wrong-parameter' ]),
2993 tdTestResultExec(fRc = True, iExitCode = 2) ],
2994 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/non/existent' ]),
2995 tdTestResultExec(fRc = True, iExitCode = 2) ],
2996 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2997 tdTestResultExec(fRc = True, iExitCode = 127) ],
2998 # StdOut.
2999 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
3000 tdTestResultExec(fRc = True) ],
3001 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdout-non-existing' ]),
3002 tdTestResultExec(fRc = True, iExitCode = 2) ],
3003 # StdErr.
3004 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
3005 tdTestResultExec(fRc = True) ],
3006 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stderr-non-existing' ]),
3007 tdTestResultExec(fRc = True, iExitCode = 2) ],
3008 # StdOut + StdErr.
3009 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
3010 tdTestResultExec(fRc = True) ],
3011 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdouterr-non-existing' ]),
3012 tdTestResultExec(fRc = True, iExitCode = 2) ],
3013 ];
3014 # atExec.extend([
3015 # FIXME: Failing tests.
3016 # Environment variables.
3017 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
3018 # tdTestResultExec(fRc = True, iExitCode = 1) ]
3019 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
3020 #
3021 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3022 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
3023 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
3024 # aEnv = [ 'TEST_FOO=BAR' ],
3025 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3026 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
3027 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
3028 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
3029 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3030 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
3031
3032 ## @todo Create some files (or get files) we know the output size of to validate output length!
3033 ## @todo Add task which gets killed at some random time while letting the guest output something.
3034 #];
3035
3036 #
3037 #for iExitCode in xrange(0, 127):
3038 # atExec.append([ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'exit %s' % iExitCode ]),
3039 # tdTestResultExec(fRc = True, iExitCode = iExitCode) ]);
3040
3041 if sVBoxControl \
3042 and self.oTstDrv.fpApiVer >= 6.0: # Investigate with this doesn't work on (<) 5.2.
3043 # Paths with spaces on windows.
3044 atExec.append([ tdTestExec(sCmd = sVBoxControl, asArgs = [ sVBoxControl, 'version' ],
3045 afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut,
3046 vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3047 tdTestResultExec(fRc = True) ]);
3048
3049 # Test very long arguments. Be careful when tweaking this to not break the tests.
3050 # Regarding paths:
3051 # - We have RTPATH_BIG_MAX (64K)
3052 # - MSDN says 32K for CreateFileW()
3053 # - On Windows, each path component must not be longer than MAX_PATH (260), see
3054 # https://docs.microsoft.com/en-us/windows/win32/fileio/filesystem-functionality-comparison#limits
3055 #
3056 # Old(er) Windows OSes tend to crash in cmd.exe, so skip this on these OSes.
3057 if self.oTstDrv.fpApiVer >= 6.1 \
3058 and oTestVm.sKind not in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
3059 sEndMarker = '--end-marker';
3060 if oTestVm.isWindows() \
3061 or oTestVm.isOS2():
3062 sCmd = sShell;
3063 else:
3064 sCmd = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'echo');
3065
3066 for _ in xrange(0, 16):
3067 if oTestVm.isWindows() \
3068 or oTestVm.isOS2():
3069 asArgs = [ sShell, sShellOpt, "echo" ];
3070 else:
3071 asArgs = [ sCmd ];
3072
3073 # Append a random number of arguments with random length.
3074 for _ in xrange(0, self.oTestFiles.oRandom.randrange(1, 64)):
3075 asArgs.append(''.join(random.choice(string.ascii_lowercase)
3076 for _ in range(self.oTestFiles.oRandom.randrange(1, 196))));
3077
3078 asArgs.append(sEndMarker);
3079
3080 reporter.log2('asArgs=%s (%d args), type=%s' % (limitString(asArgs), len(asArgs), type(asArgs)));
3081
3082 ## @todo Check limits; on Ubuntu with 256KB IPRT returns VERR_NOT_IMPLEMENTED.
3083 # Use a higher timeout (15 min) than usual for these long checks.
3084 atExec.append([ tdTestExec(sCmd, asArgs,
3085 afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut,
3086 vboxcon.ProcessCreateFlag_WaitForStdErr ],
3087 timeoutMS = 15 * 60 * 1000),
3088 tdTestResultExec(fRc = True) ]);
3089
3090 # Build up the final test array for the first batch.
3091 atTests = atInvalid + atExec;
3092
3093 #
3094 # First batch: One session per guest process.
3095 #
3096 reporter.log('One session per guest process ...');
3097 fRc = True;
3098 for (i, tTest) in enumerate(atTests):
3099 oCurTest = tTest[0] # type: tdTestExec
3100 oCurRes = tTest[1] # type: tdTestResultExec
3101 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3102 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlExec: Test #%d' % (i,));
3103 if fRc2 is not True:
3104 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3105 break;
3106 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession) and fRc;
3107 fRc = oCurTest.closeSession() and fRc;
3108
3109 reporter.log('Execution of all tests done, checking for stale sessions');
3110
3111 # No sessions left?
3112 try:
3113 aSessions = self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions');
3114 except:
3115 fRc = reporter.errorXcpt();
3116 else:
3117 cSessions = len(aSessions);
3118 if cSessions != 0:
3119 fRc = reporter.error('Found %d stale session(s), expected 0:' % (cSessions,));
3120 for (i, aSession) in enumerate(aSessions):
3121 try: reporter.log(' Stale session #%d ("%s")' % (aSession.id, aSession.name));
3122 except: reporter.errorXcpt();
3123
3124 if fRc is not True:
3125 return (fRc, oTxsSession);
3126
3127 reporter.log('Now using one guest session for all tests ...');
3128
3129 #
3130 # Second batch: One session for *all* guest processes.
3131 #
3132
3133 # Create session.
3134 reporter.log('Creating session for all tests ...');
3135 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
3136 try:
3137 oGuest = oSession.o.console.guest;
3138 oCurGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain,
3139 'testGuestCtrlExec: One session for all tests');
3140 except:
3141 return (reporter.errorXcpt(), oTxsSession);
3142
3143 try:
3144 eWaitResult = oCurGuestSession.waitForArray(aeWaitFor, 30 * 1000);
3145 except:
3146 fRc = reporter.errorXcpt('Waiting for guest session to start failed:');
3147 else:
3148 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3149 fRc = reporter.error('Session did not start successfully, returned wait result: %d' % (eWaitResult,));
3150 else:
3151 reporter.log('Session successfully started');
3152
3153 # Do the tests within this session.
3154 for (i, tTest) in enumerate(atTests):
3155 oCurTest = tTest[0] # type: tdTestExec
3156 oCurRes = tTest[1] # type: tdTestResultExec
3157
3158 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3159 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
3160 if fRc is False:
3161 break;
3162
3163 # Close the session.
3164 reporter.log2('Closing guest session ...');
3165 try:
3166 oCurGuestSession.close();
3167 oCurGuestSession = None;
3168 except:
3169 fRc = reporter.errorXcpt('Closing guest session failed:');
3170
3171 # No sessions left?
3172 reporter.log('Execution of all tests done, checking for stale sessions again');
3173 try: cSessions = len(self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions'));
3174 except: fRc = reporter.errorXcpt();
3175 else:
3176 if cSessions != 0:
3177 fRc = reporter.error('Found %d stale session(s), expected 0' % (cSessions,));
3178 return (fRc, oTxsSession);
3179
3180 def threadForTestGuestCtrlSessionReboot(self, oGuestProcess):
3181 """
3182 Thread routine which waits for the stale guest process getting terminated (or some error)
3183 while the main test routine reboots the guest. It then compares the expected guest process result
3184 and logs an error if appropriate.
3185 """
3186 reporter.log('Waiting for process to get terminated at reboot ...');
3187 try:
3188 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate ], 5 * 60 * 1000);
3189 except:
3190 return reporter.errorXcpt('waitForArray failed');
3191 try:
3192 eStatus = oGuestProcess.status
3193 except:
3194 return reporter.errorXcpt('failed to get status (wait result %d)' % (eWaitResult,));
3195
3196 if eWaitResult == vboxcon.ProcessWaitResult_Terminate and eStatus == vboxcon.ProcessStatus_Down:
3197 reporter.log('Stale process was correctly terminated (status: down)');
3198 return True;
3199
3200 return reporter.error('Process wait across reboot failed: eWaitResult=%d, expected %d; eStatus=%d, expected %d'
3201 % (eWaitResult, vboxcon.ProcessWaitResult_Terminate, eStatus, vboxcon.ProcessStatus_Down,));
3202
3203 def testGuestCtrlSessionReboot(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3204 """
3205 Tests guest object notifications when a guest gets rebooted / shutdown.
3206
3207 These notifications gets sent from the guest sessions in order to make API clients
3208 aware of guest session changes.
3209
3210 To test that we create a stale guest process and trigger a reboot of the guest.
3211 """
3212
3213 ## @todo backport fixes to 6.0 and maybe 5.2
3214 if self.oTstDrv.fpApiVer <= 6.0:
3215 reporter.log('Skipping: Required fixes not yet backported!');
3216 return None;
3217
3218 # Use credential defaults.
3219 oCreds = tdCtxCreds();
3220 oCreds.applyDefaultsIfNotSet(oTestVm);
3221
3222 fRc = True;
3223
3224 #
3225 # Start a session.
3226 #
3227 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
3228 try:
3229 oGuest = oSession.o.console.guest;
3230 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionReboot");
3231 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
3232 except:
3233 return (reporter.errorXcpt(), oTxsSession);
3234
3235 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
3236 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3237 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
3238 reporter.log('Session successfully started');
3239
3240 #
3241 # Create a process.
3242 #
3243 sImage = self.oTstDrv.getGuestSystemShell(oTestVm);
3244 asArgs = [ sImage, ];
3245 aEnv = [];
3246 afFlags = [];
3247 try:
3248 oGuestProcess = oGuestSession.processCreate(sImage,
3249 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], aEnv, afFlags,
3250 30 * 1000);
3251 except:
3252 fRc = reporter.error('Failed to start shell process (%s)' % (sImage,));
3253 else:
3254 try:
3255 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3256 except:
3257 fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
3258 else:
3259 # Check the result and state:
3260 try: eStatus = oGuestProcess.status;
3261 except: fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
3262 else:
3263 reporter.log2('Starting process wait result returned: %d; Process status is: %d' % (eWaitResult, eStatus,));
3264 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3265 fRc = reporter.error('wait for ProcessWaitForFlag_Start failed: %d, expected %d (Start)'
3266 % (eWaitResult, vboxcon.ProcessWaitResult_Start,));
3267 elif eStatus != vboxcon.ProcessStatus_Started:
3268 fRc = reporter.error('Unexpected process status after startup: %d, wanted %d (Started)'
3269 % (eStatus, vboxcon.ProcessStatus_Started,));
3270 else:
3271 # Create a thread that waits on the process to terminate
3272 reporter.log('Creating reboot thread ...');
3273 oThreadReboot = threading.Thread(target = self.threadForTestGuestCtrlSessionReboot,
3274 args = (oGuestProcess,),
3275 name = ('threadForTestGuestCtrlSessionReboot'));
3276 oThreadReboot.setDaemon(True);
3277 oThreadReboot.start();
3278
3279 # Not sure why this fudge is needed...
3280 reporter.log('5 second wait fudge before triggering reboot ...');
3281 self.oTstDrv.sleep(5);
3282
3283 # Do the reboot.
3284 reporter.log('Rebooting guest and reconnecting TXS ...');
3285 (oSession, oTxsSession) = self.oTstDrv.txsRebootAndReconnectViaTcp(oSession, oTxsSession,
3286 cMsTimeout = 3 * 60000);
3287 if not oSession or not oTxsSession:
3288 try: oGuestProcess.terminate();
3289 except: reporter.logXcpt();
3290 fRc = False;
3291
3292 reporter.log('Waiting for thread to finish ...');
3293 oThreadReboot.join();
3294
3295 #
3296 # Try make sure we don't leave with a stale process on failure.
3297 #
3298 try: oGuestProcess.terminate();
3299 except: reporter.logXcpt();
3300
3301 #
3302 # Close the session.
3303 #
3304 reporter.log2('Closing guest session ...');
3305 try:
3306 oGuestSession.close();
3307 except:
3308 fRc = reporter.errorXcpt();
3309
3310 return (fRc, oTxsSession);
3311
3312 def testGuestCtrlExecTimeout(self, oSession, oTxsSession, oTestVm):
3313 """
3314 Tests handling of timeouts of started guest processes.
3315 """
3316
3317 sShell = self.oTstDrv.getGuestSystemShell(oTestVm);
3318
3319 # Use credential defaults.
3320 oCreds = tdCtxCreds();
3321 oCreds.applyDefaultsIfNotSet(oTestVm);
3322
3323 #
3324 # Create a session.
3325 #
3326 try:
3327 oGuest = oSession.o.console.guest;
3328 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlExecTimeout");
3329 eWaitResult = oGuestSession.waitForArray([ vboxcon.GuestSessionWaitForFlag_Start, ], 30 * 1000);
3330 except:
3331 return (reporter.errorXcpt(), oTxsSession);
3332
3333 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
3334 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3335 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
3336 reporter.log('Session successfully started');
3337
3338 #
3339 # Create a process which never terminates and should timeout when
3340 # waiting for termination.
3341 #
3342 fRc = True;
3343 try:
3344 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
3345 [], [], 30 * 1000);
3346 except:
3347 fRc = reporter.errorXcpt();
3348 else:
3349 reporter.log('Waiting for process 1 being started ...');
3350 try:
3351 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3352 except:
3353 fRc = reporter.errorXcpt();
3354 else:
3355 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3356 fRc = reporter.error('Waiting for process 1 to start failed, got status %d' % (eWaitResult,));
3357 else:
3358 for msWait in (1, 32, 2000,):
3359 reporter.log('Waiting for process 1 to time out within %sms ...' % (msWait,));
3360 try:
3361 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], msWait);
3362 except:
3363 fRc = reporter.errorXcpt();
3364 break;
3365 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
3366 fRc = reporter.error('Waiting for process 1 did not time out in %sms as expected: %d'
3367 % (msWait, eWaitResult,));
3368 break;
3369 reporter.log('Waiting for process 1 timed out in %u ms, good' % (msWait,));
3370
3371 try:
3372 oCurProcess.terminate();
3373 except:
3374 reporter.errorXcpt();
3375 oCurProcess = None;
3376
3377 #
3378 # Create another process that doesn't terminate, but which will be killed by VBoxService
3379 # because it ran out of execution time (3 seconds).
3380 #
3381 try:
3382 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
3383 [], [], 3 * 1000);
3384 except:
3385 fRc = reporter.errorXcpt();
3386 else:
3387 reporter.log('Waiting for process 2 being started ...');
3388 try:
3389 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3390 except:
3391 fRc = reporter.errorXcpt();
3392 else:
3393 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3394 fRc = reporter.error('Waiting for process 2 to start failed, got status %d' % (eWaitResult,));
3395 else:
3396 reporter.log('Waiting for process 2 to get killed for running out of execution time ...');
3397 try:
3398 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 15 * 1000);
3399 except:
3400 fRc = reporter.errorXcpt();
3401 else:
3402 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
3403 fRc = reporter.error('Waiting for process 2 did not time out when it should, got wait result %d'
3404 % (eWaitResult,));
3405 else:
3406 reporter.log('Waiting for process 2 did not time out, good: %s' % (eWaitResult,));
3407 try:
3408 eStatus = oCurProcess.status;
3409 except:
3410 fRc = reporter.errorXcpt();
3411 else:
3412 if eStatus != vboxcon.ProcessStatus_TimedOutKilled:
3413 fRc = reporter.error('Status of process 2 wrong; excepted %d, got %d'
3414 % (vboxcon.ProcessStatus_TimedOutKilled, eStatus));
3415 else:
3416 reporter.log('Status of process 2 is TimedOutKilled (%d) is it should be.'
3417 % (vboxcon.ProcessStatus_TimedOutKilled,));
3418 try:
3419 oCurProcess.terminate();
3420 except:
3421 reporter.logXcpt();
3422 oCurProcess = None;
3423
3424 #
3425 # Clean up the session.
3426 #
3427 try:
3428 oGuestSession.close();
3429 except:
3430 fRc = reporter.errorXcpt();
3431
3432 return (fRc, oTxsSession);
3433
3434 def testGuestCtrlDirCreate(self, oSession, oTxsSession, oTestVm):
3435 """
3436 Tests creation of guest directories.
3437 """
3438
3439 sScratch = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'testGuestCtrlDirCreate');
3440
3441 atTests = [
3442 # Invalid stuff.
3443 [ tdTestDirCreate(sDirectory = '' ), tdTestResultFailure() ],
3444 # More unusual stuff.
3445 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '.') ), tdTestResultFailure() ],
3446 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '..') ), tdTestResultFailure() ],
3447 [ tdTestDirCreate(sDirectory = '..' ), tdTestResultFailure() ],
3448 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
3449 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
3450 [ tdTestDirCreate(sDirectory = '/' ), tdTestResultFailure() ],
3451 [ tdTestDirCreate(sDirectory = '/..' ), tdTestResultFailure() ],
3452 [ tdTestDirCreate(sDirectory = '/../' ), tdTestResultFailure() ],
3453 ];
3454 if oTestVm.isWindows() or oTestVm.isOS2():
3455 atTests.extend([
3456 [ tdTestDirCreate(sDirectory = 'C:\\' ), tdTestResultFailure() ],
3457 [ tdTestDirCreate(sDirectory = 'C:\\..' ), tdTestResultFailure() ],
3458 [ tdTestDirCreate(sDirectory = 'C:\\..\\' ), tdTestResultFailure() ],
3459 [ tdTestDirCreate(sDirectory = 'C:/' ), tdTestResultFailure() ],
3460 [ tdTestDirCreate(sDirectory = 'C:/.' ), tdTestResultFailure() ],
3461 [ tdTestDirCreate(sDirectory = 'C:/./' ), tdTestResultFailure() ],
3462 [ tdTestDirCreate(sDirectory = 'C:/..' ), tdTestResultFailure() ],
3463 [ tdTestDirCreate(sDirectory = 'C:/../' ), tdTestResultFailure() ],
3464 [ tdTestDirCreate(sDirectory = '\\\\uncrulez\\foo' ), tdTestResultFailure() ],
3465 ]);
3466 atTests.extend([
3467 # Existing directories and files.
3468 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemDir(oTestVm) ), tdTestResultFailure() ],
3469 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemShell(oTestVm) ), tdTestResultFailure() ],
3470 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemFileForReading(oTestVm) ), tdTestResultFailure() ],
3471 # Creating directories.
3472 [ tdTestDirCreate(sDirectory = sScratch ), tdTestResultSuccess() ],
3473 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
3474 afFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
3475 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
3476 afFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
3477 # Try format strings as directories.
3478 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo%sbar%sbaz%d' )), tdTestResultSuccess() ],
3479 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, '%f%%boo%%bar%RI32' )), tdTestResultSuccess() ],
3480 # Long random names.
3481 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(36, 28))),
3482 tdTestResultSuccess() ],
3483 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(140, 116))),
3484 tdTestResultSuccess() ],
3485 # Too long names. ASSUMES a guests has a 255 filename length limitation.
3486 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
3487 tdTestResultFailure() ],
3488 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
3489 tdTestResultFailure() ],
3490 # Missing directory in path.
3491 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo1', 'bar') ), tdTestResultFailure() ],
3492 ]);
3493
3494 fRc = True;
3495 for (i, tTest) in enumerate(atTests):
3496 oCurTest = tTest[0] # type: tdTestDirCreate
3497 oCurRes = tTest[1] # type: tdTestResult
3498 reporter.log('Testing #%d, sDirectory="%s" ...' % (i, limitString(oCurTest.sDirectory)));
3499
3500 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3501 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreate: Test #%d' % (i,));
3502 if fRc is False:
3503 return reporter.error('Test #%d failed: Could not create session' % (i,));
3504
3505 fRc = self.gctrlCreateDir(oCurTest, oCurRes, oCurGuestSession);
3506
3507 fRc = oCurTest.closeSession() and fRc;
3508 if fRc is False:
3509 fRc = reporter.error('Test #%d failed' % (i,));
3510
3511 return (fRc, oTxsSession);
3512
3513 def testGuestCtrlDirCreateTemp(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3514 """
3515 Tests creation of temporary directories.
3516 """
3517
3518 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3519 atTests = [
3520 # Invalid stuff (template must have one or more trailin 'X'es (upper case only), or a cluster of three or more).
3521 [ tdTestDirCreateTemp(sDirectory = ''), tdTestResultFailure() ],
3522 [ tdTestDirCreateTemp(sDirectory = sSystemDir, fMode = 1234), tdTestResultFailure() ],
3523 [ tdTestDirCreateTemp(sTemplate = 'xXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3524 [ tdTestDirCreateTemp(sTemplate = 'xxx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3525 [ tdTestDirCreateTemp(sTemplate = 'XXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3526 [ tdTestDirCreateTemp(sTemplate = 'bar', sDirectory = 'whatever', fMode = 0o700), tdTestResultFailure() ],
3527 [ tdTestDirCreateTemp(sTemplate = 'foo', sDirectory = 'it is not used', fMode = 0o700), tdTestResultFailure() ],
3528 [ tdTestDirCreateTemp(sTemplate = 'X,so', sDirectory = 'pointless test', fMode = 0o700), tdTestResultFailure() ],
3529 # Non-existing stuff.
3530 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX',
3531 sDirectory = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'non', 'existing')),
3532 tdTestResultFailure() ],
3533 # Working stuff:
3534 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3535 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3536 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3537 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3538 tdTestResultFailure() ],
3539 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3540 tdTestResultFailure() ],
3541 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3542 tdTestResultFailure() ],
3543 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3544 tdTestResultFailure() ],
3545 ];
3546
3547 if self.oTstDrv.fpApiVer >= 7.0:
3548 # Weird mode set.
3549 atTests.extend([
3550 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o42333),
3551 tdTestResultFailure() ]
3552 ]);
3553 # Same as working stuff above, but with a different mode set.
3554 atTests.extend([
3555 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3556 tdTestResultFailure() ],
3557 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3558 tdTestResultFailure() ],
3559 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3560 tdTestResultFailure() ],
3561 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3562 tdTestResultFailure() ],
3563 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3564 tdTestResultFailure() ],
3565 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3566 tdTestResultFailure() ],
3567 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3568 tdTestResultFailure() ]
3569 ]);
3570 # Same as working stuff above, but with secure mode set.
3571 atTests.extend([
3572 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fSecure = True),
3573 tdTestResultFailure() ],
3574 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fSecure = True),
3575 tdTestResultFailure() ],
3576 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fSecure = True),
3577 tdTestResultFailure() ],
3578 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fSecure = True),
3579 tdTestResultFailure() ],
3580 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm),
3581 fSecure = True),
3582 tdTestResultFailure() ],
3583 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm),
3584 fSecure = True),
3585 tdTestResultFailure() ],
3586 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm),
3587 fSecure = True),
3588 tdTestResultFailure() ]
3589 ]);
3590
3591 fRc = True;
3592 for (i, tTest) in enumerate(atTests):
3593 oCurTest = tTest[0] # type: tdTestDirCreateTemp
3594 oCurRes = tTest[1] # type: tdTestResult
3595 reporter.log('Testing #%d, sTemplate="%s", fMode=%#o, path="%s", secure="%s" ...' %
3596 (i, oCurTest.sTemplate, oCurTest.fMode, oCurTest.sDirectory, oCurTest.fSecure));
3597
3598 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3599 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreateTemp: Test #%d' % (i,));
3600 if fRc is False:
3601 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3602 break;
3603
3604 sDirTemp = '';
3605 try:
3606 sDirTemp = oCurGuestSession.directoryCreateTemp(oCurTest.sTemplate, oCurTest.fMode,
3607 oCurTest.sDirectory, oCurTest.fSecure);
3608 except:
3609 if oCurRes.fRc is True:
3610 fRc = reporter.errorXcpt('Creating temp directory "%s" failed:' % (oCurTest.sDirectory,));
3611 else:
3612 reporter.logXcpt('Creating temp directory "%s" failed expectedly, skipping:' % (oCurTest.sDirectory,));
3613 else:
3614 reporter.log2('Temporary directory is: "%s"' % (limitString(sDirTemp),));
3615 if not sDirTemp:
3616 fRc = reporter.error('Resulting directory is empty!');
3617 else:
3618 ## @todo This does not work for some unknown reason.
3619 #try:
3620 # if self.oTstDrv.fpApiVer >= 5.0:
3621 # fExists = oCurGuestSession.directoryExists(sDirTemp, False);
3622 # else:
3623 # fExists = oCurGuestSession.directoryExists(sDirTemp);
3624 #except:
3625 # fRc = reporter.errorXcpt('sDirTemp=%s' % (sDirTemp,));
3626 #else:
3627 # if fExists is not True:
3628 # fRc = reporter.error('Test #%d failed: Temporary directory "%s" does not exists (%s)'
3629 # % (i, sDirTemp, fExists));
3630 try:
3631 oFsObjInfo = oCurGuestSession.fsObjQueryInfo(sDirTemp, False);
3632 eType = oFsObjInfo.type;
3633 except:
3634 fRc = reporter.errorXcpt('sDirTemp="%s"' % (sDirTemp,));
3635 else:
3636 reporter.log2('%s: eType=%s (dir=%d)' % (limitString(sDirTemp), eType, vboxcon.FsObjType_Directory,));
3637 if eType != vboxcon.FsObjType_Directory:
3638 fRc = reporter.error('Temporary directory "%s" not created as a directory: eType=%d'
3639 % (sDirTemp, eType));
3640 fRc = oCurTest.closeSession() and fRc;
3641 return (fRc, oTxsSession);
3642
3643 def testGuestCtrlDirRead(self, oSession, oTxsSession, oTestVm):
3644 """
3645 Tests opening and reading (enumerating) guest directories.
3646 """
3647
3648 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3649 atTests = [
3650 # Invalid stuff.
3651 [ tdTestDirRead(sDirectory = ''), tdTestResultDirRead() ],
3652 [ tdTestDirRead(sDirectory = sSystemDir, afFlags = [ 1234 ]), tdTestResultDirRead() ],
3653 [ tdTestDirRead(sDirectory = sSystemDir, sFilter = '*.foo'), tdTestResultDirRead() ],
3654 # Non-existing stuff.
3655 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'really-no-such-subdir')), tdTestResultDirRead() ],
3656 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'non', 'existing')), tdTestResultDirRead() ],
3657 ];
3658
3659 if oTestVm.isWindows() or oTestVm.isOS2():
3660 atTests.extend([
3661 # More unusual stuff.
3662 [ tdTestDirRead(sDirectory = 'z:\\'), tdTestResultDirRead() ],
3663 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
3664 ]);
3665
3666 # Read the system directory (ASSUMES at least 5 files in it):
3667 # Windows 7+ has inaccessible system32/com/dmp directory that screws up this test, so skip it on windows:
3668 if not oTestVm.isWindows():
3669 atTests.append([ tdTestDirRead(sDirectory = sSystemDir),
3670 tdTestResultDirRead(fRc = True, cFiles = -5, cDirs = None) ]);
3671 ## @todo trailing slash
3672
3673 # Read from the test file set.
3674 atTests.extend([
3675 [ tdTestDirRead(sDirectory = self.oTestFiles.oEmptyDir.sPath),
3676 tdTestResultDirRead(fRc = True, cFiles = 0, cDirs = 0, cOthers = 0) ],
3677 [ tdTestDirRead(sDirectory = self.oTestFiles.oManyDir.sPath),
3678 tdTestResultDirRead(fRc = True, cFiles = len(self.oTestFiles.oManyDir.aoChildren), cDirs = 0, cOthers = 0) ],
3679 [ tdTestDirRead(sDirectory = self.oTestFiles.oTreeDir.sPath),
3680 tdTestResultDirRead(fRc = True, cFiles = self.oTestFiles.cTreeFiles, cDirs = self.oTestFiles.cTreeDirs,
3681 cOthers = self.oTestFiles.cTreeOthers) ],
3682 ]);
3683
3684
3685 fRc = True;
3686 for (i, tTest) in enumerate(atTests):
3687 oCurTest = tTest[0] # type: tdTestExec
3688 oCurRes = tTest[1] # type: tdTestResultDirRead
3689
3690 reporter.log('Testing #%d, dir="%s" ...' % (i, oCurTest.sDirectory));
3691 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3692 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: Test #%d' % (i,));
3693 if fRc is not True:
3694 break;
3695 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc);
3696 fRc = oCurTest.closeSession() and fRc;
3697
3698 reporter.log2('Test #%d: Returned %d directories, %d files total' % (i, cDirs, cFiles));
3699 if fRc2 is oCurRes.fRc:
3700 if fRc2 is True:
3701 if oCurRes.cFiles is None:
3702 pass; # ignore
3703 elif oCurRes.cFiles >= 0 and cFiles != oCurRes.cFiles:
3704 fRc = reporter.error('Test #%d failed: Got %d files, expected %d' % (i, cFiles, oCurRes.cFiles));
3705 elif oCurRes.cFiles < 0 and cFiles < -oCurRes.cFiles:
3706 fRc = reporter.error('Test #%d failed: Got %d files, expected at least %d'
3707 % (i, cFiles, -oCurRes.cFiles));
3708 if oCurRes.cDirs is None:
3709 pass; # ignore
3710 elif oCurRes.cDirs >= 0 and cDirs != oCurRes.cDirs:
3711 fRc = reporter.error('Test #%d failed: Got %d directories, expected %d' % (i, cDirs, oCurRes.cDirs));
3712 elif oCurRes.cDirs < 0 and cDirs < -oCurRes.cDirs:
3713 fRc = reporter.error('Test #%d failed: Got %d directories, expected at least %d'
3714 % (i, cDirs, -oCurRes.cDirs));
3715 if oCurRes.cOthers is None:
3716 pass; # ignore
3717 elif oCurRes.cOthers >= 0 and cOthers != oCurRes.cOthers:
3718 fRc = reporter.error('Test #%d failed: Got %d other types, expected %d' % (i, cOthers, oCurRes.cOthers));
3719 elif oCurRes.cOthers < 0 and cOthers < -oCurRes.cOthers:
3720 fRc = reporter.error('Test #%d failed: Got %d other types, expected at least %d'
3721 % (i, cOthers, -oCurRes.cOthers));
3722
3723 else:
3724 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3725
3726
3727 #
3728 # Go over a few directories in the test file set and compare names,
3729 # types and sizes rather than just the counts like we did above.
3730 #
3731 if fRc is True:
3732 oCurTest = tdTestDirRead();
3733 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3734 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: gctrlReadDirTree2');
3735 if fRc is True:
3736 for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir):
3737 reporter.log('Checking "%s" ...' % (oDir.sPath,));
3738 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir) and fRc;
3739 fRc = oCurTest.closeSession() and fRc;
3740
3741 return (fRc, oTxsSession);
3742
3743
3744 def testGuestCtrlFileRemove(self, oSession, oTxsSession, oTestVm):
3745 """
3746 Tests removing guest files.
3747 """
3748
3749 #
3750 # Create a directory with a few files in it using TXS that we'll use for the initial tests.
3751 #
3752 asTestDirs = [
3753 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1'), # [0]
3754 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1', 'subdir-1'), # [1]
3755 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1', 'subdir-1', 'subsubdir-1'), # [2]
3756 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2'), # [3]
3757 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2', 'subdir-2'), # [4]
3758 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2', 'subdir-2', 'subsbudir-2'), # [5]
3759 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-3'), # [6]
3760 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-4'), # [7]
3761 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-5'), # [8]
3762 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-5', 'subdir-5'), # [9]
3763 ]
3764 asTestFiles = [
3765 oTestVm.pathJoin(asTestDirs[0], 'file-0'), # [0]
3766 oTestVm.pathJoin(asTestDirs[0], 'file-1'), # [1]
3767 oTestVm.pathJoin(asTestDirs[0], 'file-2'), # [2]
3768 oTestVm.pathJoin(asTestDirs[1], 'file-3'), # [3] - subdir-1
3769 oTestVm.pathJoin(asTestDirs[1], 'file-4'), # [4] - subdir-1
3770 oTestVm.pathJoin(asTestDirs[2], 'file-5'), # [5] - subsubdir-1
3771 oTestVm.pathJoin(asTestDirs[3], 'file-6'), # [6] - rmtestdir-2
3772 oTestVm.pathJoin(asTestDirs[4], 'file-7'), # [7] - subdir-2
3773 oTestVm.pathJoin(asTestDirs[5], 'file-8'), # [8] - subsubdir-2
3774 ];
3775 for sDir in asTestDirs:
3776 if oTxsSession.syncMkDir(sDir, 0o777) is not True:
3777 return reporter.error('Failed to create test dir "%s"!' % (sDir,));
3778 for sFile in asTestFiles:
3779 if oTxsSession.syncUploadString(sFile, sFile, 0o666) is not True:
3780 return reporter.error('Failed to create test file "%s"!' % (sFile,));
3781
3782 #
3783 # Tear down the directories and files.
3784 #
3785 aoTests = [
3786 # Negative tests first:
3787 tdTestRemoveFile(asTestDirs[0], fRcExpect = False),
3788 tdTestRemoveDir(asTestDirs[0], fRcExpect = False),
3789 tdTestRemoveDir(asTestFiles[0], fRcExpect = False),
3790 tdTestRemoveFile(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-file'), fRcExpect = False),
3791 tdTestRemoveDir(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir'), fRcExpect = False),
3792 tdTestRemoveFile(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir', 'no-file'), fRcExpect = False),
3793 tdTestRemoveDir(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir', 'no-subdir'), fRcExpect = False),
3794 tdTestRemoveTree(asTestDirs[0], afFlags = [], fRcExpect = False), # Only removes empty dirs, this isn't empty.
3795 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_None,], fRcExpect = False), # ditto
3796 # Empty paths:
3797 tdTestRemoveFile('', fRcExpect = False),
3798 tdTestRemoveDir('', fRcExpect = False),
3799 tdTestRemoveTree('', fRcExpect = False),
3800 # Now actually remove stuff:
3801 tdTestRemoveDir(asTestDirs[7], fRcExpect = True),
3802 tdTestRemoveFile(asTestDirs[6], fRcExpect = False),
3803 tdTestRemoveDir(asTestDirs[6], fRcExpect = True),
3804 tdTestRemoveFile(asTestFiles[0], fRcExpect = True),
3805 tdTestRemoveFile(asTestFiles[0], fRcExpect = False),
3806 # 17:
3807 tdTestRemoveTree(asTestDirs[8], fRcExpect = True), # Removes empty subdirs and leaves the dir itself.
3808 tdTestRemoveDir(asTestDirs[8], fRcExpect = True),
3809 tdTestRemoveTree(asTestDirs[3], fRcExpect = False), # Have subdirs & files,
3810 tdTestRemoveTree(asTestDirs[3], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,], fRcExpect = True),
3811 tdTestRemoveDir(asTestDirs[3], fRcExpect = True),
3812 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,], fRcExpect = True),
3813 # No error if already delete (RTDirRemoveRecursive artifact).
3814 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,], fRcExpect = True),
3815 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,],
3816 fNotExist = True, fRcExpect = True),
3817 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_None,], fNotExist = True, fRcExpect = True),
3818 ];
3819
3820 #
3821 # Execution loop
3822 #
3823 fRc = True;
3824 for (i, oTest) in enumerate(aoTests): # int, tdTestRemoveBase
3825 reporter.log('Testing #%d, path="%s" %s ...' % (i, oTest.sPath, oTest.__class__.__name__));
3826 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
3827 fRc, _ = oTest.createSession('testGuestCtrlFileRemove: Test #%d' % (i,));
3828 if fRc is False:
3829 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3830 break;
3831 fRc = oTest.execute(self) and fRc;
3832 fRc = oTest.closeSession() and fRc;
3833
3834 if fRc is True:
3835 oCurTest = tdTestDirRead();
3836 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3837 fRc, oCurGuestSession = oCurTest.createSession('remove final');
3838 if fRc is True:
3839
3840 #
3841 # Delete all the files in the many subdir of the test set.
3842 #
3843 reporter.log('Deleting the file in "%s" ...' % (self.oTestFiles.oManyDir.sPath,));
3844 for oFile in self.oTestFiles.oManyDir.aoChildren:
3845 reporter.log2('"%s"' % (limitString(oFile.sPath),));
3846 try:
3847 if self.oTstDrv.fpApiVer >= 5.0:
3848 oCurGuestSession.fsObjRemove(oFile.sPath);
3849 else:
3850 oCurGuestSession.fileRemove(oFile.sPath);
3851 except:
3852 fRc = reporter.errorXcpt('Removing "%s" failed' % (oFile.sPath,));
3853
3854 # Remove the directory itself to verify that we've removed all the files in it:
3855 reporter.log('Removing the directory "%s" ...' % (self.oTestFiles.oManyDir.sPath,));
3856 try:
3857 oCurGuestSession.directoryRemove(self.oTestFiles.oManyDir.sPath);
3858 except:
3859 fRc = reporter.errorXcpt('Removing directory "%s" failed' % (self.oTestFiles.oManyDir.sPath,));
3860
3861 #
3862 # Recursively delete the entire test file tree from the root up.
3863 #
3864 # Note! On unix we cannot delete the root dir itself since it is residing
3865 # in /var/tmp where only the owner may delete it. Root is the owner.
3866 #
3867 if oTestVm.isWindows() or oTestVm.isOS2():
3868 afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,];
3869 else:
3870 afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,];
3871 try:
3872 oProgress = oCurGuestSession.directoryRemoveRecursive(self.oTestFiles.oRoot.sPath, afFlags);
3873 except:
3874 fRc = reporter.errorXcpt('Removing tree "%s" failed' % (self.oTestFiles.oRoot.sPath,));
3875 else:
3876 oWrappedProgress = vboxwrappers.ProgressWrapper(oProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv,
3877 "remove-tree-root: %s" % (self.oTestFiles.oRoot.sPath,));
3878 reporter.log2('waiting ...')
3879 oWrappedProgress.wait();
3880 reporter.log2('isSuccess=%s' % (oWrappedProgress.isSuccess(),));
3881 if not oWrappedProgress.isSuccess():
3882 fRc = oWrappedProgress.logResult();
3883
3884 fRc = oCurTest.closeSession() and fRc;
3885
3886 return (fRc, oTxsSession);
3887
3888
3889 def testGuestCtrlFileStat(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3890 """
3891 Tests querying file information through stat.
3892 """
3893
3894 # Basic stuff, existing stuff.
3895 aoTests = [
3896 tdTestSessionEx([
3897 tdStepStatDir('.'),
3898 tdStepStatDir('..'),
3899 tdStepStatDir(self.oTstDrv.getGuestTempDir(oTestVm)),
3900 tdStepStatDir(self.oTstDrv.getGuestSystemDir(oTestVm)),
3901 tdStepStatDirEx(self.oTestFiles.oRoot),
3902 tdStepStatDirEx(self.oTestFiles.oEmptyDir),
3903 tdStepStatDirEx(self.oTestFiles.oTreeDir),
3904 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3905 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3906 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3907 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3908 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3909 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3910 tdStepStatFile(self.oTstDrv.getGuestSystemFileForReading(oTestVm)),
3911 tdStepStatFile(self.oTstDrv.getGuestSystemShell(oTestVm)),
3912 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3913 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3914 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3915 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3916 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3917 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3918 ]),
3919 ];
3920
3921 # None existing stuff.
3922 sSysDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3923 sSep = oTestVm.pathSep();
3924 aoTests += [
3925 tdTestSessionEx([
3926 tdStepStatFileNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory')),
3927 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory') + sSep),
3928 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', '.')),
3929 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory')),
3930 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory') + sSep),
3931 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory', '.')),
3932 #tdStepStatPathNotFound('N:\\'), # ASSUMES nothing mounted on N:!
3933 #tdStepStatPathNotFound('\\\\NoSuchUncServerName\\NoSuchShare'),
3934 ]),
3935 ];
3936 # Invalid parameter check.
3937 aoTests += [ tdTestSessionEx([ tdStepStat('', vbox.ComError.E_INVALIDARG), ]), ];
3938
3939 #
3940 # Execute the tests.
3941 #
3942 fRc, oTxsSession = tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession,
3943 oTestVm, 'FsStat');
3944 #
3945 # Test the full test file set.
3946 #
3947 if self.oTstDrv.fpApiVer < 5.0:
3948 return (fRc, oTxsSession);
3949
3950 oTest = tdTestGuestCtrlBase();
3951 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
3952 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet');
3953 if fRc2 is not True:
3954 return (False, oTxsSession);
3955
3956 for sPath in self.oTestFiles.dPaths:
3957 oFsObj = self.oTestFiles.dPaths[sPath];
3958 reporter.log2('testGuestCtrlFileStat: %s sPath=%s'
3959 % ('file' if isinstance(oFsObj, testfileset.TestFile) else 'dir ', limitString(oFsObj.sPath),));
3960
3961 # Query the information:
3962 try:
3963 oFsInfo = oGuestSession.fsObjQueryInfo(oFsObj.sPath, False);
3964 except:
3965 fRc = reporter.errorXcpt('sPath=%s type=%s: fsObjQueryInfo trouble!' % (oFsObj.sPath, type(oFsObj),));
3966 continue;
3967 if oFsInfo is None:
3968 fRc = reporter.error('sPath=%s type=%s: No info object returned!' % (oFsObj.sPath, type(oFsObj),));
3969 continue;
3970
3971 # Check attributes:
3972 try:
3973 eType = oFsInfo.type;
3974 cbObject = oFsInfo.objectSize;
3975 except:
3976 fRc = reporter.errorXcpt('sPath=%s type=%s: attribute access trouble!' % (oFsObj.sPath, type(oFsObj),));
3977 continue;
3978
3979 if isinstance(oFsObj, testfileset.TestFile):
3980 if eType != vboxcon.FsObjType_File:
3981 fRc = reporter.error('sPath=%s type=file: eType=%s, expected %s!'
3982 % (oFsObj.sPath, eType, vboxcon.FsObjType_File));
3983 if cbObject != oFsObj.cbContent:
3984 fRc = reporter.error('sPath=%s type=file: cbObject=%s, expected %s!'
3985 % (oFsObj.sPath, cbObject, oFsObj.cbContent));
3986 fFileExists = True;
3987 fDirExists = False;
3988 elif isinstance(oFsObj, testfileset.TestDir):
3989 if eType != vboxcon.FsObjType_Directory:
3990 fRc = reporter.error('sPath=%s type=dir: eType=%s, expected %s!'
3991 % (oFsObj.sPath, eType, vboxcon.FsObjType_Directory));
3992 fFileExists = False;
3993 fDirExists = True;
3994 else:
3995 fRc = reporter.error('sPath=%s type=%s: Unexpected oFsObj type!' % (oFsObj.sPath, type(oFsObj),));
3996 continue;
3997
3998 # Check the directoryExists and fileExists results too.
3999 try:
4000 fExistsResult = oGuestSession.fileExists(oFsObj.sPath, False);
4001 except:
4002 fRc = reporter.errorXcpt('sPath=%s type=%s: fileExists trouble!' % (oFsObj.sPath, type(oFsObj),));
4003 else:
4004 if fExistsResult != fFileExists:
4005 fRc = reporter.error('sPath=%s type=%s: fileExists returned %s, expected %s!'
4006 % (oFsObj.sPath, type(oFsObj), fExistsResult, fFileExists));
4007 try:
4008 fExistsResult = oGuestSession.directoryExists(oFsObj.sPath, False);
4009 except:
4010 fRc = reporter.errorXcpt('sPath=%s type=%s: directoryExists trouble!' % (oFsObj.sPath, type(oFsObj),));
4011 else:
4012 if fExistsResult != fDirExists:
4013 fRc = reporter.error('sPath=%s type=%s: directoryExists returned %s, expected %s!'
4014 % (oFsObj.sPath, type(oFsObj), fExistsResult, fDirExists));
4015
4016 fRc = oTest.closeSession() and fRc;
4017 return (fRc, oTxsSession);
4018
4019 def testGuestCtrlFileOpen(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4020 """
4021 Tests opening guest files.
4022 """
4023 if self.oTstDrv.fpApiVer < 5.0:
4024 reporter.log('Skipping because of pre 5.0 API');
4025 return None;
4026
4027 #
4028 # Paths.
4029 #
4030 sTempDir = self.oTstDrv.getGuestTempDir(oTestVm);
4031 sFileForReading = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
4032 asFiles = [
4033 oTestVm.pathJoin(sTempDir, 'file-open-0'),
4034 oTestVm.pathJoin(sTempDir, 'file-open-1'),
4035 oTestVm.pathJoin(sTempDir, 'file-open-2'),
4036 oTestVm.pathJoin(sTempDir, 'file-open-3'),
4037 oTestVm.pathJoin(sTempDir, 'file-open-4'),
4038 ];
4039 asNonEmptyFiles = [
4040 oTestVm.pathJoin(sTempDir, 'file-open-10'),
4041 oTestVm.pathJoin(sTempDir, 'file-open-11'),
4042 oTestVm.pathJoin(sTempDir, 'file-open-12'),
4043 oTestVm.pathJoin(sTempDir, 'file-open-13'),
4044 ];
4045 sContent = 'abcdefghijklmnopqrstuvwxyz0123456789';
4046 for sFile in asNonEmptyFiles:
4047 if oTxsSession.syncUploadString(sContent, sFile, 0o666) is not True:
4048 return reporter.error('Failed to create "%s" via TXS' % (sFile,));
4049
4050 #
4051 # The tests.
4052 #
4053 atTests = [
4054 # Invalid stuff.
4055 [ tdTestFileOpen(sFile = ''), tdTestResultFailure() ],
4056 # Wrong open mode.
4057 [ tdTestFileOpen(sFile = sFileForReading, eAccessMode = -1), tdTestResultFailure() ],
4058 # Wrong disposition.
4059 [ tdTestFileOpen(sFile = sFileForReading, eAction = -1), tdTestResultFailure() ],
4060 # Non-existing file or path.
4061 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir')), tdTestResultFailure() ],
4062 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
4063 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
4064 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
4065 eAccessMode = vboxcon.FileAccessMode_WriteOnly,
4066 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
4067 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
4068 eAccessMode = vboxcon.FileAccessMode_ReadWrite,
4069 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
4070 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-dir', 'no-such-file')), tdTestResultFailure() ],
4071 ];
4072 if self.oTstDrv.fpApiVer > 5.2: # Fixed since 6.0.
4073 atTests.extend([
4074 # Wrong type:
4075 [ tdTestFileOpen(sFile = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
4076 [ tdTestFileOpen(sFile = self.oTstDrv.getGuestSystemDir(oTestVm)), tdTestResultFailure() ],
4077 ]);
4078 atTests.extend([
4079 # O_EXCL and such:
4080 [ tdTestFileOpen(sFile = sFileForReading, eAction = vboxcon.FileOpenAction_CreateNew,
4081 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultFailure() ],
4082 [ tdTestFileOpen(sFile = sFileForReading, eAction = vboxcon.FileOpenAction_CreateNew), tdTestResultFailure() ],
4083 # Open a file.
4084 [ tdTestFileOpen(sFile = sFileForReading), tdTestResultSuccess() ],
4085 [ tdTestFileOpen(sFile = sFileForReading,
4086 eAction = vboxcon.FileOpenAction_OpenOrCreate), tdTestResultSuccess() ],
4087 # Create a new file.
4088 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateNew,
4089 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4090 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateNew,
4091 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultFailure() ],
4092 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenExisting,
4093 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4094 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateOrReplace,
4095 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4096 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenOrCreate,
4097 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4098 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenExistingTruncated,
4099 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4100 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_AppendOrCreate,
4101 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4102 # Open or create a new file.
4103 [ tdTestFileOpenCheckSize(sFile = asFiles[1], eAction = vboxcon.FileOpenAction_OpenOrCreate,
4104 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4105 # Create or replace a new file.
4106 [ tdTestFileOpenCheckSize(sFile = asFiles[2], eAction = vboxcon.FileOpenAction_CreateOrReplace,
4107 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4108 # Create and append to file (weird stuff).
4109 [ tdTestFileOpenCheckSize(sFile = asFiles[3], eAction = vboxcon.FileOpenAction_AppendOrCreate,
4110 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4111 [ tdTestFileOpenCheckSize(sFile = asFiles[4], eAction = vboxcon.FileOpenAction_AppendOrCreate,
4112 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4113 # Open the non-empty files in non-destructive modes.
4114 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent)), tdTestResultSuccess() ],
4115 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
4116 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4117 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
4118 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4119
4120 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent),
4121 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4122 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4123 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
4124 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4125 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4126 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
4127 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4128 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4129
4130 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent),
4131 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4132 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4133 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
4134 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4135 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4136 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
4137 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4138 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4139
4140 # Now the destructive stuff:
4141 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], eAccessMode = vboxcon.FileAccessMode_WriteOnly,
4142 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultSuccess() ],
4143 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], eAccessMode = vboxcon.FileAccessMode_WriteOnly,
4144 eAction = vboxcon.FileOpenAction_CreateOrReplace), tdTestResultSuccess() ],
4145 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], eAction = vboxcon.FileOpenAction_CreateOrReplace,
4146 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4147 ]);
4148
4149 #
4150 # Do the testing.
4151 #
4152 fRc = True;
4153 for (i, tTest) in enumerate(atTests):
4154 oCurTest = tTest[0] # type: tdTestFileOpen
4155 oCurRes = tTest[1] # type: tdTestResult
4156
4157 reporter.log('Testing #%d: %s - sFile="%s", eAccessMode=%d, eAction=%d, (%s, %s, %s) ...'
4158 % (i, oCurTest.__class__.__name__, oCurTest.sFile, oCurTest.eAccessMode, oCurTest.eAction,
4159 oCurTest.eSharing, oCurTest.fCreationMode, oCurTest.afOpenFlags,));
4160
4161 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4162 fRc, _ = oCurTest.createSession('testGuestCtrlFileOpen: Test #%d' % (i,));
4163 if fRc is not True:
4164 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4165 break;
4166
4167 fRc2 = oCurTest.doSteps(oCurRes.fRc, self);
4168 if fRc2 != oCurRes.fRc:
4169 fRc = reporter.error('Test #%d result mismatch: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
4170
4171 fRc = oCurTest.closeSession() and fRc;
4172
4173 return (fRc, oTxsSession);
4174
4175
4176 def testGuestCtrlFileRead(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-branches,too-many-statements
4177 """
4178 Tests reading from guest files.
4179 """
4180 if self.oTstDrv.fpApiVer < 5.0:
4181 reporter.log('Skipping because of pre 5.0 API');
4182 return None;
4183
4184 #
4185 # Do everything in one session.
4186 #
4187 oTest = tdTestGuestCtrlBase();
4188 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
4189 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet');
4190 if fRc2 is not True:
4191 return (False, oTxsSession);
4192
4193 #
4194 # Create a really big zero filled, up to 1 GiB, adding it to the list of
4195 # files from the set.
4196 #
4197 # Note! This code sucks a bit because we don't have a working setSize nor
4198 # any way to figure out how much free space there is in the guest.
4199 #
4200 aoExtraFiles = [];
4201 sBigName = self.oTestFiles.generateFilenameEx();
4202 sBigPath = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sBigName);
4203 fRc = True;
4204 try:
4205 oFile = oGuestSession.fileOpenEx(sBigPath, vboxcon.FileAccessMode_ReadWrite, vboxcon.FileOpenAction_CreateOrReplace,
4206 vboxcon.FileSharingMode_All, 0, []);
4207 except:
4208 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4209 else:
4210 # Does setSize work now?
4211 fUseFallback = True;
4212 try:
4213 oFile.setSize(0);
4214 oFile.setSize(64);
4215 fUseFallback = False;
4216 except Exception as oXcpt:
4217 reporter.logXcpt();
4218
4219 # Grow the file till we hit trouble, typical VERR_DISK_FULL, then
4220 # reduce the file size if we have a working setSize.
4221 cbBigFile = 0;
4222 while cbBigFile < (1024 + 32)*1024*1024:
4223 if not fUseFallback:
4224 cbBigFile += 16*1024*1024;
4225 try:
4226 oFile.setSize(cbBigFile);
4227 except Exception as oXcpt:
4228 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4229 try:
4230 cbBigFile -= 16*1024*1024;
4231 oFile.setSize(cbBigFile);
4232 except:
4233 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4234 break;
4235 else:
4236 cbBigFile += 32*1024*1024;
4237 try:
4238 oFile.seek(cbBigFile, vboxcon.FileSeekOrigin_Begin);
4239 oFile.write(bytearray(1), 60*1000);
4240 except:
4241 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4242 break;
4243 try:
4244 cbBigFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
4245 except:
4246 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4247 try:
4248 oFile.close();
4249 except:
4250 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4251 if fRc is True:
4252 reporter.log('Big file: %s bytes: %s' % (cbBigFile, sBigPath,));
4253 aoExtraFiles.append(testfileset.TestFileZeroFilled(None, sBigPath, cbBigFile));
4254 else:
4255 try:
4256 oGuestSession.fsObjRemove(sBigPath);
4257 except:
4258 reporter.errorXcpt('fsObjRemove(sBigName=%s)' % (sBigPath,));
4259
4260 #
4261 # Open and read all the files in the test file set.
4262 #
4263 for oTestFile in aoExtraFiles + self.oTestFiles.aoFiles: # type: testfileset.TestFile
4264 reporter.log2('Test file: %s bytes, "%s" ...' % (oTestFile.cbContent, limitString(oTestFile.sPath),));
4265
4266 #
4267 # Open it:
4268 #
4269 try:
4270 oFile = oGuestSession.fileOpenEx(oTestFile.sPath, vboxcon.FileAccessMode_ReadOnly,
4271 vboxcon.FileOpenAction_OpenExisting, vboxcon.FileSharingMode_All, 0, []);
4272 except:
4273 fRc = reporter.errorXcpt('sPath=%s' % (oTestFile.sPath, ));
4274 continue;
4275
4276 #
4277 # Read the file in different sized chunks:
4278 #
4279 if oTestFile.cbContent < 128:
4280 acbChunks = xrange(1,128);
4281 elif oTestFile.cbContent < 1024:
4282 acbChunks = (2048, 127, 63, 32, 29, 17, 16, 15, 9);
4283 elif oTestFile.cbContent < 8*1024*1024:
4284 acbChunks = (128*1024, 32*1024, 8191, 255);
4285 else:
4286 acbChunks = (768*1024, 128*1024);
4287
4288 for cbChunk in acbChunks:
4289 # Read the whole file straight thru:
4290 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... cbChunk=%s' % (cbChunk,));
4291 offFile = 0;
4292 cReads = 0;
4293 while offFile <= oTestFile.cbContent:
4294 try:
4295 abRead = oFile.read(cbChunk, 30*1000);
4296 except:
4297 fRc = reporter.errorXcpt('%s: offFile=%s cbChunk=%s cbContent=%s'
4298 % (oTestFile.sPath, offFile, cbChunk, oTestFile.cbContent));
4299 break;
4300 cbRead = len(abRead);
4301 if cbRead == 0 and offFile == oTestFile.cbContent:
4302 break;
4303 if cbRead <= 0:
4304 fRc = reporter.error('%s @%s: cbRead=%s, cbContent=%s'
4305 % (oTestFile.sPath, offFile, cbRead, oTestFile.cbContent));
4306 break;
4307 if not oTestFile.equalMemory(abRead, offFile):
4308 fRc = reporter.error('%s: read mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead));
4309 break;
4310 offFile += cbRead;
4311 cReads += 1;
4312 if cReads > 8192:
4313 break;
4314
4315 # Seek to start of file.
4316 try:
4317 offFile = oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
4318 except:
4319 fRc = reporter.errorXcpt('%s: error seeking to start of file' % (oTestFile.sPath,));
4320 break;
4321 if offFile != 0:
4322 fRc = reporter.error('%s: seek to start of file returned %u, expected 0' % (oTestFile.sPath, offFile));
4323 break;
4324
4325 #
4326 # Random reads.
4327 #
4328 for _ in xrange(8):
4329 offFile = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
4330 cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
4331 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s' % (offFile, cbToRead,));
4332
4333 try:
4334 offActual = oFile.seek(offFile, vboxcon.FileSeekOrigin_Begin);
4335 except:
4336 fRc = reporter.errorXcpt('%s: error seeking to %s' % (oTestFile.sPath, offFile));
4337 break;
4338 if offActual != offFile:
4339 fRc = reporter.error('%s: seek(%s,Begin) -> %s, expected %s'
4340 % (oTestFile.sPath, offFile, offActual, offFile));
4341 break;
4342
4343 try:
4344 abRead = oFile.read(cbToRead, 30*1000);
4345 except:
4346 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s'
4347 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4348 cbRead = 0;
4349 else:
4350 cbRead = len(abRead);
4351 if not oTestFile.equalMemory(abRead, offFile):
4352 fRc = reporter.error('%s: random read mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
4353
4354 try:
4355 offActual = oFile.offset;
4356 except:
4357 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#1)'
4358 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4359 else:
4360 if offActual != offFile + cbRead:
4361 fRc = reporter.error('%s: IFile.offset is %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#1)'
4362 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4363 try:
4364 offActual = oFile.seek(0, vboxcon.FileSeekOrigin_Current);
4365 except:
4366 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#1)'
4367 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4368 else:
4369 if offActual != offFile + cbRead:
4370 fRc = reporter.error('%s: seek(0,cur) -> %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#1)'
4371 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4372
4373 #
4374 # Random reads using readAt.
4375 #
4376 for _ in xrange(12):
4377 offFile = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
4378 cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
4379 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s (readAt)' % (offFile, cbToRead,));
4380
4381 try:
4382 abRead = oFile.readAt(offFile, cbToRead, 30*1000);
4383 except:
4384 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s'
4385 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4386 cbRead = 0;
4387 else:
4388 cbRead = len(abRead);
4389 if not oTestFile.equalMemory(abRead, offFile):
4390 fRc = reporter.error('%s: random readAt mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
4391
4392 try:
4393 offActual = oFile.offset;
4394 except:
4395 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#2)'
4396 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4397 else:
4398 if offActual != offFile + cbRead:
4399 fRc = reporter.error('%s: IFile.offset is %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#2)'
4400 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4401
4402 try:
4403 offActual = oFile.seek(0, vboxcon.FileSeekOrigin_Current);
4404 except:
4405 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#2)'
4406 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4407 else:
4408 if offActual != offFile + cbRead:
4409 fRc = reporter.error('%s: seek(0,cur) -> %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#2)'
4410 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4411
4412 #
4413 # A few negative things.
4414 #
4415
4416 # Zero byte reads -> E_INVALIDARG.
4417 try:
4418 abRead = oFile.read(0, 30*1000);
4419 except Exception as oXcpt:
4420 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
4421 fRc = reporter.errorXcpt('read(0,30s) did not raise E_INVALIDARG as expected!');
4422 else:
4423 fRc = reporter.error('read(0,30s) did not fail!');
4424
4425 try:
4426 abRead = oFile.readAt(0, 0, 30*1000);
4427 except Exception as oXcpt:
4428 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
4429 fRc = reporter.errorXcpt('readAt(0,0,30s) did not raise E_INVALIDARG as expected!');
4430 else:
4431 fRc = reporter.error('readAt(0,0,30s) did not fail!');
4432
4433 # See what happens when we read 1GiB. We should get a max of 1MiB back.
4434 ## @todo Document this behaviour in VirtualBox.xidl.
4435 try:
4436 oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
4437 except:
4438 fRc = reporter.error('seek(0)');
4439 try:
4440 abRead = oFile.read(1024*1024*1024, 30*1000);
4441 except:
4442 fRc = reporter.errorXcpt('read(1GiB,30s)');
4443 else:
4444 if len(abRead) != min(oTestFile.cbContent, 1024*1024):
4445 fRc = reporter.error('Expected read(1GiB,30s) to return %s bytes, got %s bytes instead'
4446 % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
4447
4448 try:
4449 abRead = oFile.readAt(0, 1024*1024*1024, 30*1000);
4450 except:
4451 fRc = reporter.errorXcpt('readAt(0,1GiB,30s)');
4452 else:
4453 if len(abRead) != min(oTestFile.cbContent, 1024*1024):
4454 reporter.error('Expected readAt(0, 1GiB,30s) to return %s bytes, got %s bytes instead'
4455 % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
4456
4457 #
4458 # Check stat info on the file as well as querySize.
4459 #
4460 if self.oTstDrv.fpApiVer > 5.2:
4461 try:
4462 oFsObjInfo = oFile.queryInfo();
4463 except:
4464 fRc = reporter.errorXcpt('%s: queryInfo()' % (oTestFile.sPath,));
4465 else:
4466 if oFsObjInfo is None:
4467 fRc = reporter.error('IGuestFile::queryInfo returned None');
4468 else:
4469 try:
4470 cbFile = oFsObjInfo.objectSize;
4471 except:
4472 fRc = reporter.errorXcpt();
4473 else:
4474 if cbFile != oTestFile.cbContent:
4475 fRc = reporter.error('%s: queryInfo returned incorrect file size: %s, expected %s'
4476 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4477
4478 try:
4479 cbFile = oFile.querySize();
4480 except:
4481 fRc = reporter.errorXcpt('%s: querySize()' % (oTestFile.sPath,));
4482 else:
4483 if cbFile != oTestFile.cbContent:
4484 fRc = reporter.error('%s: querySize returned incorrect file size: %s, expected %s'
4485 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4486
4487 #
4488 # Use seek to test the file size and do a few other end-relative seeks.
4489 #
4490 try:
4491 cbFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
4492 except:
4493 fRc = reporter.errorXcpt('%s: seek(0,End)' % (oTestFile.sPath,));
4494 else:
4495 if cbFile != oTestFile.cbContent:
4496 fRc = reporter.error('%s: seek(0,End) returned incorrect file size: %s, expected %s'
4497 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4498 if oTestFile.cbContent > 0:
4499 for _ in xrange(5):
4500 offSeek = self.oTestFiles.oRandom.randrange(oTestFile.cbContent + 1);
4501 try:
4502 offFile = oFile.seek(-offSeek, vboxcon.FileSeekOrigin_End);
4503 except:
4504 fRc = reporter.errorXcpt('%s: seek(%s,End)' % (oTestFile.sPath, -offSeek,));
4505 else:
4506 if offFile != oTestFile.cbContent - offSeek:
4507 fRc = reporter.error('%s: seek(%s,End) returned incorrect offset: %s, expected %s (cbContent=%s)'
4508 % (oTestFile.sPath, -offSeek, offSeek, oTestFile.cbContent - offSeek,
4509 oTestFile.cbContent,));
4510
4511 #
4512 # Close it and we're done with this file.
4513 #
4514 try:
4515 oFile.close();
4516 except:
4517 fRc = reporter.errorXcpt('%s: error closing the file' % (oTestFile.sPath,));
4518
4519 #
4520 # Clean up.
4521 #
4522 for oTestFile in aoExtraFiles:
4523 try:
4524 oGuestSession.fsObjRemove(sBigPath);
4525 except:
4526 fRc = reporter.errorXcpt('fsObjRemove(%s)' % (sBigPath,));
4527
4528 fRc = oTest.closeSession() and fRc;
4529
4530 return (fRc, oTxsSession);
4531
4532
4533 def testGuestCtrlFileWrite(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4534 """
4535 Tests writing to guest files.
4536 """
4537 if self.oTstDrv.fpApiVer < 5.0:
4538 reporter.log('Skipping because of pre 5.0 API');
4539 return None;
4540
4541 #
4542 # The test file and its content.
4543 #
4544 sFile = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'gctrl-write-1');
4545 abContent = bytearray(0);
4546
4547 #
4548 # The tests.
4549 #
4550 def randBytes(cbHowMany):
4551 """ Returns an bytearray of random bytes. """
4552 return bytearray(self.oTestFiles.oRandom.getrandbits(8) for _ in xrange(cbHowMany));
4553
4554 aoTests = [
4555 # Write at end:
4556 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_CreateNew, abContent = abContent,
4557 atChunks = [(None, randBytes(1)), (None, randBytes(77)), (None, randBytes(98)),]),
4558 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1+77+98), # 176
4559 # Appending:
4560 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_AppendOrCreate, abContent = abContent,
4561 atChunks = [(None, randBytes(255)), (None, randBytes(33)),]),
4562 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 176 + 255+33), # 464
4563 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_AppendOrCreate, abContent = abContent,
4564 atChunks = [(10, randBytes(44)),]),
4565 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 464 + 44), # 508
4566 # Write within existing:
4567 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_OpenExisting, abContent = abContent,
4568 atChunks = [(0, randBytes(1)), (50, randBytes(77)), (255, randBytes(199)),]),
4569 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 508),
4570 # Writing around and over the end:
4571 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent,
4572 atChunks = [(500, randBytes(9)), (508, randBytes(15)), (512, randBytes(12)),]),
4573 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 512+12),
4574
4575 # writeAt appending:
4576 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4577 atChunks = [(0, randBytes(23)), (6, randBytes(1018)),]),
4578 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 6+1018), # 1024
4579 # writeAt within existing:
4580 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4581 atChunks = [(1000, randBytes(23)), (1, randBytes(990)),]),
4582 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1024),
4583 # writeAt around and over the end:
4584 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4585 atChunks = [(1024, randBytes(63)), (1080, randBytes(968)),]),
4586 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1080+968), # 2048
4587
4588 # writeAt beyond the end (gap is filled with zeros):
4589 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True, atChunks = [(3070, randBytes(2)),]),
4590 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 3072),
4591 # write beyond the end (gap is filled with zeros):
4592 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, atChunks = [(4090, randBytes(6)),]),
4593 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 4096),
4594 ];
4595
4596 for (i, oCurTest) in enumerate(aoTests):
4597 reporter.log('Testing #%d: %s ...' % (i, oCurTest.toString(),));
4598
4599 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4600 fRc, _ = oCurTest.createSession('testGuestCtrlFileWrite: Test #%d' % (i,));
4601 if fRc is not True:
4602 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4603 break;
4604
4605 fRc2 = oCurTest.doSteps(True, self);
4606 if fRc2 is not True:
4607 fRc = reporter.error('Test #%d failed!' % (i,));
4608
4609 fRc = oCurTest.closeSession() and fRc;
4610
4611 #
4612 # Cleanup
4613 #
4614 if oTxsSession.syncRmFile(sFile) is not True:
4615 fRc = reporter.error('Failed to remove write-test file: %s' % (sFile, ));
4616
4617 return (fRc, oTxsSession);
4618
4619 @staticmethod
4620 def __generateFile(sName, cbFile):
4621 """ Helper for generating a file with a given size. """
4622 oFile = open(sName, 'wb');
4623 while cbFile > 0:
4624 cb = cbFile if cbFile < 256*1024 else 256*1024;
4625 oFile.write(bytearray(random.getrandbits(8) for _ in xrange(cb)));
4626 cbFile -= cb;
4627 oFile.close();
4628
4629 def testGuestCtrlCopyTo(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4630 """
4631 Tests copying files from host to the guest.
4632 """
4633
4634 #
4635 # Paths and test files.
4636 #
4637 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, 'copyto');
4638 sScratchTestFilesHst = os.path.join(sScratchHst, self.oTestFiles.sSubDir);
4639 sScratchEmptyDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oEmptyDir.sName);
4640 sScratchNonEmptyDirHst = self.oTestFiles.chooseRandomDirFromTree().buildPath(sScratchHst, os.path.sep);
4641 sScratchTreeDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oTreeDir.sName);
4642
4643 sScratchGst = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'copyto');
4644 sScratchDstDir1Gst = oTestVm.pathJoin(sScratchGst, 'dstdir1');
4645 sScratchDstDir2Gst = oTestVm.pathJoin(sScratchGst, 'dstdir2');
4646 sScratchDstDir3Gst = oTestVm.pathJoin(sScratchGst, 'dstdir3');
4647 sScratchDstDir4Gst = oTestVm.pathJoin(sScratchGst, 'dstdir4');
4648 #sScratchGstNotExist = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'no-such-file-or-directory');
4649 sScratchHstNotExist = os.path.join(self.oTstDrv.sScratchPath, 'no-such-file-or-directory');
4650 sScratchGstPathNotFound = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'no-such-directory', 'or-file');
4651 #sScratchHstPathNotFound = os.path.join(self.oTstDrv.sScratchPath, 'no-such-directory', 'or-file');
4652
4653 if oTestVm.isWindows() or oTestVm.isOS2():
4654 sScratchGstInvalid = "?*|<invalid-name>";
4655 else:
4656 sScratchGstInvalid = None;
4657 if utils.getHostOs() in ('win', 'os2'):
4658 sScratchHstInvalid = "?*|<invalid-name>";
4659 else:
4660 sScratchHstInvalid = None;
4661
4662 for sDir in (sScratchGst, sScratchDstDir1Gst, sScratchDstDir2Gst, sScratchDstDir3Gst, sScratchDstDir4Gst):
4663 if oTxsSession.syncMkDir(sDir, 0o777) is not True:
4664 return reporter.error('TXS failed to create directory "%s"!' % (sDir,));
4665
4666 # Put the test file set under sScratchHst.
4667 if os.path.exists(sScratchHst):
4668 if base.wipeDirectory(sScratchHst) != 0:
4669 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
4670 else:
4671 try:
4672 os.mkdir(sScratchHst);
4673 except:
4674 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
4675 if self.oTestFiles.writeToDisk(sScratchHst) is not True:
4676 return reporter.error('Filed to write test files to "%s" on the host!' % (sScratchHst,));
4677
4678 # Generate a test file in 32MB to 64 MB range.
4679 sBigFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-random.data');
4680 cbBigFileHst = random.randrange(32*1024*1024, 64*1024*1024);
4681 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
4682 cbLeft = cbBigFileHst;
4683 try:
4684 self.__generateFile(sBigFileHst, cbBigFileHst);
4685 except:
4686 return reporter.errorXcpt('sBigFileHst=%s cbBigFileHst=%s cbLeft=%s' % (sBigFileHst, cbBigFileHst, cbLeft,));
4687 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
4688
4689 # Generate an empty file on the host that we can use to save space in the guest.
4690 sEmptyFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-empty.data');
4691 try:
4692 oFile = open(sEmptyFileHst, "wb");
4693 oFile.close();
4694 except:
4695 return reporter.errorXcpt('sEmptyFileHst=%s' % (sEmptyFileHst,));
4696
4697 #
4698 # Tests.
4699 #
4700 atTests = [
4701 # Nothing given:
4702 [ tdTestCopyToFile(), tdTestResultFailure() ],
4703 [ tdTestCopyToDir(), tdTestResultFailure() ],
4704 # Only source given:
4705 [ tdTestCopyToFile(sSrc = sBigFileHst), tdTestResultFailure() ],
4706 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst), tdTestResultFailure() ],
4707 # Only destination given:
4708 [ tdTestCopyToFile(sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')), tdTestResultFailure() ],
4709 [ tdTestCopyToDir( sDst = sScratchGst), tdTestResultFailure() ],
4710 # Both given, but invalid flags.
4711 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst, afFlags = [ 0x40000000, ] ), tdTestResultFailure() ],
4712 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGst, afFlags = [ 0x40000000, ] ),
4713 tdTestResultFailure() ],
4714 ];
4715 atTests.extend([
4716 # Non-existing source, but no destination:
4717 [ tdTestCopyToFile(sSrc = sScratchHstNotExist), tdTestResultFailure() ],
4718 [ tdTestCopyToDir( sSrc = sScratchHstNotExist), tdTestResultFailure() ],
4719 # Valid sources, but destination path not found:
4720 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
4721 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
4722 # Valid destination, but source file/dir not found:
4723 [ tdTestCopyToFile(sSrc = sScratchHstNotExist, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
4724 tdTestResultFailure() ],
4725 [ tdTestCopyToDir( sSrc = sScratchHstNotExist, sDst = sScratchGst), tdTestResultFailure() ],
4726 # Wrong type:
4727 [ tdTestCopyToFile(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
4728 tdTestResultFailure() ],
4729 [ tdTestCopyToDir( sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultFailure() ],
4730 ]);
4731 # Invalid characters in destination or source path:
4732 if sScratchGstInvalid is not None:
4733 atTests.extend([
4734 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
4735 tdTestResultFailure() ],
4736 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
4737 tdTestResultFailure() ],
4738 ]);
4739 if sScratchHstInvalid is not None:
4740 atTests.extend([
4741 [ tdTestCopyToFile(sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
4742 tdTestResultFailure() ],
4743 [ tdTestCopyToDir( sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
4744 tdTestResultFailure() ],
4745 ]);
4746
4747 #
4748 # Single file handling.
4749 #
4750 atTests.extend([
4751 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')),
4752 tdTestResultSuccess() ],
4753 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
4754 tdTestResultSuccess() ],
4755 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
4756 tdTestResultSuccess() ],
4757 ]);
4758 if self.oTstDrv.fpApiVer > 5.2: # Copying files into directories via Main is supported only 6.0 and later.
4759 atTests.extend([
4760 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ],
4761 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ], # Overwrite
4762 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, os.path.split(sBigFileHst)[1])),
4763 tdTestResultSuccess() ], # Overwrite
4764 ]);
4765
4766 if oTestVm.isWindows():
4767 # Copy to a Windows alternative data stream (ADS).
4768 atTests.extend([
4769 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat:ADS-Test')),
4770 tdTestResultSuccess() ],
4771 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat:ADS-Test')),
4772 tdTestResultSuccess() ],
4773 ]);
4774
4775 #
4776 # Directory handling.
4777 #
4778 if self.oTstDrv.fpApiVer > 5.2: # Copying directories via Main is supported only in versions > 5.2.
4779 atTests.extend([
4780 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
4781 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4782 # Try again.
4783 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
4784 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4785 # Should fail, as destination directory already exists.
4786 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultFailure() ],
4787 # Try again with trailing slash, should yield the same result:
4788 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep(),
4789 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4790 # Try again.
4791 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep(),
4792 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4793 # Should fail, as destination directory already exists.
4794 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
4795 tdTestResultFailure() ],
4796 # Copy with a different destination name just for the heck of it:
4797 # disabled at the moment, causes test failures due to the non-existing target
4798 #[ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchDstDir1Gst, 'empty2')),
4799 # tdTestResultSuccess() ],
4800 ]);
4801 atTests.extend([
4802 # Now the same using a directory with files in it:
4803 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
4804 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4805 # Again.
4806 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
4807 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4808 # Should fail, as directory is existing already.
4809 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst), tdTestResultFailure() ],
4810 ]);
4811 atTests.extend([
4812 # Copy the entire test tree:
4813 [ tdTestCopyToDir(sSrc = sScratchTreeDirHst, sDst = sScratchDstDir4Gst,
4814 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4815 ]);
4816
4817 fRc = True;
4818 for (i, tTest) in enumerate(atTests):
4819 oCurTest = tTest[0]; # tdTestCopyTo
4820 oCurRes = tTest[1]; # tdTestResult
4821 reporter.log('Testing #%d, sSrc=%s, sDst=%s, afFlags=%s ...'
4822 % (i, limitString(oCurTest.sSrc), limitString(oCurTest.sDst), oCurTest.afFlags));
4823
4824 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4825 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyTo: Test #%d' % (i,));
4826 if fRc is not True:
4827 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4828 break;
4829
4830 fRc2 = False;
4831 if isinstance(oCurTest, tdTestCopyToFile):
4832 fRc2 = self.gctrlCopyFileTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags, oCurRes.fRc);
4833 else:
4834 fRc2 = self.gctrlCopyDirTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags, oCurRes.fRc);
4835 if fRc2 is not oCurRes.fRc:
4836 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
4837
4838 fRc = oCurTest.closeSession() and fRc;
4839
4840 return (fRc, oTxsSession);
4841
4842 def testGuestCtrlCopyFrom(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4843 """
4844 Tests copying files from guest to the host.
4845 """
4846
4847 reporter.log2('Entered');
4848
4849 #
4850 # Paths.
4851 #
4852 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom");
4853 sScratchDstDir1Hst = os.path.join(sScratchHst, "dstdir1");
4854 sScratchDstDir2Hst = os.path.join(sScratchHst, "dstdir2");
4855 sScratchDstDir3Hst = os.path.join(sScratchHst, "dstdir3");
4856 oExistingFileGst = self.oTestFiles.chooseRandomFile();
4857 oNonEmptyDirGst = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True);
4858 oEmptyDirGst = self.oTestFiles.oEmptyDir;
4859
4860 if oTestVm.isWindows() or oTestVm.isOS2():
4861 sScratchGstInvalid = "?*|<invalid-name>";
4862 else:
4863 sScratchGstInvalid = None;
4864 if utils.getHostOs() in ('win', 'os2'):
4865 sScratchHstInvalid = "?*|<invalid-name>";
4866 else:
4867 sScratchHstInvalid = None;
4868
4869 if os.path.exists(sScratchHst):
4870 if base.wipeDirectory(sScratchHst) != 0:
4871 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
4872 else:
4873 try:
4874 os.mkdir(sScratchHst);
4875 except:
4876 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
4877
4878 reporter.log2('Creating host sub dirs ...');
4879
4880 for sSubDir in (sScratchDstDir1Hst, sScratchDstDir2Hst, sScratchDstDir3Hst):
4881 try:
4882 os.mkdir(sSubDir);
4883 except:
4884 return reporter.errorXcpt('os.mkdir(%s)' % (sSubDir, ));
4885
4886 reporter.log2('Defining tests ...');
4887
4888 #
4889 # Bad parameter tests.
4890 #
4891 atTests = [
4892 # Missing both source and destination:
4893 [ tdTestCopyFromFile(), tdTestResultFailure() ],
4894 [ tdTestCopyFromDir(), tdTestResultFailure() ],
4895 # Missing source.
4896 [ tdTestCopyFromFile(sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4897 [ tdTestCopyFromDir( sDst = sScratchHst), tdTestResultFailure() ],
4898 # Missing destination.
4899 [ tdTestCopyFromFile(oSrc = oExistingFileGst), tdTestResultFailure() ],
4900 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath), tdTestResultFailure() ],
4901 # Invalid flags:
4902 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somefile'), afFlags = [0x40000000]),
4903 tdTestResultFailure() ],
4904 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'somedir'), afFlags = [ 0x40000000] ),
4905 tdTestResultFailure() ],
4906 # Non-existing sources:
4907 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
4908 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4909 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
4910 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4911 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-file'),
4912 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4913 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-subdir'),
4914 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4915 # Non-existing destinations:
4916 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
4917 sDst = os.path.join(sScratchHst, 'no-such-directory', 'somefile') ), tdTestResultFailure() ],
4918 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'no-such-directory', 'somedir') ),
4919 tdTestResultFailure() ],
4920 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
4921 sDst = os.path.join(sScratchHst, 'no-such-directory-slash' + os.path.sep)),
4922 tdTestResultFailure() ],
4923 # Wrong source type:
4924 [ tdTestCopyFromFile(oSrc = oNonEmptyDirGst, sDst = os.path.join(sScratchHst, 'somefile') ), tdTestResultFailure() ],
4925 [ tdTestCopyFromDir(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somedir') ), tdTestResultFailure() ],
4926 ];
4927 # Bogus names:
4928 if sScratchHstInvalid:
4929 atTests.extend([
4930 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
4931 tdTestResultFailure() ],
4932 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
4933 tdTestResultFailure() ],
4934 ]);
4935 if sScratchGstInvalid:
4936 atTests.extend([
4937 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
4938 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4939 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
4940 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4941 ]);
4942
4943 #
4944 # Single file copying.
4945 #
4946 atTests.extend([
4947 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')),
4948 tdTestResultSuccess() ],
4949 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')), # Overwrite it
4950 tdTestResultSuccess() ],
4951 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile2')),
4952 tdTestResultSuccess() ],
4953 ]);
4954 if self.oTstDrv.fpApiVer > 5.2:
4955 # Copy into a directory.
4956 atTests.extend([
4957 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst), tdTestResultSuccess() ],
4958 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst + os.path.sep), tdTestResultSuccess() ],
4959 ]);
4960
4961 #
4962 # Directory tree copying:
4963 #
4964 atTests.extend([
4965 # Copy the empty guest directory (should end up as sScratchHst/empty):
4966 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultSuccess() ],
4967 # Repeat -- this time it should fail, as the destination directory already exists (and
4968 # DirectoryCopyFlag_CopyIntoExisting is not specified):
4969 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultFailure() ],
4970 # Add the DirectoryCopyFlag_CopyIntoExisting flag being set and it should work.
4971 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst,
4972 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4973 # Try again with trailing slash, should yield the same result:
4974 [ tdTestRemoveHostDir(os.path.join(sScratchDstDir1Hst, 'empty')), tdTestResult() ],
4975 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
4976 tdTestResultSuccess() ],
4977 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
4978 tdTestResultFailure() ],
4979 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep,
4980 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4981 # Copy with a different destination name just for the heck of it:
4982 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'empty2'), fIntoDst = True),
4983 tdTestResultFailure() ],
4984 ## bird 2021-12-15: These seems to be failing a lot, so I've temporarily disabled them. Please debug and re-enable.
4985 ## # Now the same using a directory with files in it:
4986 ## [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultSuccess() ],
4987 ## [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultFailure() ],
4988 ## [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst,
4989 ## afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4990 ## # Copy the entire test tree:
4991 ## [ tdTestCopyFromDir(sSrc = self.oTestFiles.oTreeDir.sPath, sDst = sScratchDstDir3Hst), tdTestResultSuccess() ],
4992 ]);
4993
4994 reporter.log2('Executing tests ...');
4995
4996 #
4997 # Execute the tests.
4998 #
4999 fRc = True;
5000 for (i, tTest) in enumerate(atTests):
5001 oCurTest = tTest[0]
5002 oCurRes = tTest[1] # type: tdTestResult
5003 if isinstance(oCurTest, tdTestCopyFrom):
5004 reporter.log('Testing #%d, %s: sSrc="%s", sDst="%s", afFlags="%s" ...'
5005 % (i, "directory" if isinstance(oCurTest, tdTestCopyFromDir) else "file",
5006 limitString(oCurTest.sSrc), limitString(oCurTest.sDst), oCurTest.afFlags,));
5007 else:
5008 reporter.log('Testing #%d, tdTestRemoveHostDir "%s" ...' % (i, oCurTest.sDir,));
5009 if isinstance(oCurTest, tdTestCopyFromDir) and self.oTstDrv.fpApiVer < 6.0:
5010 reporter.log('Skipping directoryCopyFromGuest test, not implemented in %s' % (self.oTstDrv.fpApiVer,));
5011 continue;
5012
5013 if isinstance(oCurTest, tdTestRemoveHostDir):
5014 fRc = oCurTest.execute(self.oTstDrv, oSession, oTxsSession, oTestVm, 'testing #%d' % (i,));
5015 else:
5016 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
5017 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyFrom: Test #%d' % (i,));
5018 if fRc2 is not True:
5019 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
5020 break;
5021
5022 if isinstance(oCurTest, tdTestCopyFromFile):
5023 fRc2 = self.gctrlCopyFileFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
5024 else:
5025 fRc2 = self.gctrlCopyDirFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
5026
5027 if fRc2 != oCurRes.fRc:
5028 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
5029
5030 fRc = oCurTest.closeSession() and fRc;
5031
5032 return (fRc, oTxsSession);
5033
5034 def testGuestCtrlUpdateAdditions(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
5035 """
5036 Tests updating the Guest Additions inside the guest.
5037
5038 """
5039
5040 ## @todo currently disabled everywhere.
5041 if self.oTstDrv.fpApiVer < 100.0:
5042 reporter.log("Skipping updating GAs everywhere for now...");
5043 return None;
5044
5045 # Skip test for updating Guest Additions if we run on a too old (Windows) guest.
5046 ##
5047 ## @todo make it work everywhere!
5048 ##
5049 if oTestVm.sKind in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
5050 reporter.log("Skipping updating GAs on old windows vm (sKind=%s)" % (oTestVm.sKind,));
5051 return (None, oTxsSession);
5052 if oTestVm.isOS2():
5053 reporter.log("Skipping updating GAs on OS/2 guest");
5054 return (None, oTxsSession);
5055
5056 sVBoxValidationKitIso = self.oTstDrv.sVBoxValidationKitIso;
5057 if not os.path.isfile(sVBoxValidationKitIso):
5058 return reporter.log('Validation Kit .ISO not found at "%s"' % (sVBoxValidationKitIso,));
5059
5060 sScratch = os.path.join(self.oTstDrv.sScratchPath, "testGctrlUpdateAdditions");
5061 try:
5062 os.makedirs(sScratch);
5063 except OSError as e:
5064 if e.errno != errno.EEXIST:
5065 return reporter.error('Failed: Unable to create scratch directory \"%s\"' % (sScratch,));
5066 reporter.log('Scratch path is: %s' % (sScratch,));
5067
5068 atTests = [];
5069 if oTestVm.isWindows():
5070 atTests.extend([
5071 # Source is missing.
5072 [ tdTestUpdateAdditions(sSrc = ''), tdTestResultFailure() ],
5073
5074 # Wrong flags.
5075 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
5076 afFlags = [ 1234 ]), tdTestResultFailure() ],
5077
5078 # Non-existing .ISO.
5079 [ tdTestUpdateAdditions(sSrc = "non-existing.iso"), tdTestResultFailure() ],
5080
5081 # Wrong .ISO.
5082 [ tdTestUpdateAdditions(sSrc = sVBoxValidationKitIso), tdTestResultFailure() ],
5083
5084 # The real thing.
5085 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso()),
5086 tdTestResultSuccess() ],
5087 # Test the (optional) installer arguments. This will extract the
5088 # installer into our guest's scratch directory.
5089 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
5090 asArgs = [ '/extract', '/D=' + sScratch ]),
5091 tdTestResultSuccess() ]
5092 # Some debg ISO. Only enable locally.
5093 #[ tdTestUpdateAdditions(
5094 # sSrc = "V:\\Downloads\\VBoxGuestAdditions-r80354.iso"),
5095 # tdTestResultSuccess() ]
5096 ]);
5097 else:
5098 reporter.log('No OS-specific tests for non-Windows yet!');
5099
5100 fRc = True;
5101 for (i, tTest) in enumerate(atTests):
5102 oCurTest = tTest[0] # type: tdTestUpdateAdditions
5103 oCurRes = tTest[1] # type: tdTestResult
5104 reporter.log('Testing #%d, sSrc="%s", afFlags="%s" ...' % (i, oCurTest.sSrc, oCurTest.afFlags,));
5105
5106 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
5107 fRc, _ = oCurTest.createSession('Test #%d' % (i,));
5108 if fRc is not True:
5109 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
5110 break;
5111
5112 try:
5113 oCurProgress = oCurTest.oGuest.updateGuestAdditions(oCurTest.sSrc, oCurTest.asArgs, oCurTest.afFlags);
5114 except:
5115 reporter.maybeErrXcpt(oCurRes.fRc, 'Updating Guest Additions exception for sSrc="%s", afFlags="%s":'
5116 % (oCurTest.sSrc, oCurTest.afFlags,));
5117 fRc = False;
5118 else:
5119 if oCurProgress is not None:
5120 oWrapperProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr,
5121 self.oTstDrv, "gctrlUpGA");
5122 oWrapperProgress.wait();
5123 if not oWrapperProgress.isSuccess():
5124 oWrapperProgress.logResult(fIgnoreErrors = not oCurRes.fRc);
5125 fRc = False;
5126 else:
5127 fRc = reporter.error('No progress object returned');
5128
5129 oCurTest.closeSession();
5130 if fRc is oCurRes.fRc:
5131 if fRc:
5132 ## @todo Verify if Guest Additions were really updated (build, revision, ...).
5133 ## @todo r=bird: Not possible since you're installing the same GAs as before...
5134 ## Maybe check creation dates on certain .sys/.dll/.exe files?
5135 pass;
5136 else:
5137 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
5138 break;
5139
5140 return (fRc, oTxsSession);
5141
5142
5143
5144class tdAddGuestCtrl(vbox.TestDriver): # pylint: disable=too-many-instance-attributes,too-many-public-methods
5145 """
5146 Guest control using VBoxService on the guest.
5147 """
5148
5149 def __init__(self):
5150 vbox.TestDriver.__init__(self);
5151 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
5152 self.asRsrcs = None;
5153 self.fQuick = False; # Don't skip lengthly tests by default.
5154 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
5155
5156 #
5157 # Overridden methods.
5158 #
5159 def showUsage(self):
5160 """
5161 Shows the testdriver usage.
5162 """
5163 rc = vbox.TestDriver.showUsage(self);
5164 reporter.log('');
5165 reporter.log('tdAddGuestCtrl Options:');
5166 reporter.log(' --quick');
5167 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
5168 return rc;
5169
5170 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
5171 """
5172 Parses the testdriver arguments from the command line.
5173 """
5174 if asArgs[iArg] == '--quick':
5175 self.parseOption(['--virt-modes', 'hwvirt'], 0);
5176 self.parseOption(['--cpu-counts', '1'], 0);
5177 self.fQuick = True;
5178 else:
5179 return vbox.TestDriver.parseOption(self, asArgs, iArg);
5180 return iArg + 1;
5181
5182 def actionConfig(self):
5183 if not self.importVBoxApi(): # So we can use the constant below.
5184 return False;
5185
5186 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
5187 sGaIso = self.getGuestAdditionsIso();
5188 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
5189
5190 def actionExecute(self):
5191 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
5192
5193 #
5194 # Test execution helpers.
5195 #
5196 def testOneCfg(self, oVM, oTestVm): # pylint: disable=too-many-statements
5197 """
5198 Runs the specified VM thru the tests.
5199
5200 Returns a success indicator on the general test execution. This is not
5201 the actual test result.
5202 """
5203
5204 self.logVmInfo(oVM);
5205
5206 fRc = True;
5207 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False);
5208 reporter.log("TxsSession: %s" % (oTxsSession,));
5209 if oSession is not None:
5210 self.addTask(oTxsSession);
5211
5212 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
5213
5214 # Cleanup.
5215 self.removeTask(oTxsSession);
5216 if not self.aoSubTstDrvs[0].oDebug.fNoExit:
5217 self.terminateVmBySession(oSession);
5218 else:
5219 fRc = False;
5220 return fRc;
5221
5222 def onExit(self, iRc):
5223 if self.aoSubTstDrvs[0].oDebug.fNoExit:
5224 return True
5225 return vbox.TestDriver.onExit(self, iRc);
5226
5227 def gctrlReportError(self, progress):
5228 """
5229 Helper function to report an error of a
5230 given progress object.
5231 """
5232 if progress is None:
5233 reporter.log('No progress object to print error for');
5234 else:
5235 errInfo = progress.errorInfo;
5236 if errInfo:
5237 reporter.log('%s' % (errInfo.text,));
5238 return False;
5239
5240 def gctrlGetRemainingTime(self, msTimeout, msStart):
5241 """
5242 Helper function to return the remaining time (in ms)
5243 based from a timeout value and the start time (both in ms).
5244 """
5245 if msTimeout == 0:
5246 return 0xFFFFFFFE; # Wait forever.
5247 msElapsed = base.timestampMilli() - msStart;
5248 if msElapsed > msTimeout:
5249 return 0; # No time left.
5250 return msTimeout - msElapsed;
5251
5252 def testGuestCtrlManual(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements,unused-argument,unused-variable
5253 """
5254 For manually testing certain bits.
5255 """
5256
5257 reporter.log('Manual testing ...');
5258 fRc = True;
5259
5260 sUser = 'Administrator';
5261 sPassword = 'password';
5262
5263 oGuest = oSession.o.console.guest;
5264 oGuestSession = oGuest.createSession(sUser,
5265 sPassword,
5266 "", "Manual Test");
5267
5268 aWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
5269 _ = oGuestSession.waitForArray(aWaitFor, 30 * 1000);
5270
5271 sCmd = self.getGuestSystemShell(oTestVm);
5272 asArgs = [ sCmd, '/C', 'dir', '/S', 'c:\\windows' ];
5273 aEnv = [];
5274 afFlags = [];
5275
5276 for _ in xrange(100):
5277 oProc = oGuestSession.processCreate(sCmd, asArgs if self.fpApiVer >= 5.0 else asArgs[1:],
5278 aEnv, afFlags, 30 * 1000);
5279
5280 aWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate ];
5281 _ = oProc.waitForArray(aWaitFor, 30 * 1000);
5282
5283 oGuestSession.close();
5284 oGuestSession = None;
5285
5286 time.sleep(5);
5287
5288 oSession.o.console.PowerDown();
5289
5290 return (fRc, oTxsSession);
5291
5292if __name__ == '__main__':
5293 sys.exit(tdAddGuestCtrl().main(sys.argv));
Note: See TracBrowser for help on using the repository browser.

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