VirtualBox

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

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

ValKit/tests: pylint 2.9.6 adjustments (mostly about using 'with' statements).

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

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