VirtualBox

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

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

Validation Kit: Fixed lots of warnings, based on pylint 2.12.2.

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

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