VirtualBox

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

Last change on this file since 99250 was 99188, checked in by vboxsync, 23 months ago

Validation Kit/Guest Control: Fixes for the parameter assignment of the internal execution testcase description. bugref:8053

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