VirtualBox

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

Last change on this file since 84950 was 84950, checked in by vboxsync, 4 years ago

Validation Kit/tdAddGuestCtrl.py: Skip enabling verbose VBoxService logging if TXS is too old (buggy) to handle this.

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

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