VirtualBox

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

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

scm copyright and license note update

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