VirtualBox

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

Last change on this file since 80852 was 80852, checked in by vboxsync, 5 years ago

ValKit/tdAddGuestCtrl.py: Adjusted session environment tests to match current IPRT/main environment validation. [fix]

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