VirtualBox

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

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

Validation Kit/Guest Control: Log status changes (as error) when waiting to start for a guest session (most certainly a bug, needs investigation) [fix, forgot the break on success].

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

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