VirtualBox

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

Last change on this file since 93307 was 93169, checked in by vboxsync, 3 years ago

Validation Kit/Guest Control: Only enable guest session reboot testing when --add-guest-ctrl-skip-known-bugs is not defined (needs fixing first).

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

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