VirtualBox

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

Last change on this file since 79318 was 79318, checked in by vboxsync, 6 years ago

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

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