VirtualBox

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

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

ValKit/tdAddGuestCtrl.py: Fixed regression from r148744 which assumed afFlags were always lists and didn't account for they defaulting to None. [missed a bit] bugref:9320

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