VirtualBox

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

Last change on this file since 99698 was 99519, checked in by vboxsync, 23 months ago

Validation Kit/Guest Control: Some older Linux test VMs (like tst-rhel5) don't have a pre-configured 'vbox' user. So make sure that this user exists and has the appropriate password set. Ignore any errors.

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