VirtualBox

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

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

Validation Kit/tdAddGuestCtrl.py: Return expected result when handling empty sources in gctrlCopy[Dir|File]From().

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