VirtualBox

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

Last change on this file since 99463 was 99399, checked in by vboxsync, 2 years ago

Validation Kit/tdAddGuestCtrl.py: Made cross testing (different VBox versions for host / guest) a bit more flexible by querying the installed Guest Additions version on runtime:

  • Use a different coreutils path for old OL6 guests (see comments).
  • Only do process execution CWD testing on guests with installed Guest Additions >= 7.1.

[Build fix]

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

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