VirtualBox

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

Last change on this file since 84930 was 84930, checked in by vboxsync, 5 years ago

tdAddGuestCtrl.py: pylint fix.

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

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