VirtualBox

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

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

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