VirtualBox

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

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

Validation Kit/Guest Control: Don't report expected non-existing paths / files as an error.

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