VirtualBox

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

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

Validation Kit/tests + Guest Control: Added (optional) parameter for passing "compatible with" specs to the TestFileSet object and use this in Guest Control testing.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 238.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# pylint: disable=too-many-lines
4
5"""
6VirtualBox Validation Kit - Guest Control Tests.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2020 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 83308 $"
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 asCompatibleWith = None;
1538 if oTestVm.isWindows():
1539 asCompatibleWith = [ 'win' ];
1540 self.oTestFiles = vboxtestfileset.TestFileSet(oTestVm,
1541 self.getGuestTempDir(oTestVm), 'addgst-1',
1542 cchMaxPath = cchMaxPath, asCompatibleWith = asCompatibleWith);
1543 return self.oTestFiles.upload(oTxsSession, self.oTstDrv);
1544
1545
1546 #
1547 # gctrlXxxx stuff.
1548 #
1549
1550 def gctrlCopyFileFrom(self, oGuestSession, oTest, fExpected):
1551 """
1552 Helper function to copy a single file from the guest to the host.
1553 """
1554 #
1555 # Do the copying.
1556 #
1557 reporter.log2('Copying guest file "%s" to host "%s"' % (oTest.sSrc, oTest.sDst));
1558 try:
1559 if self.oTstDrv.fpApiVer >= 5.0:
1560 oCurProgress = oGuestSession.fileCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.afFlags);
1561 else:
1562 oCurProgress = oGuestSession.copyFrom(oTest.sSrc, oTest.sDst, oTest.afFlags);
1563 except:
1564 reporter.maybeErrXcpt(fExpected, 'Copy from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1565 return False;
1566 if oCurProgress is None:
1567 return reporter.error('No progress object returned');
1568 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlFileCopyFrom");
1569 oProgress.wait();
1570 if not oProgress.isSuccess():
1571 oProgress.logResult(fIgnoreErrors = not fExpected);
1572 return False;
1573
1574 #
1575 # Check the result if we can.
1576 #
1577 if oTest.oSrc:
1578 assert isinstance(oTest.oSrc, testfileset.TestFile);
1579 sDst = oTest.sDst;
1580 if os.path.isdir(sDst):
1581 sDst = os.path.join(sDst, oTest.oSrc.sName);
1582 try:
1583 oFile = open(sDst, 'rb');
1584 except:
1585 return reporter.errorXcpt('open(%s) failed during verfication' % (sDst,));
1586 fEqual = oTest.oSrc.equalFile(oFile);
1587 oFile.close();
1588 if not fEqual:
1589 return reporter.error('Content differs for "%s"' % (sDst,));
1590
1591 return True;
1592
1593 def __compareTestDir(self, oDir, sHostPath): # type: (testfileset.TestDir, str) -> bool
1594 """
1595 Recursively compare the content of oDir and sHostPath.
1596
1597 Returns True on success, False + error logging on failure.
1598
1599 Note! This ASSUMES that nothing else was copied to sHostPath!
1600 """
1601 #
1602 # First check out all the entries and files in the directory.
1603 #
1604 dLeftUpper = dict(oDir.dChildrenUpper);
1605 try:
1606 asEntries = os.listdir(sHostPath);
1607 except:
1608 return reporter.errorXcpt('os.listdir(%s) failed' % (sHostPath,));
1609
1610 fRc = True;
1611 for sEntry in asEntries:
1612 sEntryUpper = sEntry.upper();
1613 if sEntryUpper not in dLeftUpper:
1614 fRc = reporter.error('Unexpected entry "%s" in "%s"' % (sEntry, sHostPath,));
1615 else:
1616 oFsObj = dLeftUpper[sEntryUpper];
1617 del dLeftUpper[sEntryUpper];
1618
1619 if isinstance(oFsObj, testfileset.TestFile):
1620 sFilePath = os.path.join(sHostPath, oFsObj.sName);
1621 try:
1622 oFile = open(sFilePath, 'rb');
1623 except:
1624 fRc = reporter.errorXcpt('open(%s) failed during verfication' % (sFilePath,));
1625 else:
1626 fEqual = oFsObj.equalFile(oFile);
1627 oFile.close();
1628 if not fEqual:
1629 fRc = reporter.error('Content differs for "%s"' % (sFilePath,));
1630
1631 # List missing entries:
1632 for sKey in dLeftUpper:
1633 oEntry = dLeftUpper[sKey];
1634 fRc = reporter.error('%s: Missing %s "%s" (src path: %s)'
1635 % (sHostPath, oEntry.sName,
1636 'file' if isinstance(oEntry, testfileset.TestFile) else 'directory', oEntry.sPath));
1637
1638 #
1639 # Recurse into subdirectories.
1640 #
1641 for oFsObj in oDir.aoChildren:
1642 if isinstance(oFsObj, testfileset.TestDir):
1643 fRc = self.__compareTestDir(oFsObj, os.path.join(sHostPath, oFsObj.sName)) and fRc;
1644 return fRc;
1645
1646 def gctrlCopyDirFrom(self, oGuestSession, oTest, fExpected):
1647 """
1648 Helper function to copy a directory from the guest to the host.
1649 """
1650 #
1651 # Do the copying.
1652 #
1653 reporter.log2('Copying guest dir "%s" to host "%s"' % (oTest.sSrc, oTest.sDst));
1654 try:
1655 oCurProgress = oGuestSession.directoryCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.afFlags);
1656 except:
1657 reporter.maybeErrXcpt(fExpected, 'Copy dir from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1658 return False;
1659 if oCurProgress is None:
1660 return reporter.error('No progress object returned');
1661
1662 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlDirCopyFrom");
1663 oProgress.wait();
1664 if not oProgress.isSuccess():
1665 oProgress.logResult(fIgnoreErrors = not fExpected);
1666 return False;
1667
1668 #
1669 # Check the result if we can.
1670 #
1671 if oTest.oSrc:
1672 assert isinstance(oTest.oSrc, testfileset.TestDir);
1673 sDst = oTest.sDst;
1674 if oTest.fIntoDst:
1675 return self.__compareTestDir(oTest.oSrc, os.path.join(sDst, oTest.oSrc.sName));
1676 oDummy = testfileset.TestDir(None, 'dummy');
1677 oDummy.aoChildren = [oTest.oSrc,]
1678 oDummy.dChildrenUpper = { oTest.oSrc.sName.upper(): oTest.oSrc, };
1679 return self.__compareTestDir(oDummy, sDst);
1680 return True;
1681
1682 def gctrlCopyFileTo(self, oGuestSession, sSrc, sDst, afFlags, fIsError):
1683 """
1684 Helper function to copy a single file from the host to the guest.
1685 """
1686 reporter.log2('Copying host file "%s" to guest "%s" (flags %s)' % (sSrc, sDst, afFlags));
1687 try:
1688 if self.oTstDrv.fpApiVer >= 5.0:
1689 oCurProgress = oGuestSession.fileCopyToGuest(sSrc, sDst, afFlags);
1690 else:
1691 oCurProgress = oGuestSession.copyTo(sSrc, sDst, afFlags);
1692 except:
1693 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1694 return False;
1695
1696 if oCurProgress is None:
1697 return reporter.error('No progress object returned');
1698 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1699
1700 try:
1701 oProgress.wait();
1702 if not oProgress.isSuccess():
1703 oProgress.logResult(fIgnoreErrors = not fIsError);
1704 return False;
1705 except:
1706 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1707 return False;
1708 return True;
1709
1710 def gctrlCopyDirTo(self, oGuestSession, sSrc, sDst, afFlags, fIsError):
1711 """
1712 Helper function to copy a directory tree from the host to the guest.
1713 """
1714 reporter.log2('Copying host directory "%s" to guest "%s" (flags %s)' % (sSrc, sDst, afFlags));
1715 try:
1716 oCurProgress = oGuestSession.directoryCopyToGuest(sSrc, sDst, afFlags);
1717 except:
1718 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1719 return False;
1720
1721 if oCurProgress is None:
1722 return reporter.error('No progress object returned');
1723 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1724
1725 try:
1726 oProgress.wait();
1727 if not oProgress.isSuccess():
1728 oProgress.logResult(fIgnoreErrors = not fIsError);
1729 return False;
1730 except:
1731 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1732 return False;
1733 return True;
1734
1735 def gctrlCreateDir(self, oTest, oRes, oGuestSession):
1736 """
1737 Helper function to create a guest directory specified in the current test.
1738 """
1739 reporter.log2('Creating directory "%s"' % (oTest.sDirectory,));
1740 try:
1741 oGuestSession.directoryCreate(oTest.sDirectory, oTest.fMode, oTest.afFlags);
1742 except:
1743 reporter.maybeErrXcpt(oRes.fRc, 'Failed to create "%s" fMode=%o afFlags=%s'
1744 % (oTest.sDirectory, oTest.fMode, oTest.afFlags,));
1745 return not oRes.fRc;
1746 if oRes.fRc is not True:
1747 return reporter.error('Did not expect to create directory "%s"!' % (oTest.sDirectory,));
1748
1749 # Check if the directory now exists.
1750 try:
1751 if self.oTstDrv.fpApiVer >= 5.0:
1752 fDirExists = oGuestSession.directoryExists(oTest.sDirectory, False);
1753 else:
1754 fDirExists = oGuestSession.directoryExists(oTest.sDirectory);
1755 except:
1756 return reporter.errorXcpt('directoryExists failed on "%s"!' % (oTest.sDirectory,));
1757 if not fDirExists:
1758 return reporter.errorXcpt('directoryExists returned False on "%s" after directoryCreate succeeded!'
1759 % (oTest.sDirectory,));
1760 return True;
1761
1762 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, sSubDir = None):
1763 """
1764 Helper function to recursively read a guest directory tree specified in the current test.
1765 """
1766 sDir = oTest.sDirectory;
1767 sFilter = oTest.sFilter;
1768 afFlags = oTest.afFlags;
1769 oTestVm = oTest.oCreds.oTestVm;
1770 sCurDir = oTestVm.pathJoin(sDir, sSubDir) if sSubDir else sDir;
1771
1772 fRc = True; # Be optimistic.
1773 cDirs = 0; # Number of directories read.
1774 cFiles = 0; # Number of files read.
1775 cOthers = 0; # Other files.
1776
1777 ##
1778 ## @todo r=bird: Unlike fileOpen, directoryOpen will not fail if the directory does not exist.
1779 ## This is of course a bug in the implementation, as it is documented to return
1780 ## VBOX_E_OBJECT_NOT_FOUND or VBOX_E_IPRT_ERROR!
1781 ##
1782
1783 # Open the directory:
1784 #reporter.log2('Directory="%s", filter="%s", afFlags="%s"' % (sCurDir, sFilter, afFlags));
1785 try:
1786 oCurDir = oGuestSession.directoryOpen(sCurDir, sFilter, afFlags);
1787 except:
1788 reporter.maybeErrXcpt(fIsError, 'sCurDir=%s sFilter=%s afFlags=%s' % (sCurDir, sFilter, afFlags,))
1789 return (False, 0, 0, 0);
1790
1791 # Read the directory.
1792 while fRc is True:
1793 try:
1794 oFsObjInfo = oCurDir.read();
1795 except Exception as oXcpt:
1796 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1797 ##
1798 ## @todo r=bird: Change this to reporter.errorXcpt() once directoryOpen() starts
1799 ## working the way it is documented.
1800 ##
1801 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,)); # See above why 'maybe'.
1802 fRc = False;
1803 #else: reporter.log2('\tNo more directory entries for "%s"' % (sCurDir,));
1804 break;
1805
1806 try:
1807 sName = oFsObjInfo.name;
1808 eType = oFsObjInfo.type;
1809 except:
1810 fRc = reporter.errorXcpt();
1811 break;
1812
1813 if sName in ('.', '..', ):
1814 if eType != vboxcon.FsObjType_Directory:
1815 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1816 % (sName, eType, vboxcon.FsObjType_Directory));
1817 elif eType == vboxcon.FsObjType_Directory:
1818 #reporter.log2(' Directory "%s"' % oFsObjInfo.name);
1819 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError,
1820 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName);
1821 fRc = aSubResult[0];
1822 cDirs += aSubResult[1] + 1;
1823 cFiles += aSubResult[2];
1824 cOthers += aSubResult[3];
1825 elif eType is vboxcon.FsObjType_File:
1826 #reporter.log2(' File "%s"' % oFsObjInfo.name);
1827 cFiles += 1;
1828 elif eType is vboxcon.FsObjType_Symlink:
1829 #reporter.log2(' Symlink "%s" -- not tested yet' % oFsObjInfo.name);
1830 cOthers += 1;
1831 elif oTestVm.isWindows() \
1832 or oTestVm.isOS2() \
1833 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock,
1834 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut):
1835 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' %
1836 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,));
1837 else:
1838 cOthers += 1;
1839
1840 # Close the directory
1841 try:
1842 oCurDir.close();
1843 except:
1844 fRc = reporter.errorXcpt('sCurDir=%s' % (sCurDir));
1845
1846 return (fRc, cDirs, cFiles, cOthers);
1847
1848 def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (testfileset.TestDir) -> bool
1849 """
1850 Helper function to recursively read a guest directory tree specified in the current test.
1851 """
1852
1853 #
1854 # Process the directory.
1855 #
1856
1857 # Open the directory:
1858 try:
1859 oCurDir = oGuestSession.directoryOpen(oDir.sPath, '', None);
1860 except:
1861 return reporter.errorXcpt('sPath=%s' % (oDir.sPath,));
1862
1863 # Read the directory.
1864 dLeftUpper = dict(oDir.dChildrenUpper);
1865 cDot = 0;
1866 cDotDot = 0;
1867 fRc = True;
1868 while True:
1869 try:
1870 oFsObjInfo = oCurDir.read();
1871 except Exception as oXcpt:
1872 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1873 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath,));
1874 break;
1875
1876 try:
1877 sName = oFsObjInfo.name;
1878 eType = oFsObjInfo.type;
1879 cbFile = oFsObjInfo.objectSize;
1880 ## @todo check further attributes.
1881 except:
1882 fRc = reporter.errorXcpt();
1883 break;
1884
1885 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment:
1886 if sName in ('.', '..', ):
1887 if eType != vboxcon.FsObjType_Directory:
1888 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1889 % (sName, eType, vboxcon.FsObjType_Directory));
1890 if sName == '.': cDot += 1;
1891 else: cDotDot += 1;
1892 else:
1893 # Find the child and remove it from the dictionary.
1894 sNameUpper = sName.upper();
1895 oFsObj = dLeftUpper.get(sNameUpper);
1896 if oFsObj is None:
1897 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!'
1898 % (sName, oDir.sPath, eType, cbFile,));
1899 else:
1900 del dLeftUpper[sNameUpper];
1901
1902 # Check type
1903 if isinstance(oFsObj, testfileset.TestDir):
1904 if eType != vboxcon.FsObjType_Directory:
1905 fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
1906 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
1907 elif isinstance(oFsObj, testfileset.TestFile):
1908 if eType != vboxcon.FsObjType_File:
1909 fRc = reporter.error('%s: expected file (%d), got eType=%d!'
1910 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,));
1911 else:
1912 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),));
1913
1914 # Check the name.
1915 if oFsObj.sName != sName:
1916 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,));
1917
1918 # Check the size if a file.
1919 if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent:
1920 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,));
1921
1922 ## @todo check timestamps and attributes.
1923
1924 # Close the directory
1925 try:
1926 oCurDir.close();
1927 except:
1928 fRc = reporter.errorXcpt('oDir.sPath=%s' % (oDir.sPath,));
1929
1930 # Any files left over?
1931 for sKey in dLeftUpper:
1932 oFsObj = dLeftUpper[sKey];
1933 fRc = reporter.error('%s: Was not returned! (%s)' % (oFsObj.sPath, type(oFsObj),));
1934
1935 # Check the dot and dot-dot counts.
1936 if cDot != 1:
1937 fRc = reporter.error('%s: Found %s "." entries, expected exactly 1!' % (oDir.sPath, cDot,));
1938 if cDotDot != 1:
1939 fRc = reporter.error('%s: Found %s ".." entries, expected exactly 1!' % (oDir.sPath, cDotDot,));
1940
1941 #
1942 # Recurse into subdirectories using info from oDir.
1943 #
1944 for oFsObj in oDir.aoChildren:
1945 if isinstance(oFsObj, testfileset.TestDir):
1946 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc;
1947
1948 return fRc;
1949
1950 def gctrlExecDoTest(self, i, oTest, oRes, oGuestSession):
1951 """
1952 Wrapper function around gctrlExecute to provide more sanity checking
1953 when needed in actual execution tests.
1954 """
1955 reporter.log('Testing #%d, cmd="%s" ...' % (i, oTest.sCmd));
1956 fRcExec = self.gctrlExecute(oTest, oGuestSession, oRes.fRc);
1957 if fRcExec == oRes.fRc:
1958 fRc = True;
1959 if fRcExec is True:
1960 # Compare exit status / code on successful process execution.
1961 if oTest.uExitStatus != oRes.uExitStatus \
1962 or oTest.iExitCode != oRes.iExitCode:
1963 fRc = reporter.error('Test #%d (%s) failed: Got exit status + code %d,%d, expected %d,%d'
1964 % (i, oTest.asArgs, oTest.uExitStatus, oTest.iExitCode,
1965 oRes.uExitStatus, oRes.iExitCode));
1966
1967 # Compare test / result buffers on successful process execution.
1968 if oTest.sBuf is not None and oRes.sBuf is not None:
1969 if not utils.areBytesEqual(oTest.sBuf, oRes.sBuf):
1970 fRc = reporter.error('Test #%d (%s) failed: Got buffer\n%s (%d bytes), expected\n%s (%d bytes)'
1971 % (i, oTest.asArgs,
1972 map(hex, map(ord, oTest.sBuf)), len(oTest.sBuf),
1973 map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf)));
1974 reporter.log2('Test #%d passed: Buffers match (%d bytes)' % (i, len(oRes.sBuf)));
1975 elif oRes.sBuf and not oTest.sBuf:
1976 fRc = reporter.error('Test #%d (%s) failed: Got no buffer data, expected\n%s (%dbytes)' %
1977 (i, oTest.asArgs, map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf),));
1978
1979 if oRes.cbStdOut is not None and oRes.cbStdOut != oTest.cbStdOut:
1980 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stdout data, expected %d'
1981 % (i, oTest.asArgs, oTest.cbStdOut, oRes.cbStdOut));
1982 if oRes.cbStdErr is not None and oRes.cbStdErr != oTest.cbStdErr:
1983 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stderr data, expected %d'
1984 % (i, oTest.asArgs, oTest.cbStdErr, oRes.cbStdErr));
1985 else:
1986 fRc = reporter.error('Test #%d (%s) failed: Got %s, expected %s' % (i, oTest.asArgs, fRcExec, oRes.fRc));
1987 return fRc;
1988
1989 def gctrlExecute(self, oTest, oGuestSession, fIsError):
1990 """
1991 Helper function to execute a program on a guest, specified in the current test.
1992
1993 Note! This weirdo returns results (process exitcode and status) in oTest.
1994 """
1995 fRc = True; # Be optimistic.
1996
1997 # Reset the weird result stuff:
1998 oTest.cbStdOut = 0;
1999 oTest.cbStdErr = 0;
2000 oTest.sBuf = '';
2001 oTest.uExitStatus = 0;
2002 oTest.iExitCode = 0;
2003
2004 ## @todo Compare execution timeouts!
2005 #tsStart = base.timestampMilli();
2006
2007 try:
2008 reporter.log2('Using session user=%s, sDomain=%s, name=%s, timeout=%d'
2009 % (oGuestSession.user, oGuestSession.domain, oGuestSession.name, oGuestSession.timeout,));
2010 except:
2011 return reporter.errorXcpt();
2012
2013 #
2014 # Start the process:
2015 #
2016 reporter.log2('Executing sCmd=%s, afFlags=%s, timeoutMS=%d, asArgs=%s, asEnv=%s'
2017 % (oTest.sCmd, oTest.afFlags, oTest.timeoutMS, oTest.asArgs, oTest.aEnv,));
2018 try:
2019 oProcess = oGuestSession.processCreate(oTest.sCmd,
2020 oTest.asArgs if self.oTstDrv.fpApiVer >= 5.0 else oTest.asArgs[1:],
2021 oTest.aEnv, oTest.afFlags, oTest.timeoutMS);
2022 except:
2023 reporter.maybeErrXcpt(fIsError, 'asArgs=%s' % (oTest.asArgs,));
2024 return False;
2025 if oProcess is None:
2026 return reporter.error('oProcess is None! (%s)' % (oTest.asArgs,));
2027
2028 #time.sleep(5); # try this if you want to see races here.
2029
2030 # Wait for the process to start properly:
2031 reporter.log2('Process start requested, waiting for start (%dms) ...' % (oTest.timeoutMS,));
2032 iPid = -1;
2033 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Start, ];
2034 try:
2035 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
2036 except:
2037 reporter.maybeErrXcpt(fIsError, 'waitforArray failed for asArgs=%s' % (oTest.asArgs,));
2038 fRc = False;
2039 else:
2040 try:
2041 eStatus = oProcess.status;
2042 iPid = oProcess.PID;
2043 except:
2044 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2045 else:
2046 reporter.log2('Wait result returned: %d, current process status is: %d' % (eWaitResult, eStatus,));
2047
2048 #
2049 # Wait for the process to run to completion if necessary.
2050 #
2051 # Note! The above eWaitResult return value can be ignored as it will
2052 # (mostly) reflect the process status anyway.
2053 #
2054 if eStatus == vboxcon.ProcessStatus_Started:
2055
2056 # What to wait for:
2057 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate, ];
2058 if vboxcon.ProcessCreateFlag_WaitForStdOut in oTest.afFlags:
2059 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdOut);
2060 if vboxcon.ProcessCreateFlag_WaitForStdErr in oTest.afFlags:
2061 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdErr);
2062 ## @todo Add vboxcon.ProcessWaitForFlag_StdIn.
2063
2064 reporter.log2('Process (PID %d) started, waiting for termination (%dms), aeWaitFor=%s ...'
2065 % (iPid, oTest.timeoutMS, aeWaitFor));
2066 acbFdOut = [0,0,0];
2067 while True:
2068 try:
2069 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
2070 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
2071 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
2072 try: oProcess.close();
2073 except: pass;
2074 break;
2075 except:
2076 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2077 break;
2078 reporter.log2('Wait returned: %d' % (eWaitResult,));
2079
2080 # Process output:
2081 for eFdResult, iFd, sFdNm in [ (vboxcon.ProcessWaitResult_StdOut, 1, 'stdout'),
2082 (vboxcon.ProcessWaitResult_StdErr, 2, 'stderr'), ]:
2083 if eWaitResult in (eFdResult, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
2084 reporter.log2('Reading %s ...' % (sFdNm,));
2085 try:
2086 abBuf = oProcess.Read(1, 64 * 1024, oTest.timeoutMS);
2087 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
2088 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
2089 try: oProcess.close();
2090 except: pass;
2091 except:
2092 pass; ## @todo test for timeouts and fail on anything else!
2093 else:
2094 if abBuf:
2095 reporter.log2('Process (PID %d) got %d bytes of %s data' % (iPid, len(abBuf), sFdNm,));
2096 acbFdOut[iFd] += len(abBuf);
2097 oTest.sBuf = abBuf; ## @todo Figure out how to uniform + append!
2098
2099 ## Process input (todo):
2100 #if eWaitResult in (vboxcon.ProcessWaitResult_StdIn, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
2101 # reporter.log2('Process (PID %d) needs stdin data' % (iPid,));
2102
2103 # Termination or error?
2104 if eWaitResult in (vboxcon.ProcessWaitResult_Terminate,
2105 vboxcon.ProcessWaitResult_Error,
2106 vboxcon.ProcessWaitResult_Timeout,):
2107 try: eStatus = oProcess.status;
2108 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2109 reporter.log2('Process (PID %d) reported terminate/error/timeout: %d, status: %d'
2110 % (iPid, eWaitResult, eStatus,));
2111 break;
2112
2113 # End of the wait loop.
2114 _, oTest.cbStdOut, oTest.cbStdErr = acbFdOut;
2115
2116 try: eStatus = oProcess.status;
2117 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2118 reporter.log2('Final process status (PID %d) is: %d' % (iPid, eStatus));
2119 reporter.log2('Process (PID %d) %d stdout, %d stderr' % (iPid, oTest.cbStdOut, oTest.cbStdErr));
2120
2121 #
2122 # Get the final status and exit code of the process.
2123 #
2124 try:
2125 oTest.uExitStatus = oProcess.status;
2126 oTest.iExitCode = oProcess.exitCode;
2127 except:
2128 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2129 reporter.log2('Process (PID %d) has exit code: %d; status: %d ' % (iPid, oTest.iExitCode, oTest.uExitStatus));
2130 return fRc;
2131
2132 def testGuestCtrlSessionEnvironment(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2133 """
2134 Tests the guest session environment changes.
2135 """
2136 aoTests = [
2137 # Check basic operations.
2138 tdTestSessionEx([ # Initial environment is empty.
2139 tdStepSessionCheckEnv(),
2140 # Check clearing empty env.
2141 tdStepSessionClearEnv(),
2142 tdStepSessionCheckEnv(),
2143 # Check set.
2144 tdStepSessionSetEnv('FOO', 'BAR'),
2145 tdStepSessionCheckEnv(['FOO=BAR',]),
2146 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
2147 tdStepSessionClearEnv(),
2148 tdStepSessionCheckEnv(),
2149 # Check unset.
2150 tdStepSessionUnsetEnv('BAR'),
2151 tdStepSessionCheckEnv(['BAR']),
2152 tdStepSessionClearEnv(),
2153 tdStepSessionCheckEnv(),
2154 # Set + unset.
2155 tdStepSessionSetEnv('FOO', 'BAR'),
2156 tdStepSessionCheckEnv(['FOO=BAR',]),
2157 tdStepSessionUnsetEnv('FOO'),
2158 tdStepSessionCheckEnv(['FOO']),
2159 # Bulk environment changes (via attrib) (shall replace existing 'FOO').
2160 tdStepSessionBulkEnv( ['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
2161 tdStepSessionCheckEnv(['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
2162 ]),
2163 tdTestSessionEx([ # Check that setting the same value several times works.
2164 tdStepSessionSetEnv('FOO','BAR'),
2165 tdStepSessionCheckEnv([ 'FOO=BAR',]),
2166 tdStepSessionSetEnv('FOO','BAR2'),
2167 tdStepSessionCheckEnv([ 'FOO=BAR2',]),
2168 tdStepSessionSetEnv('FOO','BAR3'),
2169 tdStepSessionCheckEnv([ 'FOO=BAR3',]),
2170 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
2171 # Add a little unsetting to the mix.
2172 tdStepSessionSetEnv('BAR', 'BEAR'),
2173 tdStepSessionCheckEnv([ 'FOO=BAR3', 'BAR=BEAR',]),
2174 tdStepSessionUnsetEnv('FOO'),
2175 tdStepSessionCheckEnv([ 'FOO', 'BAR=BEAR',]),
2176 tdStepSessionSetEnv('FOO','BAR4'),
2177 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR',]),
2178 # The environment is case sensitive.
2179 tdStepSessionSetEnv('foo','BAR5'),
2180 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo=BAR5']),
2181 tdStepSessionUnsetEnv('foo'),
2182 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo']),
2183 ]),
2184 tdTestSessionEx([ # Bulk settings merges stuff, last entry standing.
2185 tdStepSessionBulkEnv(['FOO=bar', 'foo=bar', 'FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
2186 tdStepSessionCheckEnv(['FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
2187 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
2188 tdStepSessionBulkEnv(['2=1+1', 'FOO=doofus2', ]),
2189 tdStepSessionCheckEnv(['2=1+1', 'FOO=doofus2' ]),
2190 ]),
2191 # Invalid variable names.
2192 tdTestSessionEx([
2193 tdStepSessionSetEnv('', 'FOO', vbox.ComError.E_INVALIDARG),
2194 tdStepSessionCheckEnv(),
2195 tdStepRequireMinimumApiVer(5.0), # 4.3 is too relaxed checking input!
2196 tdStepSessionBulkEnv(['', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2197 tdStepSessionCheckEnv(),
2198 tdStepSessionSetEnv('FOO=', 'BAR', vbox.ComError.E_INVALIDARG),
2199 tdStepSessionCheckEnv(),
2200 ]),
2201 # A bit more weird keys/values.
2202 tdTestSessionEx([ tdStepSessionSetEnv('$$$', ''),
2203 tdStepSessionCheckEnv([ '$$$=',]), ]),
2204 tdTestSessionEx([ tdStepSessionSetEnv('$$$', '%%%'),
2205 tdStepSessionCheckEnv([ '$$$=%%%',]),
2206 ]),
2207 tdTestSessionEx([ tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
2208 tdStepSessionSetEnv(u'ß$%ß&', ''),
2209 tdStepSessionCheckEnv([ u'ß$%ß&=',]),
2210 ]),
2211 # Misc stuff.
2212 tdTestSessionEx([ tdStepSessionSetEnv('FOO', ''),
2213 tdStepSessionCheckEnv(['FOO=',]),
2214 ]),
2215 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
2216 tdStepSessionCheckEnv(['FOO=BAR',])
2217 ],),
2218 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
2219 tdStepSessionSetEnv('BAR', 'BAZ'),
2220 tdStepSessionCheckEnv([ 'FOO=BAR', 'BAR=BAZ',]),
2221 ]),
2222 ];
2223 # Leading '=' in the name is okay for windows guests in 6.1 and later (for driver letter CWDs).
2224 if (self.oTstDrv.fpApiVer < 6.1 and self.oTstDrv.fpApiVer >= 5.0) or not oTestVm.isWindows():
2225 aoTests.append(tdTestSessionEx([tdStepSessionSetEnv('=', '===', vbox.ComError.E_INVALIDARG),
2226 tdStepSessionCheckEnv(),
2227 tdStepSessionSetEnv('=FOO', 'BAR', vbox.ComError.E_INVALIDARG),
2228 tdStepSessionCheckEnv(),
2229 tdStepSessionBulkEnv(['=', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2230 tdStepSessionCheckEnv(),
2231 tdStepSessionBulkEnv(['=FOO', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2232 tdStepSessionCheckEnv(),
2233 tdStepSessionBulkEnv(['=D:=D:/tmp', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2234 tdStepSessionCheckEnv(),
2235 tdStepSessionSetEnv('=D:', 'D:/temp', vbox.ComError.E_INVALIDARG),
2236 tdStepSessionCheckEnv(),
2237 ]));
2238 elif self.oTstDrv.fpApiVer >= 6.1 and oTestVm.isWindows():
2239 aoTests.append(tdTestSessionEx([tdStepSessionSetEnv('=D:', 'D:/tmp'),
2240 tdStepSessionCheckEnv(['=D:=D:/tmp',]),
2241 tdStepSessionBulkEnv(['=D:=D:/temp', '=FOO', 'foo=bar']),
2242 tdStepSessionCheckEnv(['=D:=D:/temp', '=FOO', 'foo=bar']),
2243 tdStepSessionUnsetEnv('=D:'),
2244 tdStepSessionCheckEnv(['=D:', '=FOO', 'foo=bar']),
2245 ]));
2246
2247 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'SessionEnv');
2248
2249 def testGuestCtrlSession(self, oSession, oTxsSession, oTestVm):
2250 """
2251 Tests the guest session handling.
2252 """
2253
2254 #
2255 # Tests:
2256 #
2257 atTests = [
2258 # Invalid parameters.
2259 [ tdTestSession(sUser = ''), tdTestResultSession() ],
2260 # User account without a passwort - forbidden.
2261 [ tdTestSession(sPassword = "" ), tdTestResultSession() ],
2262 # Various wrong credentials.
2263 # Note! Only windows cares about sDomain, the other guests ignores it.
2264 # Note! On Guest Additions < 4.3 this always succeeds because these don't
2265 # support creating dedicated sessions. Instead, guest process creation
2266 # then will fail. See note below.
2267 [ tdTestSession(sPassword = 'bar'), tdTestResultSession() ],
2268 [ tdTestSession(sUser = 'foo', sPassword = 'bar'), tdTestResultSession() ],
2269 [ tdTestSession(sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
2270 [ tdTestSession(sUser = 'foo', sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
2271 ];
2272 if oTestVm.isWindows(): # domain is ignored elsewhere.
2273 atTests.append([ tdTestSession(sDomain = 'boo'), tdTestResultSession() ]);
2274
2275 # Finally, correct credentials.
2276 atTests.append([ tdTestSession(), tdTestResultSession(fRc = True, cNumSessions = 1) ]);
2277
2278 #
2279 # Run the tests.
2280 #
2281 fRc = True;
2282 for (i, tTest) in enumerate(atTests):
2283 oCurTest = tTest[0] # type: tdTestSession
2284 oCurRes = tTest[1] # type: tdTestResult
2285
2286 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2287 reporter.log('Testing #%d, user="%s", sPassword="%s", sDomain="%s" ...'
2288 % (i, oCurTest.oCreds.sUser, oCurTest.oCreds.sPassword, oCurTest.oCreds.sDomain));
2289 sCurGuestSessionName = 'testGuestCtrlSession: Test #%d' % (i,);
2290 fRc2, oCurGuestSession = oCurTest.createSession(sCurGuestSessionName, fIsError = oCurRes.fRc);
2291
2292 # See note about < 4.3 Guest Additions above.
2293 uProtocolVersion = 2;
2294 if oCurGuestSession is not None:
2295 try:
2296 uProtocolVersion = oCurGuestSession.protocolVersion;
2297 except:
2298 fRc = reporter.errorXcpt('Test #%d' % (i,));
2299
2300 if uProtocolVersion >= 2 and fRc2 is not oCurRes.fRc:
2301 fRc = reporter.error('Test #%d failed: Session creation failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
2302
2303 if fRc2 and oCurGuestSession is None:
2304 fRc = reporter.error('Test #%d failed: no session object' % (i,));
2305 fRc2 = False;
2306
2307 if fRc2:
2308 if uProtocolVersion >= 2: # For Guest Additions < 4.3 getSessionCount() always will return 1.
2309 cCurSessions = oCurTest.getSessionCount(self.oTstDrv.oVBoxMgr);
2310 if cCurSessions != oCurRes.cNumSessions:
2311 fRc = reporter.error('Test #%d failed: Session count does not match: Got %d, expected %d'
2312 % (i, cCurSessions, oCurRes.cNumSessions));
2313 try:
2314 sObjName = oCurGuestSession.name;
2315 except:
2316 fRc = reporter.errorXcpt('Test #%d' % (i,));
2317 else:
2318 if sObjName != sCurGuestSessionName:
2319 fRc = reporter.error('Test #%d failed: Session name does not match: Got "%s", expected "%s"'
2320 % (i, sObjName, sCurGuestSessionName));
2321 fRc2 = oCurTest.closeSession();
2322 if fRc2 is False:
2323 fRc = reporter.error('Test #%d failed: Session could not be closed' % (i,));
2324
2325 if fRc is False:
2326 return (False, oTxsSession);
2327
2328 #
2329 # Multiple sessions.
2330 #
2331 cMaxGuestSessions = 31; # Maximum number of concurrent guest session allowed.
2332 # Actually, this is 32, but we don't test session 0.
2333 aoMultiSessions = {};
2334 reporter.log2('Opening multiple guest tsessions at once ...');
2335 for i in xrange(cMaxGuestSessions + 1):
2336 aoMultiSessions[i] = tdTestSession(sSessionName = 'MultiSession #%d' % (i,));
2337 aoMultiSessions[i].setEnvironment(oSession, oTxsSession, oTestVm);
2338
2339 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
2340 reporter.log2('MultiSession test #%d count is %d' % (i, cCurSessions));
2341 if cCurSessions != i:
2342 return (reporter.error('MultiSession count is %d, expected %d' % (cCurSessions, i)), oTxsSession);
2343 fRc2, _ = aoMultiSessions[i].createSession('MultiSession #%d' % (i,), i < cMaxGuestSessions);
2344 if fRc2 is not True:
2345 if i < cMaxGuestSessions:
2346 return (reporter.error('MultiSession #%d test failed' % (i,)), oTxsSession);
2347 reporter.log('MultiSession #%d exceeded concurrent guest session count, good' % (i,));
2348 break;
2349
2350 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
2351 if cCurSessions is not cMaxGuestSessions:
2352 return (reporter.error('Final session count %d, expected %d ' % (cCurSessions, cMaxGuestSessions,)), oTxsSession);
2353
2354 reporter.log2('Closing MultiSessions ...');
2355 for i in xrange(cMaxGuestSessions):
2356 # Close this session:
2357 oClosedGuestSession = aoMultiSessions[i].oGuestSession;
2358 fRc2 = aoMultiSessions[i].closeSession();
2359 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr)
2360 reporter.log2('MultiSession #%d count is %d' % (i, cCurSessions,));
2361 if fRc2 is False:
2362 fRc = reporter.error('Closing MultiSession #%d failed' % (i,));
2363 elif cCurSessions != cMaxGuestSessions - (i + 1):
2364 fRc = reporter.error('Expected %d session after closing #%d, got %d instead'
2365 % (cMaxGuestSessions - (i + 1), cCurSessions, i,));
2366 assert aoMultiSessions[i].oGuestSession is None or not fRc2;
2367 ## @todo any way to check that the session is closed other than the 'sessions' attribute?
2368
2369 # Try check that none of the remaining sessions got closed.
2370 try:
2371 aoGuestSessions = self.oTstDrv.oVBoxMgr.getArray(atTests[0][0].oGuest, 'sessions');
2372 except:
2373 return (reporter.errorXcpt('i=%d/%d' % (i, cMaxGuestSessions,)), oTxsSession);
2374 if oClosedGuestSession in aoGuestSessions:
2375 fRc = reporter.error('i=%d/%d: %s should not be in %s'
2376 % (i, cMaxGuestSessions, oClosedGuestSession, aoGuestSessions));
2377 if i + 1 < cMaxGuestSessions: # Not sure what xrange(2,2) does...
2378 for j in xrange(i + 1, cMaxGuestSessions):
2379 if aoMultiSessions[j].oGuestSession not in aoGuestSessions:
2380 fRc = reporter.error('i=%d/j=%d/%d: %s should be in %s'
2381 % (i, j, cMaxGuestSessions, aoMultiSessions[j].oGuestSession, aoGuestSessions));
2382 ## @todo any way to check that they work?
2383
2384 ## @todo Test session timeouts.
2385
2386 return (fRc, oTxsSession);
2387
2388 def testGuestCtrlSessionFileRefs(self, oSession, oTxsSession, oTestVm):
2389 """
2390 Tests the guest session file reference handling.
2391 """
2392
2393 # Find a file to play around with:
2394 sFile = self.getGuestSystemFileForReading(oTestVm);
2395
2396 # Use credential defaults.
2397 oCreds = tdCtxCreds();
2398 oCreds.applyDefaultsIfNotSet(oTestVm);
2399
2400 # Number of stale guest files to create.
2401 cStaleFiles = 10;
2402
2403 #
2404 # Start a session.
2405 #
2406 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2407 try:
2408 oGuest = oSession.o.console.guest;
2409 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionFileRefs");
2410 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2411 except:
2412 return (reporter.errorXcpt(), oTxsSession);
2413
2414 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2415 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2416 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2417 reporter.log('Session successfully started');
2418
2419 #
2420 # Open guest files and "forget" them (stale entries).
2421 # For them we don't have any references anymore intentionally.
2422 #
2423 reporter.log2('Opening stale files');
2424 fRc = True;
2425 for i in xrange(0, cStaleFiles):
2426 try:
2427 if self.oTstDrv.fpApiVer >= 5.0:
2428 oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly, vboxcon.FileOpenAction_OpenExisting, 0);
2429 else:
2430 oGuestSession.fileOpen(sFile, "r", "oe", 0);
2431 # Note: Use a timeout in the call above for not letting the stale processes
2432 # hanging around forever. This can happen if the installed Guest Additions
2433 # do not support terminating guest processes.
2434 except:
2435 fRc = reporter.errorXcpt('Opening stale file #%d failed:' % (i,));
2436 break;
2437
2438 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2439 except: fRc = reporter.errorXcpt();
2440 else:
2441 if cFiles != cStaleFiles:
2442 fRc = reporter.error('Got %d stale files, expected %d' % (cFiles, cStaleFiles));
2443
2444 if fRc is True:
2445 #
2446 # Open non-stale files and close them again.
2447 #
2448 reporter.log2('Opening non-stale files');
2449 aoFiles = [];
2450 for i in xrange(0, cStaleFiles):
2451 try:
2452 if self.oTstDrv.fpApiVer >= 5.0:
2453 oCurFile = oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly,
2454 vboxcon.FileOpenAction_OpenExisting, 0);
2455 else:
2456 oCurFile = oGuestSession.fileOpen(sFile, "r", "oe", 0);
2457 aoFiles.append(oCurFile);
2458 except:
2459 fRc = reporter.errorXcpt('Opening non-stale file #%d failed:' % (i,));
2460 break;
2461
2462 # Check the count.
2463 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2464 except: fRc = reporter.errorXcpt();
2465 else:
2466 if cFiles != cStaleFiles * 2:
2467 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles * 2));
2468
2469 # Close them.
2470 reporter.log2('Closing all non-stale files again ...');
2471 for i, oFile in enumerate(aoFiles):
2472 try:
2473 oFile.close();
2474 except:
2475 fRc = reporter.errorXcpt('Closing non-stale file #%d failed:' % (i,));
2476
2477 # Check the count again.
2478 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2479 except: fRc = reporter.errorXcpt();
2480 # Here we count the stale files (that is, files we don't have a reference
2481 # anymore for) and the opened and then closed non-stale files (that we still keep
2482 # a reference in aoFiles[] for).
2483 if cFiles != cStaleFiles:
2484 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles));
2485
2486 #
2487 # Check that all (referenced) non-stale files are now in the "closed" state.
2488 #
2489 reporter.log2('Checking statuses of all non-stale files ...');
2490 for i, oFile in enumerate(aoFiles):
2491 try:
2492 eFileStatus = aoFiles[i].status;
2493 except:
2494 fRc = reporter.errorXcpt('Checking status of file #%d failed:' % (i,));
2495 else:
2496 if eFileStatus != vboxcon.FileStatus_Closed:
2497 fRc = reporter.error('Non-stale file #%d has status %d, expected %d'
2498 % (i, eFileStatus, vboxcon.FileStatus_Closed));
2499
2500 if fRc is True:
2501 reporter.log2('All non-stale files closed');
2502
2503 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2504 except: fRc = reporter.errorXcpt();
2505 else: reporter.log2('Final guest session file count: %d' % (cFiles,));
2506
2507 #
2508 # Now try to close the session and see what happens.
2509 # Note! Session closing is why we've been doing all the 'if fRc is True' stuff above rather than returning.
2510 #
2511 reporter.log2('Closing guest session ...');
2512 try:
2513 oGuestSession.close();
2514 except:
2515 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2516
2517 return (fRc, oTxsSession);
2518
2519 #def testGuestCtrlSessionDirRefs(self, oSession, oTxsSession, oTestVm):
2520 # """
2521 # Tests the guest session directory reference handling.
2522 # """
2523
2524 # fRc = True;
2525 # return (fRc, oTxsSession);
2526
2527 def testGuestCtrlSessionProcRefs(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2528 """
2529 Tests the guest session process reference handling.
2530 """
2531
2532 sCmd = self.getGuestSystemShell(oTestVm);
2533 asArgs = [sCmd,];
2534
2535 # Use credential defaults.
2536 oCreds = tdCtxCreds();
2537 oCreds.applyDefaultsIfNotSet(oTestVm);
2538
2539 # Number of stale guest processes to create.
2540 cStaleProcs = 10;
2541
2542 #
2543 # Start a session.
2544 #
2545 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2546 try:
2547 oGuest = oSession.o.console.guest;
2548 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionProcRefs");
2549 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2550 except:
2551 return (reporter.errorXcpt(), oTxsSession);
2552
2553 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2554 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2555 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2556 reporter.log('Session successfully started');
2557
2558 #
2559 # Fire off forever-running processes and "forget" them (stale entries).
2560 # For them we don't have any references anymore intentionally.
2561 #
2562 reporter.log2('Starting stale processes...');
2563 fRc = True;
2564 for i in xrange(0, cStaleProcs):
2565 try:
2566 oGuestSession.processCreate(sCmd,
2567 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], [],
2568 [ vboxcon.ProcessCreateFlag_WaitForStdOut ], 30 * 1000);
2569 # Note: Use a timeout in the call above for not letting the stale processes
2570 # hanging around forever. This can happen if the installed Guest Additions
2571 # do not support terminating guest processes.
2572 except:
2573 fRc = reporter.errorXcpt('Creating stale process #%d failed:' % (i,));
2574 break;
2575
2576 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2577 except: fRc = reporter.errorXcpt();
2578 else:
2579 if cProcesses != cStaleProcs:
2580 fRc = reporter.error('Got %d stale processes, expected %d' % (cProcesses, cStaleProcs));
2581
2582 if fRc is True:
2583 #
2584 # Fire off non-stale processes and wait for termination.
2585 #
2586 if oTestVm.isWindows() or oTestVm.isOS2():
2587 asArgs = [ sCmd, '/C', 'dir', '/S', self.getGuestSystemDir(oTestVm), ];
2588 else:
2589 asArgs = [ sCmd, '-c', 'ls -la ' + self.getGuestSystemDir(oTestVm), ];
2590 reporter.log2('Starting non-stale processes...');
2591 aoProcesses = [];
2592 for i in xrange(0, cStaleProcs):
2593 try:
2594 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2595 [], [], 0); # Infinite timeout.
2596 aoProcesses.append(oCurProc);
2597 except:
2598 fRc = reporter.errorXcpt('Creating non-stale process #%d failed:' % (i,));
2599 break;
2600
2601 reporter.log2('Waiting for non-stale processes to terminate...');
2602 for i, oProcess in enumerate(aoProcesses):
2603 try:
2604 eWaitResult = oProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 120 * 1000);
2605 eProcessStatus = oProcess.status;
2606 except:
2607 fRc = reporter.errorXcpt('Waiting for non-stale process #%d failed:' % (i,));
2608 else:
2609 if eProcessStatus != vboxcon.ProcessStatus_TerminatedNormally:
2610 fRc = reporter.error('Waiting for non-stale processes #%d resulted in status %d, expected %d (wr=%d)'
2611 % (i, eProcessStatus, vboxcon.ProcessStatus_TerminatedNormally, eWaitResult));
2612
2613 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2614 except: fRc = reporter.errorXcpt();
2615 else:
2616 # Here we count the stale processes (that is, processes we don't have a reference
2617 # anymore for) and the started + terminated non-stale processes (that we still keep
2618 # a reference in aoProcesses[] for).
2619 if cProcesses != (cStaleProcs * 2):
2620 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2621
2622 if fRc is True:
2623 reporter.log2('All non-stale processes terminated');
2624
2625 #
2626 # Fire off non-stale blocking processes which are terminated via terminate().
2627 #
2628 if oTestVm.isWindows() or oTestVm.isOS2():
2629 asArgs = [ sCmd, '/C', 'pause'];
2630 else:
2631 asArgs = [ sCmd ];
2632 reporter.log2('Starting blocking processes...');
2633 aoProcesses = [];
2634 for i in xrange(0, cStaleProcs):
2635 try:
2636 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2637 [], [], 30 * 1000);
2638 # Note: Use a timeout in the call above for not letting the stale processes
2639 # hanging around forever. This can happen if the installed Guest Additions
2640 # do not support terminating guest processes.
2641 aoProcesses.append(oCurProc);
2642 except:
2643 fRc = reporter.errorXcpt('Creating non-stale blocking process #%d failed:' % (i,));
2644 break;
2645
2646 reporter.log2('Terminating blocking processes...');
2647 for i, oProcess in enumerate(aoProcesses):
2648 try:
2649 oProcess.terminate();
2650 except: # Termination might not be supported, just skip and log it.
2651 reporter.logXcpt('Termination of blocking process #%d failed, skipped:' % (i,));
2652
2653 # There still should be 20 processes because we terminated the 10 newest ones.
2654 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2655 except: fRc = reporter.errorXcpt();
2656 else:
2657 if cProcesses != (cStaleProcs * 2):
2658 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2659 reporter.log2('Final guest session processes count: %d' % (cProcesses,));
2660
2661 #
2662 # Now try to close the session and see what happens.
2663 #
2664 reporter.log2('Closing guest session ...');
2665 try:
2666 oGuestSession.close();
2667 except:
2668 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2669
2670 return (fRc, oTxsSession);
2671
2672 def testGuestCtrlExec(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements
2673 """
2674 Tests the basic execution feature.
2675 """
2676
2677 # Paths:
2678 sVBoxControl = None; ## @todo Get path of installed Guest Additions. Later.
2679 sShell = self.getGuestSystemShell(oTestVm);
2680 sShellOpt = '/C' if oTestVm.isWindows() or oTestVm.isOS2() else '-c';
2681 sSystemDir = self.getGuestSystemDir(oTestVm);
2682 sFileForReading = self.getGuestSystemFileForReading(oTestVm);
2683 if oTestVm.isWindows() or oTestVm.isOS2():
2684 sImageOut = self.getGuestSystemShell(oTestVm);
2685 if oTestVm.isWindows():
2686 sVBoxControl = "C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\VBoxControl.exe";
2687 else:
2688 sImageOut = "/bin/ls";
2689 if oTestVm.isLinux(): ## @todo check solaris and darwin.
2690 sVBoxControl = "/usr/bin/VBoxControl"; # Symlink
2691
2692 # Use credential defaults.
2693 oCreds = tdCtxCreds();
2694 oCreds.applyDefaultsIfNotSet(oTestVm);
2695
2696 atInvalid = [
2697 # Invalid parameters.
2698 [ tdTestExec(), tdTestResultExec() ],
2699 # Non-existent / invalid image.
2700 [ tdTestExec(sCmd = "non-existent"), tdTestResultExec() ],
2701 [ tdTestExec(sCmd = "non-existent2"), tdTestResultExec() ],
2702 # Use an invalid format string.
2703 [ tdTestExec(sCmd = "%$%%%&"), tdTestResultExec() ],
2704 # More stuff.
2705 [ tdTestExec(sCmd = u"ƒ‰‹ˆ÷‹¸"), tdTestResultExec() ],
2706 [ tdTestExec(sCmd = "???://!!!"), tdTestResultExec() ],
2707 [ tdTestExec(sCmd = "<>!\\"), tdTestResultExec() ],
2708 # Enable as soon as ERROR_BAD_DEVICE is implemented.
2709 #[ tdTestExec(sCmd = "CON", tdTestResultExec() ],
2710 ];
2711
2712 atExec = [];
2713 if oTestVm.isWindows() or oTestVm.isOS2():
2714 atExec += [
2715 # Basic execution.
2716 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2717 tdTestResultExec(fRc = True) ],
2718 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sFileForReading ]),
2719 tdTestResultExec(fRc = True) ],
2720 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir + '\\nonexist.dll' ]),
2721 tdTestResultExec(fRc = True, iExitCode = 1) ],
2722 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', '/wrongparam' ]),
2723 tdTestResultExec(fRc = True, iExitCode = 1) ],
2724 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2725 tdTestResultExec(fRc = True, iExitCode = 1) ],
2726 # StdOut.
2727 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2728 tdTestResultExec(fRc = True) ],
2729 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdout-non-existing' ]),
2730 tdTestResultExec(fRc = True, iExitCode = 1) ],
2731 # StdErr.
2732 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2733 tdTestResultExec(fRc = True) ],
2734 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stderr-non-existing' ]),
2735 tdTestResultExec(fRc = True, iExitCode = 1) ],
2736 # StdOut + StdErr.
2737 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2738 tdTestResultExec(fRc = True) ],
2739 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdouterr-non-existing' ]),
2740 tdTestResultExec(fRc = True, iExitCode = 1) ],
2741 ];
2742 # atExec.extend([
2743 # FIXME: Failing tests.
2744 # Environment variables.
2745 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2746 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2747 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2748 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2749 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2750 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2751 # aEnv = [ 'TEST_FOO=BAR' ],
2752 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2753 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2754 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2755 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2756 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2757 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2758
2759 ## @todo Create some files (or get files) we know the output size of to validate output length!
2760 ## @todo Add task which gets killed at some random time while letting the guest output something.
2761 #];
2762 else:
2763 atExec += [
2764 # Basic execution.
2765 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '-R', sSystemDir ]),
2766 tdTestResultExec(fRc = True) ],
2767 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sFileForReading ]),
2768 tdTestResultExec(fRc = True) ],
2769 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '--wrong-parameter' ]),
2770 tdTestResultExec(fRc = True, iExitCode = 2) ],
2771 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/non/existent' ]),
2772 tdTestResultExec(fRc = True, iExitCode = 2) ],
2773 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2774 tdTestResultExec(fRc = True, iExitCode = 127) ],
2775 # StdOut.
2776 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2777 tdTestResultExec(fRc = True) ],
2778 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdout-non-existing' ]),
2779 tdTestResultExec(fRc = True, iExitCode = 2) ],
2780 # StdErr.
2781 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2782 tdTestResultExec(fRc = True) ],
2783 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stderr-non-existing' ]),
2784 tdTestResultExec(fRc = True, iExitCode = 2) ],
2785 # StdOut + StdErr.
2786 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2787 tdTestResultExec(fRc = True) ],
2788 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdouterr-non-existing' ]),
2789 tdTestResultExec(fRc = True, iExitCode = 2) ],
2790 ];
2791 # atExec.extend([
2792 # FIXME: Failing tests.
2793 # Environment variables.
2794 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2795 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2796 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2797 #
2798 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2799 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2800 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2801 # aEnv = [ 'TEST_FOO=BAR' ],
2802 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2803 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2804 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2805 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2806 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2807 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2808
2809 ## @todo Create some files (or get files) we know the output size of to validate output length!
2810 ## @todo Add task which gets killed at some random time while letting the guest output something.
2811 #];
2812
2813 #
2814 for iExitCode in xrange(0, 127):
2815 atExec.append([ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'exit %s' % iExitCode ]),
2816 tdTestResultExec(fRc = True, iExitCode = iExitCode) ]);
2817
2818 if sVBoxControl:
2819 # Paths with spaces on windows.
2820 atExec.append([ tdTestExec(sCmd = sVBoxControl, asArgs = [ sVBoxControl, 'version' ]),
2821 tdTestResultExec(fRc = True) ]);
2822
2823 # Build up the final test array for the first batch.
2824 atTests = atInvalid + atExec;
2825
2826 #
2827 # First batch: One session per guest process.
2828 #
2829 reporter.log('One session per guest process ...');
2830 fRc = True;
2831 for (i, tTest) in enumerate(atTests):
2832 oCurTest = tTest[0] # type: tdTestExec
2833 oCurRes = tTest[1] # type: tdTestResultExec
2834 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2835 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlExec: Test #%d' % (i,));
2836 if fRc2 is not True:
2837 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
2838 break;
2839 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession) and fRc;
2840 fRc = oCurTest.closeSession() and fRc;
2841
2842 reporter.log('Execution of all tests done, checking for stale sessions');
2843
2844 # No sessions left?
2845 try:
2846 aSessions = self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions');
2847 except:
2848 fRc = reporter.errorXcpt();
2849 else:
2850 cSessions = len(aSessions);
2851 if cSessions != 0:
2852 fRc = reporter.error('Found %d stale session(s), expected 0:' % (cSessions,));
2853 for (i, aSession) in enumerate(aSessions):
2854 try: reporter.log(' Stale session #%d ("%s")' % (aSession.id, aSession.name));
2855 except: reporter.errorXcpt();
2856
2857 if fRc is not True:
2858 return (fRc, oTxsSession);
2859
2860 reporter.log('Now using one guest session for all tests ...');
2861
2862 #
2863 # Second batch: One session for *all* guest processes.
2864 #
2865
2866 # Create session.
2867 reporter.log('Creating session for all tests ...');
2868 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
2869 try:
2870 oGuest = oSession.o.console.guest;
2871 oCurGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain,
2872 'testGuestCtrlExec: One session for all tests');
2873 except:
2874 return (reporter.errorXcpt(), oTxsSession);
2875
2876 try:
2877 eWaitResult = oCurGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2878 except:
2879 fRc = reporter.errorXcpt('Waiting for guest session to start failed:');
2880 else:
2881 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2882 fRc = reporter.error('Session did not start successfully, returned wait result: %d' % (eWaitResult,));
2883 else:
2884 reporter.log('Session successfully started');
2885
2886 # Do the tests within this session.
2887 for (i, tTest) in enumerate(atTests):
2888 oCurTest = tTest[0] # type: tdTestExec
2889 oCurRes = tTest[1] # type: tdTestResultExec
2890
2891 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2892 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
2893 if fRc is False:
2894 break;
2895
2896 # Close the session.
2897 reporter.log2('Closing guest session ...');
2898 try:
2899 oCurGuestSession.close();
2900 oCurGuestSession = None;
2901 except:
2902 fRc = reporter.errorXcpt('Closing guest session failed:');
2903
2904 # No sessions left?
2905 reporter.log('Execution of all tests done, checking for stale sessions again');
2906 try: cSessions = len(self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions'));
2907 except: fRc = reporter.errorXcpt();
2908 else:
2909 if cSessions != 0:
2910 fRc = reporter.error('Found %d stale session(s), expected 0' % (cSessions,));
2911 return (fRc, oTxsSession);
2912
2913 def threadForTestGuestCtrlSessionReboot(self, oGuestProcess):
2914 """
2915 Thread routine which waits for the stale guest process getting terminated (or some error)
2916 while the main test routine reboots the guest. It then compares the expected guest process result
2917 and logs an error if appropriate.
2918 """
2919 reporter.log('Waiting for process to get terminated at reboot ...');
2920 try:
2921 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate ], 5 * 60 * 1000);
2922 except:
2923 return reporter.errorXcpt('waitForArray failed');
2924 try:
2925 eStatus = oGuestProcess.status
2926 except:
2927 return reporter.errorXcpt('failed to get status (wait result %d)' % (eWaitResult,));
2928
2929 if eWaitResult == vboxcon.ProcessWaitResult_Terminate and eStatus == vboxcon.ProcessStatus_Down:
2930 reporter.log('Stale process was correctly terminated (status: down)');
2931 return True;
2932
2933 return reporter.error('Process wait across reboot failed: eWaitResult=%d, expected %d; eStatus=%d, expected %d'
2934 % (eWaitResult, vboxcon.ProcessWaitResult_Terminate, eStatus, vboxcon.ProcessStatus_Down,));
2935
2936 def testGuestCtrlSessionReboot(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2937 """
2938 Tests guest object notifications when a guest gets rebooted / shutdown.
2939
2940 These notifications gets sent from the guest sessions in order to make API clients
2941 aware of guest session changes.
2942
2943 To test that we create a stale guest process and trigger a reboot of the guest.
2944 """
2945
2946 ## @todo backport fixes to 6.0 and maybe 5.2
2947 if self.oTstDrv.fpApiVer <= 6.0:
2948 reporter.log('Skipping: Required fixes not yet backported!');
2949 return None;
2950
2951 # Use credential defaults.
2952 oCreds = tdCtxCreds();
2953 oCreds.applyDefaultsIfNotSet(oTestVm);
2954
2955 fRc = True;
2956
2957 #
2958 # Start a session.
2959 #
2960 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2961 try:
2962 oGuest = oSession.o.console.guest;
2963 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionReboot");
2964 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2965 except:
2966 return (reporter.errorXcpt(), oTxsSession);
2967
2968 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2969 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2970 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2971 reporter.log('Session successfully started');
2972
2973 #
2974 # Create a process.
2975 #
2976 sImage = self.getGuestSystemShell(oTestVm);
2977 asArgs = [ sImage, ];
2978 aEnv = [];
2979 afFlags = [];
2980 try:
2981 oGuestProcess = oGuestSession.processCreate(sImage,
2982 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], aEnv, afFlags,
2983 30 * 1000);
2984 except:
2985 fRc = reporter.error('Failed to start shell process (%s)' % (sImage,));
2986 else:
2987 try:
2988 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2989 except:
2990 fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
2991 else:
2992 # Check the result and state:
2993 try: eStatus = oGuestProcess.status;
2994 except: fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
2995 else:
2996 reporter.log2('Starting process wait result returned: %d; Process status is: %d' % (eWaitResult, eStatus,));
2997 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2998 fRc = reporter.error('wait for ProcessWaitForFlag_Start failed: %d, expected %d (Start)'
2999 % (eWaitResult, vboxcon.ProcessWaitResult_Start,));
3000 elif eStatus != vboxcon.ProcessStatus_Started:
3001 fRc = reporter.error('Unexpected process status after startup: %d, wanted %d (Started)'
3002 % (eStatus, vboxcon.ProcessStatus_Started,));
3003 else:
3004 # Create a thread that waits on the process to terminate
3005 reporter.log('Creating reboot thread ...');
3006 oThreadReboot = threading.Thread(target = self.threadForTestGuestCtrlSessionReboot,
3007 args = (oGuestProcess,),
3008 name = ('threadForTestGuestCtrlSessionReboot'));
3009 oThreadReboot.setDaemon(True);
3010 oThreadReboot.start();
3011
3012 # Not sure why this fudge is needed...
3013 reporter.log('5 second wait fudge before triggering reboot ...');
3014 self.oTstDrv.sleep(5);
3015
3016 # Do the reboot.
3017 reporter.log('Rebooting guest and reconnecting TXS ...');
3018 (oSession, oTxsSession) = self.oTstDrv.txsRebootAndReconnectViaTcp(oSession, oTxsSession,
3019 cMsTimeout = 3 * 60000);
3020 if not oSession or not oTxsSession:
3021 try: oGuestProcess.terminate();
3022 except: reporter.logXcpt();
3023 fRc = False;
3024
3025 reporter.log('Waiting for thread to finish ...');
3026 oThreadReboot.join();
3027
3028 #
3029 # Try make sure we don't leave with a stale process on failure.
3030 #
3031 try: oGuestProcess.terminate();
3032 except: reporter.logXcpt();
3033
3034 #
3035 # Close the session.
3036 #
3037 reporter.log2('Closing guest session ...');
3038 try:
3039 oGuestSession.close();
3040 except:
3041 fRc = reporter.errorXcpt();
3042
3043 return (fRc, oTxsSession);
3044
3045 def testGuestCtrlExecTimeout(self, oSession, oTxsSession, oTestVm):
3046 """
3047 Tests handling of timeouts of started guest processes.
3048 """
3049
3050 sShell = self.getGuestSystemShell(oTestVm);
3051
3052 # Use credential defaults.
3053 oCreds = tdCtxCreds();
3054 oCreds.applyDefaultsIfNotSet(oTestVm);
3055
3056 #
3057 # Create a session.
3058 #
3059 try:
3060 oGuest = oSession.o.console.guest;
3061 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlExecTimeout");
3062 eWaitResult = oGuestSession.waitForArray([ vboxcon.GuestSessionWaitForFlag_Start, ], 30 * 1000);
3063 except:
3064 return (reporter.errorXcpt(), oTxsSession);
3065
3066 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
3067 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3068 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
3069 reporter.log('Session successfully started');
3070
3071 #
3072 # Create a process which never terminates and should timeout when
3073 # waiting for termination.
3074 #
3075 fRc = True;
3076 try:
3077 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
3078 [], [], 30 * 1000);
3079 except:
3080 fRc = reporter.errorXcpt();
3081 else:
3082 reporter.log('Waiting for process 1 being started ...');
3083 try:
3084 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3085 except:
3086 fRc = reporter.errorXcpt();
3087 else:
3088 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3089 fRc = reporter.error('Waiting for process 1 to start failed, got status %d' % (eWaitResult,));
3090 else:
3091 for msWait in (1, 32, 2000,):
3092 reporter.log('Waiting for process 1 to time out within %sms ...' % (msWait,));
3093 try:
3094 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], msWait);
3095 except:
3096 fRc = reporter.errorXcpt();
3097 break;
3098 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
3099 fRc = reporter.error('Waiting for process 1 did not time out in %sms as expected: %d'
3100 % (msWait, eWaitResult,));
3101 break;
3102 reporter.log('Waiting for process 1 timed out in %u ms, good' % (msWait,));
3103
3104 try:
3105 oCurProcess.terminate();
3106 except:
3107 reporter.errorXcpt();
3108 oCurProcess = None;
3109
3110 #
3111 # Create another process that doesn't terminate, but which will be killed by VBoxService
3112 # because it ran out of execution time (3 seconds).
3113 #
3114 try:
3115 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
3116 [], [], 3 * 1000);
3117 except:
3118 fRc = reporter.errorXcpt();
3119 else:
3120 reporter.log('Waiting for process 2 being started ...');
3121 try:
3122 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3123 except:
3124 fRc = reporter.errorXcpt();
3125 else:
3126 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3127 fRc = reporter.error('Waiting for process 2 to start failed, got status %d' % (eWaitResult,));
3128 else:
3129 reporter.log('Waiting for process 2 to get killed for running out of execution time ...');
3130 try:
3131 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 15 * 1000);
3132 except:
3133 fRc = reporter.errorXcpt();
3134 else:
3135 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
3136 fRc = reporter.error('Waiting for process 2 did not time out when it should, got wait result %d'
3137 % (eWaitResult,));
3138 else:
3139 reporter.log('Waiting for process 2 did not time out, good: %s' % (eWaitResult,));
3140 try:
3141 eStatus = oCurProcess.status;
3142 except:
3143 fRc = reporter.errorXcpt();
3144 else:
3145 if eStatus != vboxcon.ProcessStatus_TimedOutKilled:
3146 fRc = reporter.error('Status of process 2 wrong; excepted %d, got %d'
3147 % (vboxcon.ProcessStatus_TimedOutKilled, eStatus));
3148 else:
3149 reporter.log('Status of process 2 is TimedOutKilled (%d) is it should be.'
3150 % (vboxcon.ProcessStatus_TimedOutKilled,));
3151 try:
3152 oCurProcess.terminate();
3153 except:
3154 reporter.logXcpt();
3155 oCurProcess = None;
3156
3157 #
3158 # Clean up the session.
3159 #
3160 try:
3161 oGuestSession.close();
3162 except:
3163 fRc = reporter.errorXcpt();
3164
3165 return (fRc, oTxsSession);
3166
3167 def testGuestCtrlDirCreate(self, oSession, oTxsSession, oTestVm):
3168 """
3169 Tests creation of guest directories.
3170 """
3171
3172 sScratch = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'testGuestCtrlDirCreate');
3173
3174 atTests = [
3175 # Invalid stuff.
3176 [ tdTestDirCreate(sDirectory = '' ), tdTestResultFailure() ],
3177 # More unusual stuff.
3178 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '.') ), tdTestResultFailure() ],
3179 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '..') ), tdTestResultFailure() ],
3180 [ tdTestDirCreate(sDirectory = '..' ), tdTestResultFailure() ],
3181 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
3182 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
3183 [ tdTestDirCreate(sDirectory = '/' ), tdTestResultFailure() ],
3184 [ tdTestDirCreate(sDirectory = '/..' ), tdTestResultFailure() ],
3185 [ tdTestDirCreate(sDirectory = '/../' ), tdTestResultFailure() ],
3186 ];
3187 if oTestVm.isWindows() or oTestVm.isOS2():
3188 atTests.extend([
3189 [ tdTestDirCreate(sDirectory = 'C:\\' ), tdTestResultFailure() ],
3190 [ tdTestDirCreate(sDirectory = 'C:\\..' ), tdTestResultFailure() ],
3191 [ tdTestDirCreate(sDirectory = 'C:\\..\\' ), tdTestResultFailure() ],
3192 [ tdTestDirCreate(sDirectory = 'C:/' ), tdTestResultFailure() ],
3193 [ tdTestDirCreate(sDirectory = 'C:/.' ), tdTestResultFailure() ],
3194 [ tdTestDirCreate(sDirectory = 'C:/./' ), tdTestResultFailure() ],
3195 [ tdTestDirCreate(sDirectory = 'C:/..' ), tdTestResultFailure() ],
3196 [ tdTestDirCreate(sDirectory = 'C:/../' ), tdTestResultFailure() ],
3197 [ tdTestDirCreate(sDirectory = '\\\\uncrulez\\foo' ), tdTestResultFailure() ],
3198 ]);
3199 atTests.extend([
3200 # Existing directories and files.
3201 [ tdTestDirCreate(sDirectory = self.getGuestSystemDir(oTestVm) ), tdTestResultFailure() ],
3202 [ tdTestDirCreate(sDirectory = self.getGuestSystemShell(oTestVm) ), tdTestResultFailure() ],
3203 [ tdTestDirCreate(sDirectory = self.getGuestSystemFileForReading(oTestVm) ), tdTestResultFailure() ],
3204 # Creating directories.
3205 [ tdTestDirCreate(sDirectory = sScratch ), tdTestResultSuccess() ],
3206 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
3207 afFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
3208 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
3209 afFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
3210 # Long random names.
3211 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(36, 28))),
3212 tdTestResultSuccess() ],
3213 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(140, 116))),
3214 tdTestResultSuccess() ],
3215 # Too long names. ASSUMES a guests has a 255 filename length limitation.
3216 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
3217 tdTestResultFailure() ],
3218 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
3219 tdTestResultFailure() ],
3220 # Missing directory in path.
3221 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo1', 'bar') ), tdTestResultFailure() ],
3222 ]);
3223
3224 fRc = True;
3225 for (i, tTest) in enumerate(atTests):
3226 oCurTest = tTest[0] # type: tdTestDirCreate
3227 oCurRes = tTest[1] # type: tdTestResult
3228 reporter.log('Testing #%d, sDirectory="%s" ...' % (i, oCurTest.sDirectory));
3229
3230 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3231 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreate: Test #%d' % (i,));
3232 if fRc is False:
3233 return reporter.error('Test #%d failed: Could not create session' % (i,));
3234
3235 fRc = self.gctrlCreateDir(oCurTest, oCurRes, oCurGuestSession);
3236
3237 fRc = oCurTest.closeSession() and fRc;
3238 if fRc is False:
3239 fRc = reporter.error('Test #%d failed' % (i,));
3240
3241 return (fRc, oTxsSession);
3242
3243 def testGuestCtrlDirCreateTemp(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3244 """
3245 Tests creation of temporary directories.
3246 """
3247
3248 sSystemDir = self.getGuestSystemDir(oTestVm);
3249 atTests = [
3250 # Invalid stuff (template must have one or more trailin 'X'es (upper case only), or a cluster of three or more).
3251 [ tdTestDirCreateTemp(sDirectory = ''), tdTestResultFailure() ],
3252 [ tdTestDirCreateTemp(sDirectory = sSystemDir, fMode = 1234), tdTestResultFailure() ],
3253 [ tdTestDirCreateTemp(sTemplate = 'xXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3254 [ tdTestDirCreateTemp(sTemplate = 'xxx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3255 [ tdTestDirCreateTemp(sTemplate = 'XXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3256 [ tdTestDirCreateTemp(sTemplate = 'bar', sDirectory = 'whatever', fMode = 0o700), tdTestResultFailure() ],
3257 [ tdTestDirCreateTemp(sTemplate = 'foo', sDirectory = 'it is not used', fMode = 0o700), tdTestResultFailure() ],
3258 [ tdTestDirCreateTemp(sTemplate = 'X,so', sDirectory = 'pointless test', fMode = 0o700), tdTestResultFailure() ],
3259 # Non-existing stuff.
3260 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX',
3261 sDirectory = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'non', 'existing')),
3262 tdTestResultFailure() ],
3263 # Working stuff:
3264 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3265 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3266 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3267 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3268 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3269 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3270 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3271 ## @todo test fSecure and pass weird fMode values once these parameters are implemented in the API.
3272 ];
3273
3274 fRc = True;
3275 for (i, tTest) in enumerate(atTests):
3276 oCurTest = tTest[0] # type: tdTestDirCreateTemp
3277 oCurRes = tTest[1] # type: tdTestResult
3278 reporter.log('Testing #%d, sTemplate="%s", fMode=%#o, path="%s", secure="%s" ...' %
3279 (i, oCurTest.sTemplate, oCurTest.fMode, oCurTest.sDirectory, oCurTest.fSecure));
3280
3281 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3282 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreateTemp: Test #%d' % (i,));
3283 if fRc is False:
3284 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3285 break;
3286
3287 sDirTemp = '';
3288 try:
3289 sDirTemp = oCurGuestSession.directoryCreateTemp(oCurTest.sTemplate, oCurTest.fMode,
3290 oCurTest.sDirectory, oCurTest.fSecure);
3291 except:
3292 if oCurRes.fRc is True:
3293 fRc = reporter.errorXcpt('Creating temp directory "%s" failed:' % (oCurTest.sDirectory,));
3294 else:
3295 reporter.logXcpt('Creating temp directory "%s" failed expectedly, skipping:' % (oCurTest.sDirectory,));
3296 else:
3297 reporter.log2('Temporary directory is: "%s"' % (sDirTemp,));
3298 if not sDirTemp:
3299 fRc = reporter.error('Resulting directory is empty!');
3300 else:
3301 ## @todo This does not work for some unknown reason.
3302 #try:
3303 # if self.oTstDrv.fpApiVer >= 5.0:
3304 # fExists = oCurGuestSession.directoryExists(sDirTemp, False);
3305 # else:
3306 # fExists = oCurGuestSession.directoryExists(sDirTemp);
3307 #except:
3308 # fRc = reporter.errorXcpt('sDirTemp=%s' % (sDirTemp,));
3309 #else:
3310 # if fExists is not True:
3311 # fRc = reporter.error('Test #%d failed: Temporary directory "%s" does not exists (%s)'
3312 # % (i, sDirTemp, fExists));
3313 try:
3314 oFsObjInfo = oCurGuestSession.fsObjQueryInfo(sDirTemp, False);
3315 eType = oFsObjInfo.type;
3316 except:
3317 fRc = reporter.errorXcpt('sDirTemp="%s"' % (sDirTemp,));
3318 else:
3319 reporter.log2('%s: eType=%s (dir=%d)' % (sDirTemp, eType, vboxcon.FsObjType_Directory,));
3320 if eType != vboxcon.FsObjType_Directory:
3321 fRc = reporter.error('Temporary directory "%s" not created as a directory: eType=%d'
3322 % (sDirTemp, eType));
3323 fRc = oCurTest.closeSession() and fRc;
3324 return (fRc, oTxsSession);
3325
3326 def testGuestCtrlDirRead(self, oSession, oTxsSession, oTestVm):
3327 """
3328 Tests opening and reading (enumerating) guest directories.
3329 """
3330
3331 sSystemDir = self.getGuestSystemDir(oTestVm);
3332 atTests = [
3333 # Invalid stuff.
3334 [ tdTestDirRead(sDirectory = ''), tdTestResultDirRead() ],
3335 [ tdTestDirRead(sDirectory = sSystemDir, afFlags = [ 1234 ]), tdTestResultDirRead() ],
3336 [ tdTestDirRead(sDirectory = sSystemDir, sFilter = '*.foo'), tdTestResultDirRead() ],
3337 # Non-existing stuff.
3338 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'really-no-such-subdir')), tdTestResultDirRead() ],
3339 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'non', 'existing')), tdTestResultDirRead() ],
3340 ];
3341
3342 if oTestVm.isWindows() or oTestVm.isOS2():
3343 atTests.extend([
3344 # More unusual stuff.
3345 [ tdTestDirRead(sDirectory = 'z:\\'), tdTestResultDirRead() ],
3346 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
3347 ]);
3348
3349 # Read the system directory (ASSUMES at least 5 files in it):
3350 # Windows 7+ has inaccessible system32/com/dmp directory that screws up this test, so skip it on windows:
3351 if not oTestVm.isWindows():
3352 atTests.append([ tdTestDirRead(sDirectory = sSystemDir),
3353 tdTestResultDirRead(fRc = True, cFiles = -5, cDirs = None) ]);
3354 ## @todo trailing slash
3355
3356 # Read from the test file set.
3357 atTests.extend([
3358 [ tdTestDirRead(sDirectory = self.oTestFiles.oEmptyDir.sPath),
3359 tdTestResultDirRead(fRc = True, cFiles = 0, cDirs = 0, cOthers = 0) ],
3360 [ tdTestDirRead(sDirectory = self.oTestFiles.oManyDir.sPath),
3361 tdTestResultDirRead(fRc = True, cFiles = len(self.oTestFiles.oManyDir.aoChildren), cDirs = 0, cOthers = 0) ],
3362 [ tdTestDirRead(sDirectory = self.oTestFiles.oTreeDir.sPath),
3363 tdTestResultDirRead(fRc = True, cFiles = self.oTestFiles.cTreeFiles, cDirs = self.oTestFiles.cTreeDirs,
3364 cOthers = self.oTestFiles.cTreeOthers) ],
3365 ]);
3366
3367
3368 fRc = True;
3369 for (i, tTest) in enumerate(atTests):
3370 oCurTest = tTest[0] # type: tdTestExec
3371 oCurRes = tTest[1] # type: tdTestResultDirRead
3372
3373 reporter.log('Testing #%d, dir="%s" ...' % (i, oCurTest.sDirectory));
3374 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3375 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: Test #%d' % (i,));
3376 if fRc is not True:
3377 break;
3378 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc);
3379 fRc = oCurTest.closeSession() and fRc;
3380
3381 reporter.log2('Test #%d: Returned %d directories, %d files total' % (i, cDirs, cFiles));
3382 if fRc2 is oCurRes.fRc:
3383 if fRc2 is True:
3384 if oCurRes.cFiles is None:
3385 pass; # ignore
3386 elif oCurRes.cFiles >= 0 and cFiles != oCurRes.cFiles:
3387 fRc = reporter.error('Test #%d failed: Got %d files, expected %d' % (i, cFiles, oCurRes.cFiles));
3388 elif oCurRes.cFiles < 0 and cFiles < -oCurRes.cFiles:
3389 fRc = reporter.error('Test #%d failed: Got %d files, expected at least %d'
3390 % (i, cFiles, -oCurRes.cFiles));
3391 if oCurRes.cDirs is None:
3392 pass; # ignore
3393 elif oCurRes.cDirs >= 0 and cDirs != oCurRes.cDirs:
3394 fRc = reporter.error('Test #%d failed: Got %d directories, expected %d' % (i, cDirs, oCurRes.cDirs));
3395 elif oCurRes.cDirs < 0 and cDirs < -oCurRes.cDirs:
3396 fRc = reporter.error('Test #%d failed: Got %d directories, expected at least %d'
3397 % (i, cDirs, -oCurRes.cDirs));
3398 if oCurRes.cOthers is None:
3399 pass; # ignore
3400 elif oCurRes.cOthers >= 0 and cOthers != oCurRes.cOthers:
3401 fRc = reporter.error('Test #%d failed: Got %d other types, expected %d' % (i, cOthers, oCurRes.cOthers));
3402 elif oCurRes.cOthers < 0 and cOthers < -oCurRes.cOthers:
3403 fRc = reporter.error('Test #%d failed: Got %d other types, expected at least %d'
3404 % (i, cOthers, -oCurRes.cOthers));
3405
3406 else:
3407 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3408
3409
3410 #
3411 # Go over a few directories in the test file set and compare names,
3412 # types and sizes rather than just the counts like we did above.
3413 #
3414 if fRc is True:
3415 oCurTest = tdTestDirRead();
3416 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3417 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: gctrlReadDirTree2');
3418 if fRc is True:
3419 for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir):
3420 reporter.log('Checking "%s" ...' % (oDir.sPath,));
3421 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir) and fRc;
3422 fRc = oCurTest.closeSession() and fRc;
3423
3424 return (fRc, oTxsSession);
3425
3426
3427 def testGuestCtrlFileRemove(self, oSession, oTxsSession, oTestVm):
3428 """
3429 Tests removing guest files.
3430 """
3431
3432 #
3433 # Create a directory with a few files in it using TXS that we'll use for the initial tests.
3434 #
3435 asTestDirs = [
3436 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1'), # [0]
3437 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1', 'subdir-1'), # [1]
3438 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1', 'subdir-1', 'subsubdir-1'), # [2]
3439 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2'), # [3]
3440 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2', 'subdir-2'), # [4]
3441 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2', 'subdir-2', 'subsbudir-2'), # [5]
3442 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-3'), # [6]
3443 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-4'), # [7]
3444 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-5'), # [8]
3445 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-5', 'subdir-5'), # [9]
3446 ]
3447 asTestFiles = [
3448 oTestVm.pathJoin(asTestDirs[0], 'file-0'), # [0]
3449 oTestVm.pathJoin(asTestDirs[0], 'file-1'), # [1]
3450 oTestVm.pathJoin(asTestDirs[0], 'file-2'), # [2]
3451 oTestVm.pathJoin(asTestDirs[1], 'file-3'), # [3] - subdir-1
3452 oTestVm.pathJoin(asTestDirs[1], 'file-4'), # [4] - subdir-1
3453 oTestVm.pathJoin(asTestDirs[2], 'file-5'), # [5] - subsubdir-1
3454 oTestVm.pathJoin(asTestDirs[3], 'file-6'), # [6] - rmtestdir-2
3455 oTestVm.pathJoin(asTestDirs[4], 'file-7'), # [7] - subdir-2
3456 oTestVm.pathJoin(asTestDirs[5], 'file-8'), # [8] - subsubdir-2
3457 ];
3458 for sDir in asTestDirs:
3459 if oTxsSession.syncMkDir(sDir, 0o777) is not True:
3460 return reporter.error('Failed to create test dir "%s"!' % (sDir,));
3461 for sFile in asTestFiles:
3462 if oTxsSession.syncUploadString(sFile, sFile, 0o666) is not True:
3463 return reporter.error('Failed to create test file "%s"!' % (sFile,));
3464
3465 #
3466 # Tear down the directories and files.
3467 #
3468 aoTests = [
3469 # Negative tests first:
3470 tdTestRemoveFile(asTestDirs[0], fRcExpect = False),
3471 tdTestRemoveDir(asTestDirs[0], fRcExpect = False),
3472 tdTestRemoveDir(asTestFiles[0], fRcExpect = False),
3473 tdTestRemoveFile(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-file'), fRcExpect = False),
3474 tdTestRemoveDir(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir'), fRcExpect = False),
3475 tdTestRemoveFile(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir', 'no-file'), fRcExpect = False),
3476 tdTestRemoveDir(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir', 'no-subdir'), fRcExpect = False),
3477 tdTestRemoveTree(asTestDirs[0], afFlags = [], fRcExpect = False), # Only removes empty dirs, this isn't empty.
3478 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_None,], fRcExpect = False), # ditto
3479 # Empty paths:
3480 tdTestRemoveFile('', fRcExpect = False),
3481 tdTestRemoveDir('', fRcExpect = False),
3482 tdTestRemoveTree('', fRcExpect = False),
3483 # Now actually remove stuff:
3484 tdTestRemoveDir(asTestDirs[7], fRcExpect = True),
3485 tdTestRemoveFile(asTestDirs[6], fRcExpect = False),
3486 tdTestRemoveDir(asTestDirs[6], fRcExpect = True),
3487 tdTestRemoveFile(asTestFiles[0], fRcExpect = True),
3488 tdTestRemoveFile(asTestFiles[0], fRcExpect = False),
3489 # 17:
3490 tdTestRemoveTree(asTestDirs[8], fRcExpect = True), # Removes empty subdirs and leaves the dir itself.
3491 tdTestRemoveDir(asTestDirs[8], fRcExpect = True),
3492 tdTestRemoveTree(asTestDirs[3], fRcExpect = False), # Have subdirs & files,
3493 tdTestRemoveTree(asTestDirs[3], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,], fRcExpect = True),
3494 tdTestRemoveDir(asTestDirs[3], fRcExpect = True),
3495 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,], fRcExpect = True),
3496 # No error if already delete (RTDirRemoveRecursive artifact).
3497 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,], fRcExpect = True),
3498 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,],
3499 fNotExist = True, fRcExpect = True),
3500 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_None,], fNotExist = True, fRcExpect = True),
3501 ];
3502
3503 #
3504 # Execution loop
3505 #
3506 fRc = True;
3507 for (i, oTest) in enumerate(aoTests): # int, tdTestRemoveBase
3508 reporter.log('Testing #%d, path="%s" %s ...' % (i, oTest.sPath, oTest.__class__.__name__));
3509 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
3510 fRc, _ = oTest.createSession('testGuestCtrlFileRemove: Test #%d' % (i,));
3511 if fRc is False:
3512 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3513 break;
3514 fRc = oTest.execute(self) and fRc;
3515 fRc = oTest.closeSession() and fRc;
3516
3517 if fRc is True:
3518 oCurTest = tdTestDirRead();
3519 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3520 fRc, oCurGuestSession = oCurTest.createSession('remove final');
3521 if fRc is True:
3522
3523 #
3524 # Delete all the files in the many subdir of the test set.
3525 #
3526 reporter.log('Deleting the file in "%s" ...' % (self.oTestFiles.oManyDir.sPath,));
3527 for oFile in self.oTestFiles.oManyDir.aoChildren:
3528 reporter.log2('"%s"' % (oFile.sPath,));
3529 try:
3530 if self.oTstDrv.fpApiVer >= 5.0:
3531 oCurGuestSession.fsObjRemove(oFile.sPath);
3532 else:
3533 oCurGuestSession.fileRemove(oFile.sPath);
3534 except:
3535 fRc = reporter.errorXcpt('Removing "%s" failed' % (oFile.sPath,));
3536
3537 # Remove the directory itself to verify that we've removed all the files in it:
3538 reporter.log('Removing the directory "%s" ...' % (self.oTestFiles.oManyDir.sPath,));
3539 try:
3540 oCurGuestSession.directoryRemove(self.oTestFiles.oManyDir.sPath);
3541 except:
3542 fRc = reporter.errorXcpt('Removing directory "%s" failed' % (self.oTestFiles.oManyDir.sPath,));
3543
3544 #
3545 # Recursively delete the entire test file tree from the root up.
3546 #
3547 # Note! On unix we cannot delete the root dir itself since it is residing
3548 # in /var/tmp where only the owner may delete it. Root is the owner.
3549 #
3550 if oTestVm.isWindows() or oTestVm.isOS2():
3551 afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,];
3552 else:
3553 afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,];
3554 try:
3555 oProgress = oCurGuestSession.directoryRemoveRecursive(self.oTestFiles.oRoot.sPath, afFlags);
3556 except:
3557 fRc = reporter.errorXcpt('Removing tree "%s" failed' % (self.oTestFiles.oRoot.sPath,));
3558 else:
3559 oWrappedProgress = vboxwrappers.ProgressWrapper(oProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv,
3560 "remove-tree-root: %s" % (self.oTestFiles.oRoot.sPath,));
3561 reporter.log2('waiting ...')
3562 oWrappedProgress.wait();
3563 reporter.log2('isSuccess=%s' % (oWrappedProgress.isSuccess(),));
3564 if not oWrappedProgress.isSuccess():
3565 fRc = oWrappedProgress.logResult();
3566
3567 fRc = oCurTest.closeSession() and fRc;
3568
3569 return (fRc, oTxsSession);
3570
3571
3572 def testGuestCtrlFileStat(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3573 """
3574 Tests querying file information through stat.
3575 """
3576
3577 # Basic stuff, existing stuff.
3578 aoTests = [
3579 tdTestSessionEx([
3580 tdStepStatDir('.'),
3581 tdStepStatDir('..'),
3582 tdStepStatDir(self.getGuestTempDir(oTestVm)),
3583 tdStepStatDir(self.getGuestSystemDir(oTestVm)),
3584 tdStepStatDirEx(self.oTestFiles.oRoot),
3585 tdStepStatDirEx(self.oTestFiles.oEmptyDir),
3586 tdStepStatDirEx(self.oTestFiles.oTreeDir),
3587 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3588 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3589 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3590 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3591 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3592 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
3593 tdStepStatFile(self.getGuestSystemFileForReading(oTestVm)),
3594 tdStepStatFile(self.getGuestSystemShell(oTestVm)),
3595 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3596 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3597 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3598 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3599 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3600 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
3601 ]),
3602 ];
3603
3604 # None existing stuff.
3605 sSysDir = self.getGuestSystemDir(oTestVm);
3606 sSep = oTestVm.pathSep();
3607 aoTests += [
3608 tdTestSessionEx([
3609 tdStepStatFileNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory')),
3610 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory') + sSep),
3611 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', '.')),
3612 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory')),
3613 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory') + sSep),
3614 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory', '.')),
3615 #tdStepStatPathNotFound('N:\\'), # ASSUMES nothing mounted on N:!
3616 #tdStepStatPathNotFound('\\\\NoSuchUncServerName\\NoSuchShare'),
3617 ]),
3618 ];
3619 # Invalid parameter check.
3620 aoTests += [ tdTestSessionEx([ tdStepStat('', vbox.ComError.E_INVALIDARG), ]), ];
3621
3622 #
3623 # Execute the tests.
3624 #
3625 fRc, oTxsSession = tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession,
3626 oTestVm, 'FsStat');
3627 #
3628 # Test the full test file set.
3629 #
3630 if self.oTstDrv.fpApiVer < 5.0:
3631 return (fRc, oTxsSession);
3632
3633 oTest = tdTestGuestCtrlBase();
3634 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
3635 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet');
3636 if fRc2 is not True:
3637 return (False, oTxsSession);
3638
3639 for sPath in self.oTestFiles.dPaths:
3640 oFsObj = self.oTestFiles.dPaths[sPath];
3641 reporter.log2('testGuestCtrlFileStat: %s sPath=%s'
3642 % ('file' if isinstance(oFsObj, testfileset.TestFile) else 'dir ', oFsObj.sPath,));
3643
3644 # Query the information:
3645 try:
3646 oFsInfo = oGuestSession.fsObjQueryInfo(oFsObj.sPath, False);
3647 except:
3648 fRc = reporter.errorXcpt('sPath=%s type=%s: fsObjQueryInfo trouble!' % (oFsObj.sPath, type(oFsObj),));
3649 continue;
3650 if oFsInfo is None:
3651 fRc = reporter.error('sPath=%s type=%s: No info object returned!' % (oFsObj.sPath, type(oFsObj),));
3652 continue;
3653
3654 # Check attributes:
3655 try:
3656 eType = oFsInfo.type;
3657 cbObject = oFsInfo.objectSize;
3658 except:
3659 fRc = reporter.errorXcpt('sPath=%s type=%s: attribute access trouble!' % (oFsObj.sPath, type(oFsObj),));
3660 continue;
3661
3662 if isinstance(oFsObj, testfileset.TestFile):
3663 if eType != vboxcon.FsObjType_File:
3664 fRc = reporter.error('sPath=%s type=file: eType=%s, expected %s!'
3665 % (oFsObj.sPath, eType, vboxcon.FsObjType_File));
3666 if cbObject != oFsObj.cbContent:
3667 fRc = reporter.error('sPath=%s type=file: cbObject=%s, expected %s!'
3668 % (oFsObj.sPath, cbObject, oFsObj.cbContent));
3669 fFileExists = True;
3670 fDirExists = False;
3671 elif isinstance(oFsObj, testfileset.TestDir):
3672 if eType != vboxcon.FsObjType_Directory:
3673 fRc = reporter.error('sPath=%s type=dir: eType=%s, expected %s!'
3674 % (oFsObj.sPath, eType, vboxcon.FsObjType_Directory));
3675 fFileExists = False;
3676 fDirExists = True;
3677 else:
3678 fRc = reporter.error('sPath=%s type=%s: Unexpected oFsObj type!' % (oFsObj.sPath, type(oFsObj),));
3679 continue;
3680
3681 # Check the directoryExists and fileExists results too.
3682 try:
3683 fExistsResult = oGuestSession.fileExists(oFsObj.sPath, False);
3684 except:
3685 fRc = reporter.errorXcpt('sPath=%s type=%s: fileExists trouble!' % (oFsObj.sPath, type(oFsObj),));
3686 else:
3687 if fExistsResult != fFileExists:
3688 fRc = reporter.error('sPath=%s type=%s: fileExists returned %s, expected %s!'
3689 % (oFsObj.sPath, type(oFsObj), fExistsResult, fFileExists));
3690
3691 if not self.fSkipKnownBugs: ## @todo At least two different failures here.
3692 try:
3693 fExistsResult = oGuestSession.directoryExists(oFsObj.sPath, False);
3694 except:
3695 fRc = reporter.errorXcpt('sPath=%s type=%s: directoryExists trouble!' % (oFsObj.sPath, type(oFsObj),));
3696 else:
3697 if fExistsResult != fDirExists:
3698 fRc = reporter.error('sPath=%s type=%s: directoryExists returned %s, expected %s!'
3699 % (oFsObj.sPath, type(oFsObj), fExistsResult, fDirExists));
3700
3701 fRc = oTest.closeSession() and fRc;
3702 return (fRc, oTxsSession);
3703
3704 def testGuestCtrlFileOpen(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3705 """
3706 Tests opening guest files.
3707 """
3708 if self.oTstDrv.fpApiVer < 5.0:
3709 reporter.log('Skipping because of pre 5.0 API');
3710 return None;
3711
3712 #
3713 # Paths.
3714 #
3715 sTempDir = self.getGuestTempDir(oTestVm);
3716 sFileForReading = self.getGuestSystemFileForReading(oTestVm);
3717 asFiles = [
3718 oTestVm.pathJoin(sTempDir, 'file-open-0'),
3719 oTestVm.pathJoin(sTempDir, 'file-open-1'),
3720 oTestVm.pathJoin(sTempDir, 'file-open-2'),
3721 oTestVm.pathJoin(sTempDir, 'file-open-3'),
3722 oTestVm.pathJoin(sTempDir, 'file-open-4'),
3723 ];
3724 asNonEmptyFiles = [
3725 oTestVm.pathJoin(sTempDir, 'file-open-10'),
3726 oTestVm.pathJoin(sTempDir, 'file-open-11'),
3727 oTestVm.pathJoin(sTempDir, 'file-open-12'),
3728 oTestVm.pathJoin(sTempDir, 'file-open-13'),
3729 ];
3730 sContent = 'abcdefghijklmnopqrstuvwxyz0123456789';
3731 for sFile in asNonEmptyFiles:
3732 if oTxsSession.syncUploadString(sContent, sFile, 0o666) is not True:
3733 return reporter.error('Failed to create "%s" via TXS' % (sFile,));
3734
3735 #
3736 # The tests.
3737 #
3738 atTests = [
3739 # Invalid stuff.
3740 [ tdTestFileOpen(sFile = ''), tdTestResultFailure() ],
3741 # Wrong open mode.
3742 [ tdTestFileOpen(sFile = sFileForReading, eAccessMode = -1), tdTestResultFailure() ],
3743 # Wrong disposition.
3744 [ tdTestFileOpen(sFile = sFileForReading, eAction = -1), tdTestResultFailure() ],
3745 # Non-existing file or path.
3746 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir')), tdTestResultFailure() ],
3747 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
3748 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
3749 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
3750 eAccessMode = vboxcon.FileAccessMode_WriteOnly,
3751 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
3752 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
3753 eAccessMode = vboxcon.FileAccessMode_ReadWrite,
3754 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
3755 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-dir', 'no-such-file')), tdTestResultFailure() ],
3756 ];
3757 if oTestVm.isWindows() or not self.fSkipKnownBugs: # We can open directories on linux, but we shouldn't, right...
3758 atTests.extend([
3759 # Wrong type:
3760 [ tdTestFileOpen(sFile = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3761 [ tdTestFileOpen(sFile = self.getGuestSystemDir(oTestVm)), tdTestResultFailure() ],
3762 ]);
3763 atTests.extend([
3764 # O_EXCL and such:
3765 [ tdTestFileOpen(sFile = sFileForReading, eAction = vboxcon.FileOpenAction_CreateNew,
3766 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultFailure() ],
3767 [ tdTestFileOpen(sFile = sFileForReading, eAction = vboxcon.FileOpenAction_CreateNew), tdTestResultFailure() ],
3768 # Open a file.
3769 [ tdTestFileOpen(sFile = sFileForReading), tdTestResultSuccess() ],
3770 [ tdTestFileOpen(sFile = sFileForReading,
3771 eAction = vboxcon.FileOpenAction_OpenOrCreate), tdTestResultSuccess() ],
3772 # Create a new file.
3773 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateNew,
3774 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3775 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateNew,
3776 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultFailure() ],
3777 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenExisting,
3778 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3779 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateOrReplace,
3780 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3781 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenOrCreate,
3782 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3783 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenExistingTruncated,
3784 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3785 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_AppendOrCreate,
3786 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3787 # Open or create a new file.
3788 [ tdTestFileOpenCheckSize(sFile = asFiles[1], eAction = vboxcon.FileOpenAction_OpenOrCreate,
3789 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3790 # Create or replace a new file.
3791 [ tdTestFileOpenCheckSize(sFile = asFiles[2], eAction = vboxcon.FileOpenAction_CreateOrReplace,
3792 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3793 # Create and append to file (weird stuff).
3794 [ tdTestFileOpenCheckSize(sFile = asFiles[3], eAction = vboxcon.FileOpenAction_AppendOrCreate,
3795 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3796 [ tdTestFileOpenCheckSize(sFile = asFiles[4], eAction = vboxcon.FileOpenAction_AppendOrCreate,
3797 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3798 # Open the non-empty files in non-destructive modes.
3799 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent)), tdTestResultSuccess() ],
3800 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
3801 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3802 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
3803 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3804
3805 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent),
3806 eAction = vboxcon.FileOpenAction_OpenOrCreate,
3807 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3808 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
3809 eAction = vboxcon.FileOpenAction_OpenOrCreate,
3810 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3811 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
3812 eAction = vboxcon.FileOpenAction_OpenOrCreate,
3813 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3814
3815 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent),
3816 eAction = vboxcon.FileOpenAction_AppendOrCreate,
3817 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
3818 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
3819 eAction = vboxcon.FileOpenAction_AppendOrCreate,
3820 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3821 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
3822 eAction = vboxcon.FileOpenAction_AppendOrCreate,
3823 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3824
3825 # Now the destructive stuff:
3826 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], eAccessMode = vboxcon.FileAccessMode_WriteOnly,
3827 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultSuccess() ],
3828 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], eAccessMode = vboxcon.FileAccessMode_WriteOnly,
3829 eAction = vboxcon.FileOpenAction_CreateOrReplace), tdTestResultSuccess() ],
3830 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], eAction = vboxcon.FileOpenAction_CreateOrReplace,
3831 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
3832 ]);
3833
3834 #
3835 # Do the testing.
3836 #
3837 fRc = True;
3838 for (i, tTest) in enumerate(atTests):
3839 oCurTest = tTest[0] # type: tdTestFileOpen
3840 oCurRes = tTest[1] # type: tdTestResult
3841
3842 reporter.log('Testing #%d: %s - sFile="%s", eAccessMode=%d, eAction=%d, (%s, %s, %s) ...'
3843 % (i, oCurTest.__class__.__name__, oCurTest.sFile, oCurTest.eAccessMode, oCurTest.eAction,
3844 oCurTest.eSharing, oCurTest.fCreationMode, oCurTest.afOpenFlags,));
3845
3846 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3847 fRc, _ = oCurTest.createSession('testGuestCtrlFileOpen: Test #%d' % (i,));
3848 if fRc is not True:
3849 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3850 break;
3851
3852 fRc2 = oCurTest.doSteps(oCurRes.fRc, self);
3853 if fRc2 != oCurRes.fRc:
3854 fRc = reporter.error('Test #%d result mismatch: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
3855
3856 fRc = oCurTest.closeSession() and fRc;
3857
3858 return (fRc, oTxsSession);
3859
3860
3861 def testGuestCtrlFileRead(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-branches,too-many-statements
3862 """
3863 Tests reading from guest files.
3864 """
3865 if self.oTstDrv.fpApiVer < 5.0:
3866 reporter.log('Skipping because of pre 5.0 API');
3867 return None;
3868
3869 #
3870 # Do everything in one session.
3871 #
3872 oTest = tdTestGuestCtrlBase();
3873 oTest.setEnvironment(oSession, oTxsSession, oTestVm);
3874 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet');
3875 if fRc2 is not True:
3876 return (False, oTxsSession);
3877
3878 #
3879 # Create a really big zero filled, up to 1 GiB, adding it to the list of
3880 # files from the set.
3881 #
3882 # Note! This code sucks a bit because we don't have a working setSize nor
3883 # any way to figure out how much free space there is in the guest.
3884 #
3885 aoExtraFiles = [];
3886 sBigName = self.oTestFiles.generateFilenameEx();
3887 sBigPath = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sBigName);
3888 fRc = True;
3889 try:
3890 oFile = oGuestSession.fileOpenEx(sBigPath, vboxcon.FileAccessMode_ReadWrite, vboxcon.FileOpenAction_CreateOrReplace,
3891 vboxcon.FileSharingMode_All, 0, []);
3892 except:
3893 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
3894 else:
3895 # Does setSize work now?
3896 fUseFallback = True;
3897 try:
3898 oFile.setSize(0);
3899 oFile.setSize(64);
3900 fUseFallback = False;
3901 except Exception as oXcpt:
3902 reporter.logXcpt();
3903
3904 # Grow the file till we hit trouble, typical VERR_DISK_FULL, then
3905 # reduce the file size if we have a working setSize.
3906 cbBigFile = 0;
3907 while cbBigFile < (1024 + 32)*1024*1024:
3908 if not fUseFallback:
3909 cbBigFile += 16*1024*1024;
3910 try:
3911 oFile.setSize(cbBigFile);
3912 except Exception as oXcpt:
3913 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
3914 try:
3915 cbBigFile -= 16*1024*1024;
3916 oFile.setSize(cbBigFile);
3917 except:
3918 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
3919 break;
3920 else:
3921 cbBigFile += 32*1024*1024;
3922 try:
3923 oFile.seek(cbBigFile, vboxcon.FileSeekOrigin_Begin);
3924 oFile.write(bytearray(1), 60*1000);
3925 except:
3926 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
3927 break;
3928 try:
3929 cbBigFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
3930 except:
3931 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
3932 try:
3933 oFile.close();
3934 except:
3935 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
3936 if fRc is True:
3937 reporter.log('Big file: %s bytes: %s' % (cbBigFile, sBigPath,));
3938 aoExtraFiles.append(testfileset.TestFileZeroFilled(None, sBigPath, cbBigFile));
3939 else:
3940 try:
3941 oGuestSession.fsObjRemove(sBigPath);
3942 except:
3943 reporter.errorXcpt('fsObjRemove(sBigName=%s)' % (sBigPath,));
3944
3945 #
3946 # Open and read all the files in the test file set.
3947 #
3948 for oTestFile in aoExtraFiles + self.oTestFiles.aoFiles: # type: testfileset.TestFile
3949 reporter.log2('Test file: %s bytes, "%s" ...' % (oTestFile.cbContent, oTestFile.sPath,));
3950
3951 #
3952 # Open it:
3953 #
3954 try:
3955 oFile = oGuestSession.fileOpenEx(oTestFile.sPath, vboxcon.FileAccessMode_ReadOnly,
3956 vboxcon.FileOpenAction_OpenExisting, vboxcon.FileSharingMode_All, 0, []);
3957 except:
3958 fRc = reporter.errorXcpt('sPath=%s' % (oTestFile.sPath, ));
3959 continue;
3960
3961 #
3962 # Read the file in different sized chunks:
3963 #
3964 if oTestFile.cbContent < 128:
3965 acbChunks = xrange(1,128);
3966 elif oTestFile.cbContent < 1024:
3967 acbChunks = (2048, 127, 63, 32, 29, 17, 16, 15, 9);
3968 elif oTestFile.cbContent < 8*1024*1024:
3969 acbChunks = (128*1024, 32*1024, 8191, 255);
3970 else:
3971 acbChunks = (768*1024, 128*1024);
3972
3973 for cbChunk in acbChunks:
3974 # Read the whole file straight thru:
3975 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... cbChunk=%s' % (cbChunk,));
3976 offFile = 0;
3977 cReads = 0;
3978 while offFile <= oTestFile.cbContent:
3979 try:
3980 abRead = oFile.read(cbChunk, 30*1000);
3981 except:
3982 fRc = reporter.errorXcpt('%s: offFile=%s cbChunk=%s cbContent=%s'
3983 % (oTestFile.sPath, offFile, cbChunk, oTestFile.cbContent));
3984 break;
3985 cbRead = len(abRead);
3986 if cbRead == 0 and offFile == oTestFile.cbContent:
3987 break;
3988 if cbRead <= 0:
3989 fRc = reporter.error('%s @%s: cbRead=%s, cbContent=%s'
3990 % (oTestFile.sPath, offFile, cbRead, oTestFile.cbContent));
3991 break;
3992 if not oTestFile.equalMemory(abRead, offFile):
3993 fRc = reporter.error('%s: read mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead));
3994 break;
3995 offFile += cbRead;
3996 cReads += 1;
3997 if cReads > 8192:
3998 break;
3999
4000 # Seek to start of file.
4001 try:
4002 offFile = oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
4003 except:
4004 fRc = reporter.errorXcpt('%s: error seeking to start of file' % (oTestFile.sPath,));
4005 break;
4006 if offFile != 0:
4007 fRc = reporter.error('%s: seek to start of file returned %u, expected 0' % (oTestFile.sPath, offFile));
4008 break;
4009
4010 #
4011 # Random reads.
4012 #
4013 for _ in xrange(8):
4014 offFile = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
4015 cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
4016 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s' % (offFile, cbToRead,));
4017
4018 try:
4019 offActual = oFile.seek(offFile, vboxcon.FileSeekOrigin_Begin);
4020 except:
4021 fRc = reporter.errorXcpt('%s: error seeking to %s' % (oTestFile.sPath, offFile));
4022 break;
4023 if offActual != offFile:
4024 fRc = reporter.error('%s: seek(%s,Begin) -> %s, expected %s'
4025 % (oTestFile.sPath, offFile, offActual, offFile));
4026 break;
4027
4028 try:
4029 abRead = oFile.read(cbToRead, 30*1000);
4030 except:
4031 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s'
4032 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4033 cbRead = 0;
4034 else:
4035 cbRead = len(abRead);
4036 if not oTestFile.equalMemory(abRead, offFile):
4037 fRc = reporter.error('%s: random read mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
4038
4039 try:
4040 offActual = oFile.offset;
4041 except:
4042 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#1)'
4043 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4044 else:
4045 if offActual != offFile + cbRead:
4046 fRc = reporter.error('%s: IFile.offset is %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#1)'
4047 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4048 try:
4049 offActual = oFile.seek(0, vboxcon.FileSeekOrigin_Current);
4050 except:
4051 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#1)'
4052 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4053 else:
4054 if offActual != offFile + cbRead:
4055 fRc = reporter.error('%s: seek(0,cur) -> %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#1)'
4056 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4057
4058 #
4059 # Random reads using readAt.
4060 #
4061 for _ in xrange(12):
4062 offFile = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
4063 cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
4064 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s (readAt)' % (offFile, cbToRead,));
4065
4066 try:
4067 abRead = oFile.readAt(offFile, cbToRead, 30*1000);
4068 except:
4069 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s'
4070 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4071 cbRead = 0;
4072 else:
4073 cbRead = len(abRead);
4074 if not oTestFile.equalMemory(abRead, offFile):
4075 fRc = reporter.error('%s: random readAt mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
4076
4077 try:
4078 offActual = oFile.offset;
4079 except:
4080 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#2)'
4081 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4082 else:
4083 if offActual != offFile + cbRead:
4084 fRc = reporter.error('%s: IFile.offset is %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#2)'
4085 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4086
4087 try:
4088 offActual = oFile.seek(0, vboxcon.FileSeekOrigin_Current);
4089 except:
4090 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#2)'
4091 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4092 else:
4093 if offActual != offFile + cbRead:
4094 fRc = reporter.error('%s: seek(0,cur) -> %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#2)'
4095 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4096
4097 #
4098 # A few negative things.
4099 #
4100
4101 # Zero byte reads -> E_INVALIDARG.
4102 try:
4103 abRead = oFile.read(0, 30*1000);
4104 except Exception as oXcpt:
4105 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
4106 fRc = reporter.errorXcpt('read(0,30s) did not raise E_INVALIDARG as expected!');
4107 else:
4108 fRc = reporter.error('read(0,30s) did not fail!');
4109
4110 try:
4111 abRead = oFile.readAt(0, 0, 30*1000);
4112 except Exception as oXcpt:
4113 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
4114 fRc = reporter.errorXcpt('readAt(0,0,30s) did not raise E_INVALIDARG as expected!');
4115 else:
4116 fRc = reporter.error('readAt(0,0,30s) did not fail!');
4117
4118 # See what happens when we read 1GiB. We should get a max of 1MiB back.
4119 ## @todo Document this behaviour in VirtualBox.xidl.
4120 try:
4121 oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
4122 except:
4123 fRc = reporter.error('seek(0)');
4124 try:
4125 abRead = oFile.read(1024*1024*1024, 30*1000);
4126 except:
4127 fRc = reporter.errorXcpt('read(1GiB,30s)');
4128 else:
4129 if len(abRead) != min(oTestFile.cbContent, 1024*1024):
4130 fRc = reporter.error('Expected read(1GiB,30s) to return %s bytes, got %s bytes instead'
4131 % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
4132
4133 try:
4134 abRead = oFile.readAt(0, 1024*1024*1024, 30*1000);
4135 except:
4136 fRc = reporter.errorXcpt('readAt(0,1GiB,30s)');
4137 else:
4138 if len(abRead) != min(oTestFile.cbContent, 1024*1024):
4139 reporter.error('Expected readAt(0, 1GiB,30s) to return %s bytes, got %s bytes instead'
4140 % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
4141
4142 #
4143 # Check stat info on the file as well as querySize.
4144 #
4145 if self.oTstDrv.fpApiVer > 5.2:
4146 try:
4147 oFsObjInfo = oFile.queryInfo();
4148 except:
4149 fRc = reporter.errorXcpt('%s: queryInfo()' % (oTestFile.sPath,));
4150 else:
4151 if oFsObjInfo is None:
4152 fRc = reporter.error('IGuestFile::queryInfo returned None');
4153 else:
4154 try:
4155 cbFile = oFsObjInfo.objectSize;
4156 except:
4157 fRc = reporter.errorXcpt();
4158 else:
4159 if cbFile != oTestFile.cbContent:
4160 fRc = reporter.error('%s: queryInfo returned incorrect file size: %s, expected %s'
4161 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4162
4163 try:
4164 cbFile = oFile.querySize();
4165 except:
4166 fRc = reporter.errorXcpt('%s: querySize()' % (oTestFile.sPath,));
4167 else:
4168 if cbFile != oTestFile.cbContent:
4169 fRc = reporter.error('%s: querySize returned incorrect file size: %s, expected %s'
4170 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4171
4172 #
4173 # Use seek to test the file size and do a few other end-relative seeks.
4174 #
4175 try:
4176 cbFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
4177 except:
4178 fRc = reporter.errorXcpt('%s: seek(0,End)' % (oTestFile.sPath,));
4179 else:
4180 if cbFile != oTestFile.cbContent:
4181 fRc = reporter.error('%s: seek(0,End) returned incorrect file size: %s, expected %s'
4182 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4183 if oTestFile.cbContent > 0:
4184 for _ in xrange(5):
4185 offSeek = self.oTestFiles.oRandom.randrange(oTestFile.cbContent + 1);
4186 try:
4187 offFile = oFile.seek(-offSeek, vboxcon.FileSeekOrigin_End);
4188 except:
4189 fRc = reporter.errorXcpt('%s: seek(%s,End)' % (oTestFile.sPath, -offSeek,));
4190 else:
4191 if offFile != oTestFile.cbContent - offSeek:
4192 fRc = reporter.error('%s: seek(%s,End) returned incorrect offset: %s, expected %s (cbContent=%s)'
4193 % (oTestFile.sPath, -offSeek, offSeek, oTestFile.cbContent - offSeek,
4194 oTestFile.cbContent,));
4195
4196 #
4197 # Close it and we're done with this file.
4198 #
4199 try:
4200 oFile.close();
4201 except:
4202 fRc = reporter.errorXcpt('%s: error closing the file' % (oTestFile.sPath,));
4203
4204 #
4205 # Clean up.
4206 #
4207 for oTestFile in aoExtraFiles:
4208 try:
4209 oGuestSession.fsObjRemove(sBigPath);
4210 except:
4211 fRc = reporter.errorXcpt('fsObjRemove(%s)' % (sBigPath,));
4212
4213 fRc = oTest.closeSession() and fRc;
4214
4215 return (fRc, oTxsSession);
4216
4217
4218 def testGuestCtrlFileWrite(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4219 """
4220 Tests writing to guest files.
4221 """
4222 if self.oTstDrv.fpApiVer < 5.0:
4223 reporter.log('Skipping because of pre 5.0 API');
4224 return None;
4225
4226 #
4227 # The test file and its content.
4228 #
4229 sFile = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'gctrl-write-1');
4230 abContent = bytearray(0);
4231
4232 #
4233 # The tests.
4234 #
4235 def randBytes(cbHowMany):
4236 """ Returns an bytearray of random bytes. """
4237 return bytearray(self.oTestFiles.oRandom.getrandbits(8) for _ in xrange(cbHowMany));
4238
4239 aoTests = [
4240 # Write at end:
4241 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_CreateNew, abContent = abContent,
4242 atChunks = [(None, randBytes(1)), (None, randBytes(77)), (None, randBytes(98)),]),
4243 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1+77+98), # 176
4244 # Appending:
4245 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_AppendOrCreate, abContent = abContent,
4246 atChunks = [(None, randBytes(255)), (None, randBytes(33)),]),
4247 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 176 + 255+33), # 464
4248 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_AppendOrCreate, abContent = abContent,
4249 atChunks = [(10, randBytes(44)),]),
4250 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 464 + 44), # 508
4251 # Write within existing:
4252 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_OpenExisting, abContent = abContent,
4253 atChunks = [(0, randBytes(1)), (50, randBytes(77)), (255, randBytes(199)),]),
4254 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 508),
4255 # Writing around and over the end:
4256 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent,
4257 atChunks = [(500, randBytes(9)), (508, randBytes(15)), (512, randBytes(12)),]),
4258 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 512+12),
4259
4260 # writeAt appending:
4261 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4262 atChunks = [(0, randBytes(23)), (6, randBytes(1018)),]),
4263 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 6+1018), # 1024
4264 # writeAt within existing:
4265 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4266 atChunks = [(1000, randBytes(23)), (1, randBytes(990)),]),
4267 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1024),
4268 # writeAt around and over the end:
4269 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4270 atChunks = [(1024, randBytes(63)), (1080, randBytes(968)),]),
4271 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1080+968), # 2048
4272
4273 # writeAt beyond the end (gap is filled with zeros):
4274 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True, atChunks = [(3070, randBytes(2)),]),
4275 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 3072),
4276 # write beyond the end (gap is filled with zeros):
4277 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, atChunks = [(4090, randBytes(6)),]),
4278 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 4096),
4279 ];
4280
4281 for (i, oCurTest) in enumerate(aoTests):
4282 reporter.log('Testing #%d: %s ...' % (i, oCurTest.toString(),));
4283
4284 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4285 fRc, _ = oCurTest.createSession('testGuestCtrlFileWrite: Test #%d' % (i,));
4286 if fRc is not True:
4287 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4288 break;
4289
4290 fRc2 = oCurTest.doSteps(True, self);
4291 if fRc2 is not True:
4292 fRc = reporter.error('Test #%d failed!' % (i,));
4293
4294 fRc = oCurTest.closeSession() and fRc;
4295
4296 #
4297 # Cleanup
4298 #
4299 if oTxsSession.syncRmFile(sFile) is not True:
4300 fRc = reporter.error('Failed to remove write-test file: %s' % (sFile, ));
4301
4302 return (fRc, oTxsSession);
4303
4304 @staticmethod
4305 def __generateFile(sName, cbFile):
4306 """ Helper for generating a file with a given size. """
4307 oFile = open(sName, 'wb');
4308 while cbFile > 0:
4309 cb = cbFile if cbFile < 256*1024 else 256*1024;
4310 oFile.write(bytearray(random.getrandbits(8) for _ in xrange(cb)));
4311 cbFile -= cb;
4312 oFile.close();
4313
4314 def testGuestCtrlCopyTo(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4315 """
4316 Tests copying files from host to the guest.
4317 """
4318
4319 #
4320 # Paths and test files.
4321 #
4322 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, 'cp2');
4323 sScratchTestFilesHst = os.path.join(sScratchHst, self.oTestFiles.sSubDir);
4324 sScratchEmptyDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oEmptyDir.sName);
4325 sScratchNonEmptyDirHst = self.oTestFiles.chooseRandomDirFromTree().buildPath(sScratchHst, os.path.sep);
4326 sScratchTreeDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oTreeDir.sName);
4327
4328 sScratchGst = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'cp2');
4329 sScratchDstDir1Gst = oTestVm.pathJoin(sScratchGst, 'dstdir1');
4330 sScratchDstDir2Gst = oTestVm.pathJoin(sScratchGst, 'dstdir2');
4331 sScratchDstDir3Gst = oTestVm.pathJoin(sScratchGst, 'dstdir3');
4332 sScratchDstDir4Gst = oTestVm.pathJoin(sScratchGst, 'dstdir4');
4333 #sScratchGstNotExist = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'no-such-file-or-directory');
4334 sScratchHstNotExist = os.path.join(self.oTstDrv.sScratchPath, 'no-such-file-or-directory');
4335 sScratchGstPathNotFound = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'no-such-directory', 'or-file');
4336 #sScratchHstPathNotFound = os.path.join(self.oTstDrv.sScratchPath, 'no-such-directory', 'or-file');
4337
4338 if oTestVm.isWindows() or oTestVm.isOS2():
4339 sScratchGstInvalid = "?*|<invalid-name>";
4340 else:
4341 sScratchGstInvalid = None;
4342 if utils.getHostOs() in ('win', 'os2'):
4343 sScratchHstInvalid = "?*|<invalid-name>";
4344 else:
4345 sScratchHstInvalid = None;
4346
4347 for sDir in (sScratchGst, sScratchDstDir1Gst, sScratchDstDir2Gst, sScratchDstDir3Gst, sScratchDstDir4Gst):
4348 if oTxsSession.syncMkDir(sDir, 0o777) is not True:
4349 return reporter.error('TXS failed to create directory "%s"!' % (sDir,));
4350
4351 # Put the test file set under sScratchHst.
4352 if os.path.exists(sScratchHst):
4353 if base.wipeDirectory(sScratchHst) != 0:
4354 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
4355 else:
4356 try:
4357 os.mkdir(sScratchHst);
4358 except:
4359 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
4360 if self.oTestFiles.writeToDisk(sScratchHst) is not True:
4361 return reporter.error('Filed to write test files to "%s" on the host!' % (sScratchHst,));
4362
4363 # Generate a test file in 32MB to 64 MB range.
4364 sBigFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-random.data');
4365 cbBigFileHst = random.randrange(32*1024*1024, 64*1024*1024);
4366 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
4367 cbLeft = cbBigFileHst;
4368 try:
4369 self.__generateFile(sBigFileHst, cbBigFileHst);
4370 except:
4371 return reporter.errorXcpt('sBigFileHst=%s cbBigFileHst=%s cbLeft=%s' % (sBigFileHst, cbBigFileHst, cbLeft,));
4372 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
4373
4374 # Generate an empty file on the host that we can use to save space in the guest.
4375 sEmptyFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-empty.data');
4376 try:
4377 oFile = open(sEmptyFileHst, "wb");
4378 oFile.close();
4379 except:
4380 return reporter.errorXcpt('sEmptyFileHst=%s' % (sEmptyFileHst,));
4381
4382 #
4383 # Tests.
4384 #
4385 atTests = [
4386 # Nothing given:
4387 [ tdTestCopyToFile(), tdTestResultFailure() ],
4388 [ tdTestCopyToDir(), tdTestResultFailure() ],
4389 # Only source given:
4390 [ tdTestCopyToFile(sSrc = sBigFileHst), tdTestResultFailure() ],
4391 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst), tdTestResultFailure() ],
4392 # Only destination given:
4393 [ tdTestCopyToFile(sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')), tdTestResultFailure() ],
4394 [ tdTestCopyToDir( sDst = sScratchGst), tdTestResultFailure() ],
4395 # Both given, but invalid flags.
4396 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst, afFlags = [ 0x40000000] ), tdTestResultFailure() ],
4397 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGst, afFlags = [ 0x40000000] ),
4398 tdTestResultFailure() ],
4399 ];
4400 atTests.extend([
4401 # Non-existing source, but no destination:
4402 [ tdTestCopyToFile(sSrc = sScratchHstNotExist), tdTestResultFailure() ],
4403 [ tdTestCopyToDir( sSrc = sScratchHstNotExist), tdTestResultFailure() ],
4404 # Valid sources, but destination path not found:
4405 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
4406 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
4407 # Valid destination, but source file/dir not found:
4408 [ tdTestCopyToFile(sSrc = sScratchHstNotExist, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
4409 tdTestResultFailure() ],
4410 [ tdTestCopyToDir( sSrc = sScratchHstNotExist, sDst = sScratchGst), tdTestResultFailure() ],
4411 # Wrong type:
4412 [ tdTestCopyToFile(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
4413 tdTestResultFailure() ],
4414 [ tdTestCopyToDir( sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultFailure() ],
4415 ]);
4416 # Invalid characters in destination or source path:
4417 if sScratchGstInvalid is not None:
4418 atTests.extend([
4419 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
4420 tdTestResultFailure() ],
4421 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
4422 tdTestResultFailure() ],
4423 ]);
4424 if sScratchHstInvalid is not None:
4425 atTests.extend([
4426 [ tdTestCopyToFile(sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
4427 tdTestResultFailure() ],
4428 [ tdTestCopyToDir( sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
4429 tdTestResultFailure() ],
4430 ]);
4431
4432 #
4433 # Single file handling.
4434 #
4435 atTests.extend([
4436 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')),
4437 tdTestResultSuccess() ],
4438 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
4439 tdTestResultSuccess() ],
4440 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
4441 tdTestResultSuccess() ],
4442 ]);
4443 if self.oTstDrv.fpApiVer > 5.2: # Copying files into directories via Main is supported only 6.0 and later.
4444 atTests.extend([
4445 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ],
4446 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ], # Overwrite
4447 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, os.path.split(sBigFileHst)[1])),
4448 tdTestResultSuccess() ], # Overwrite
4449 ]);
4450
4451 if oTestVm.isWindows():
4452 # Copy to a Windows alternative data stream (ADS).
4453 atTests.extend([
4454 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat:ADS-Test')),
4455 tdTestResultSuccess() ],
4456 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat:ADS-Test')),
4457 tdTestResultSuccess() ],
4458 ]);
4459
4460 #
4461 # Directory handling.
4462 #
4463 if self.oTstDrv.fpApiVer > 5.2: # Copying directories via Main is supported only in versions > 5.2.
4464 atTests.extend([
4465 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultSuccess() ],
4466 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultFailure() ],
4467 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
4468 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4469 # Try again with trailing slash, should yield the same result:
4470 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
4471 tdTestResultSuccess() ],
4472 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
4473 tdTestResultFailure() ],
4474 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep(),
4475 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]),
4476 tdTestResultSuccess() ],
4477 ]);
4478 if not self.fSkipKnownBugs:
4479 atTests.extend([
4480 # Copy with a different destination name just for the heck of it:
4481 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchDstDir1Gst, 'empty2')),
4482 tdTestResultSuccess() ],
4483 ]);
4484 atTests.extend([
4485 # Now the same using a directory with files in it:
4486 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst), tdTestResultSuccess() ],
4487 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst), tdTestResultFailure() ],
4488 ]);
4489 if not self.fSkipKnownBugs:
4490 atTests.extend([
4491 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
4492 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting]), tdTestResultSuccess() ],
4493 ]);
4494 atTests.extend([
4495 #[ tdTestRemoveGuestDir(sScratchDstDir2Gst, tdTestResult() ],
4496 # Copy the entire test tree:
4497 [ tdTestCopyToDir(sSrc = sScratchTreeDirHst, sDst = sScratchDstDir4Gst), tdTestResultSuccess() ],
4498 #[ tdTestRemoveGuestDir(sScratchDstDir3Gst, tdTestResult() ],
4499 ]);
4500
4501 fRc = True;
4502 for (i, tTest) in enumerate(atTests):
4503 oCurTest = tTest[0]; # tdTestCopyTo
4504 oCurRes = tTest[1]; # tdTestResult
4505 reporter.log('Testing #%d, sSrc=%s, sDst=%s, afFlags=%s ...' % (i, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags));
4506
4507 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4508 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyTo: Test #%d' % (i,));
4509 if fRc is not True:
4510 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4511 break;
4512
4513 fRc2 = False;
4514 if isinstance(oCurTest, tdTestCopyToFile):
4515 fRc2 = self.gctrlCopyFileTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags, oCurRes.fRc);
4516 else:
4517 fRc2 = self.gctrlCopyDirTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags, oCurRes.fRc);
4518 if fRc2 is not oCurRes.fRc:
4519 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
4520
4521 fRc = oCurTest.closeSession() and fRc;
4522
4523 return (fRc, oTxsSession);
4524
4525 def testGuestCtrlCopyFrom(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4526 """
4527 Tests copying files from guest to the host.
4528 """
4529
4530 #
4531 # Paths.
4532 #
4533 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom");
4534 sScratchDstDir1Hst = os.path.join(sScratchHst, "dstdir1");
4535 sScratchDstDir2Hst = os.path.join(sScratchHst, "dstdir2");
4536 sScratchDstDir3Hst = os.path.join(sScratchHst, "dstdir3");
4537 oExistingFileGst = self.oTestFiles.chooseRandomFile();
4538 oNonEmptyDirGst = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True);
4539 oEmptyDirGst = self.oTestFiles.oEmptyDir;
4540
4541 if oTestVm.isWindows() or oTestVm.isOS2():
4542 sScratchGstInvalid = "?*|<invalid-name>";
4543 else:
4544 sScratchGstInvalid = None;
4545 if utils.getHostOs() in ('win', 'os2'):
4546 sScratchHstInvalid = "?*|<invalid-name>";
4547 else:
4548 sScratchHstInvalid = None;
4549
4550 if os.path.exists(sScratchHst):
4551 if base.wipeDirectory(sScratchHst) != 0:
4552 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
4553 else:
4554 try:
4555 os.mkdir(sScratchHst);
4556 except:
4557 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
4558
4559 for sSubDir in (sScratchDstDir1Hst, sScratchDstDir2Hst, sScratchDstDir3Hst):
4560 try:
4561 os.mkdir(sSubDir);
4562 except:
4563 return reporter.errorXcpt('os.mkdir(%s)' % (sSubDir, ));
4564
4565 #
4566 # Bad parameter tests.
4567 #
4568 atTests = [
4569 # Missing both source and destination:
4570 [ tdTestCopyFromFile(), tdTestResultFailure() ],
4571 [ tdTestCopyFromDir(), tdTestResultFailure() ],
4572 # Missing source.
4573 [ tdTestCopyFromFile(sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4574 [ tdTestCopyFromDir( sDst = sScratchHst), tdTestResultFailure() ],
4575 # Missing destination.
4576 [ tdTestCopyFromFile(oSrc = oExistingFileGst), tdTestResultFailure() ],
4577 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath), tdTestResultFailure() ],
4578 # Invalid flags:
4579 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somefile'), afFlags = [0x40000000]),
4580 tdTestResultFailure() ],
4581 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'somedir'), afFlags = [ 0x40000000] ),
4582 tdTestResultFailure() ],
4583 # Non-existing sources:
4584 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
4585 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4586 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
4587 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4588 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-file'),
4589 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4590 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-subdir'),
4591 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4592 # Non-existing destinations:
4593 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
4594 sDst = os.path.join(sScratchHst, 'no-such-directory', 'somefile') ), tdTestResultFailure() ],
4595 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'no-such-directory', 'somedir') ),
4596 tdTestResultFailure() ],
4597 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
4598 sDst = os.path.join(sScratchHst, 'no-such-directory-slash' + os.path.sep)),
4599 tdTestResultFailure() ],
4600 # Wrong source type:
4601 [ tdTestCopyFromFile(oSrc = oNonEmptyDirGst, sDst = os.path.join(sScratchHst, 'somefile') ), tdTestResultFailure() ],
4602 [ tdTestCopyFromDir(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somedir') ), tdTestResultFailure() ],
4603 ];
4604 # Bogus names:
4605 if sScratchHstInvalid:
4606 atTests.extend([
4607 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
4608 tdTestResultFailure() ],
4609 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
4610 tdTestResultFailure() ],
4611 ]);
4612 if sScratchGstInvalid:
4613 atTests.extend([
4614 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
4615 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
4616 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
4617 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
4618 ]);
4619
4620 #
4621 # Single file copying.
4622 #
4623 atTests.extend([
4624 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')),
4625 tdTestResultSuccess() ],
4626 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')), # Overwrite it
4627 tdTestResultSuccess() ],
4628 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile2')),
4629 tdTestResultSuccess() ],
4630 ]);
4631 if self.oTstDrv.fpApiVer > 5.2:
4632 # Copy into a directory.
4633 atTests.extend([
4634 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst), tdTestResultSuccess() ],
4635 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst + os.path.sep), tdTestResultSuccess() ],
4636 ]);
4637
4638 #
4639 # Directory tree copying:
4640 #
4641 atTests.extend([
4642 # Copy the empty guest directory (should end up as sScratchHst/empty):
4643 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultSuccess() ],
4644 # Repeat -- this time it should fail, as the destination directory already exists (and
4645 # DirectoryCopyFlag_CopyIntoExisting is not specified):
4646 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst), tdTestResultFailure() ],
4647 # Add the DirectoryCopyFlag_CopyIntoExisting flag being set and it should work.
4648 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst,
4649 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4650 # Try again with trailing slash, should yield the same result:
4651 [ tdTestRemoveHostDir(os.path.join(sScratchDstDir1Hst, 'empty')), tdTestResult() ],
4652 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
4653 tdTestResultSuccess() ],
4654 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep),
4655 tdTestResultFailure() ],
4656 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir1Hst + os.path.sep,
4657 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4658 # Copy with a different destination name just for the heck of it:
4659 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'empty2'), fIntoDst = True),
4660 tdTestResultFailure() ],
4661 # Now the same using a directory with files in it:
4662 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultSuccess() ],
4663 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst), tdTestResultFailure() ],
4664 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir2Hst,
4665 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
4666 # Copy the entire test tree:
4667 [ tdTestCopyFromDir(sSrc = self.oTestFiles.oTreeDir.sPath, sDst = sScratchDstDir3Hst), tdTestResultSuccess() ],
4668 ]);
4669
4670 #
4671 # Execute the tests.
4672 #
4673 fRc = True;
4674 for (i, tTest) in enumerate(atTests):
4675 oCurTest = tTest[0]
4676 oCurRes = tTest[1] # type: tdTestResult
4677 if isinstance(oCurTest, tdTestCopyFrom):
4678 reporter.log('Testing #%d, %s: sSrc="%s", sDst="%s", afFlags="%s" ...'
4679 % (i, "directory" if isinstance(oCurTest, tdTestCopyFromDir) else "file",
4680 oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags,));
4681 else:
4682 reporter.log('Testing #%d, tdTestRemoveHostDir "%s" ...' % (i, oCurTest.sDir,));
4683 if isinstance(oCurTest, tdTestCopyFromDir) and self.oTstDrv.fpApiVer < 6.0:
4684 reporter.log('Skipping directoryCopyFromGuest test, not implemented in %s' % (self.oTstDrv.fpApiVer,));
4685 continue;
4686
4687 if isinstance(oCurTest, tdTestRemoveHostDir):
4688 fRc = oCurTest.execute(self.oTstDrv, oSession, oTxsSession, oTestVm, 'testing #%d' % (i,));
4689 else:
4690 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4691 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyFrom: Test #%d' % (i,));
4692 if fRc2 is not True:
4693 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4694 break;
4695
4696 if isinstance(oCurTest, tdTestCopyFromFile):
4697 fRc2 = self.gctrlCopyFileFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
4698 else:
4699 fRc2 = self.gctrlCopyDirFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
4700
4701 if fRc2 != oCurRes.fRc:
4702 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
4703
4704 fRc = oCurTest.closeSession() and fRc;
4705
4706 return (fRc, oTxsSession);
4707
4708 def testGuestCtrlUpdateAdditions(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4709 """
4710 Tests updating the Guest Additions inside the guest.
4711
4712 """
4713
4714 ## @todo currently disabled everywhere.
4715 if self.oTstDrv.fpApiVer < 100.0:
4716 reporter.log("Skipping updating GAs everywhere for now...");
4717 return None;
4718
4719 # Skip test for updating Guest Additions if we run on a too old (Windows) guest.
4720 ##
4721 ## @todo make it work everywhere!
4722 ##
4723 if oTestVm.sKind in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
4724 reporter.log("Skipping updating GAs on old windows vm (sKind=%s)" % (oTestVm.sKind,));
4725 return (None, oTxsSession);
4726 if oTestVm.isOS2():
4727 reporter.log("Skipping updating GAs on OS/2 guest");
4728 return (None, oTxsSession);
4729
4730 sVBoxValidationKitIso = self.oTstDrv.sVBoxValidationKitIso;
4731 if not os.path.isfile(sVBoxValidationKitIso):
4732 return reporter.log('Validation Kit .ISO not found at "%s"' % (sVBoxValidationKitIso,));
4733
4734 sScratch = os.path.join(self.oTstDrv.sScratchPath, "testGctrlUpdateAdditions");
4735 try:
4736 os.makedirs(sScratch);
4737 except OSError as e:
4738 if e.errno != errno.EEXIST:
4739 return reporter.error('Failed: Unable to create scratch directory \"%s\"' % (sScratch,));
4740 reporter.log('Scratch path is: %s' % (sScratch,));
4741
4742 atTests = [];
4743 if oTestVm.isWindows():
4744 atTests.extend([
4745 # Source is missing.
4746 [ tdTestUpdateAdditions(sSrc = ''), tdTestResultFailure() ],
4747
4748 # Wrong flags.
4749 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
4750 afFlags = [ 1234 ]), tdTestResultFailure() ],
4751
4752 # Non-existing .ISO.
4753 [ tdTestUpdateAdditions(sSrc = "non-existing.iso"), tdTestResultFailure() ],
4754
4755 # Wrong .ISO.
4756 [ tdTestUpdateAdditions(sSrc = sVBoxValidationKitIso), tdTestResultFailure() ],
4757
4758 # The real thing.
4759 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso()),
4760 tdTestResultSuccess() ],
4761 # Test the (optional) installer arguments. This will extract the
4762 # installer into our guest's scratch directory.
4763 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
4764 asArgs = [ '/extract', '/D=' + sScratch ]),
4765 tdTestResultSuccess() ]
4766 # Some debg ISO. Only enable locally.
4767 #[ tdTestUpdateAdditions(
4768 # sSrc = "V:\\Downloads\\VBoxGuestAdditions-r80354.iso"),
4769 # tdTestResultSuccess() ]
4770 ]);
4771 else:
4772 reporter.log('No OS-specific tests for non-Windows yet!');
4773
4774 fRc = True;
4775 for (i, tTest) in enumerate(atTests):
4776 oCurTest = tTest[0] # type: tdTestUpdateAdditions
4777 oCurRes = tTest[1] # type: tdTestResult
4778 reporter.log('Testing #%d, sSrc="%s", afFlags="%s" ...' % (i, oCurTest.sSrc, oCurTest.afFlags,));
4779
4780 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4781 fRc, _ = oCurTest.createSession('Test #%d' % (i,));
4782 if fRc is not True:
4783 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4784 break;
4785
4786 try:
4787 oCurProgress = oCurTest.oGuest.updateGuestAdditions(oCurTest.sSrc, oCurTest.asArgs, oCurTest.afFlags);
4788 except:
4789 reporter.maybeErrXcpt(oCurRes.fRc, 'Updating Guest Additions exception for sSrc="%s", afFlags="%s":'
4790 % (oCurTest.sSrc, oCurTest.afFlags,));
4791 fRc = False;
4792 else:
4793 if oCurProgress is not None:
4794 oWrapperProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr,
4795 self.oTstDrv, "gctrlUpGA");
4796 oWrapperProgress.wait();
4797 if not oWrapperProgress.isSuccess():
4798 oWrapperProgress.logResult(fIgnoreErrors = not oCurRes.fRc);
4799 fRc = False;
4800 else:
4801 fRc = reporter.error('No progress object returned');
4802
4803 oCurTest.closeSession();
4804 if fRc is oCurRes.fRc:
4805 if fRc:
4806 ## @todo Verify if Guest Additions were really updated (build, revision, ...).
4807 ## @todo r=bird: Not possible since you're installing the same GAs as before...
4808 ## Maybe check creation dates on certain .sys/.dll/.exe files?
4809 pass;
4810 else:
4811 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
4812 break;
4813
4814 return (fRc, oTxsSession);
4815
4816
4817
4818class tdAddGuestCtrl(vbox.TestDriver): # pylint: disable=too-many-instance-attributes,too-many-public-methods
4819 """
4820 Guest control using VBoxService on the guest.
4821 """
4822
4823 def __init__(self):
4824 vbox.TestDriver.__init__(self);
4825 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
4826 self.asRsrcs = None;
4827 self.fQuick = False; # Don't skip lengthly tests by default.
4828 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
4829
4830 #
4831 # Overridden methods.
4832 #
4833 def showUsage(self):
4834 """
4835 Shows the testdriver usage.
4836 """
4837 rc = vbox.TestDriver.showUsage(self);
4838 reporter.log('');
4839 reporter.log('tdAddGuestCtrl Options:');
4840 reporter.log(' --quick');
4841 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
4842 return rc;
4843
4844 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
4845 """
4846 Parses the testdriver arguments from the command line.
4847 """
4848 if asArgs[iArg] == '--quick':
4849 self.parseOption(['--virt-modes', 'hwvirt'], 0);
4850 self.parseOption(['--cpu-counts', '1'], 0);
4851 self.fQuick = True;
4852 else:
4853 return vbox.TestDriver.parseOption(self, asArgs, iArg);
4854 return iArg + 1;
4855
4856 def actionConfig(self):
4857 if not self.importVBoxApi(): # So we can use the constant below.
4858 return False;
4859
4860 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
4861 sGaIso = self.getGuestAdditionsIso();
4862 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
4863
4864 def actionExecute(self):
4865 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
4866
4867 #
4868 # Test execution helpers.
4869 #
4870 def testOneCfg(self, oVM, oTestVm): # pylint: disable=too-many-statements
4871 """
4872 Runs the specified VM thru the tests.
4873
4874 Returns a success indicator on the general test execution. This is not
4875 the actual test result.
4876 """
4877
4878 self.logVmInfo(oVM);
4879
4880 fRc = True;
4881 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False);
4882 reporter.log("TxsSession: %s" % (oTxsSession,));
4883 if oSession is not None:
4884 self.addTask(oTxsSession);
4885
4886 fManual = False; # Manual override for local testing. (Committed version shall be False.)
4887 if not fManual:
4888 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
4889 else:
4890 fRc, oTxsSession = self.testGuestCtrlManual(oSession, oTxsSession, oTestVm);
4891
4892 # Cleanup.
4893 self.removeTask(oTxsSession);
4894 if not fManual:
4895 self.terminateVmBySession(oSession);
4896 else:
4897 fRc = False;
4898 return fRc;
4899
4900 def gctrlReportError(self, progress):
4901 """
4902 Helper function to report an error of a
4903 given progress object.
4904 """
4905 if progress is None:
4906 reporter.log('No progress object to print error for');
4907 else:
4908 errInfo = progress.errorInfo;
4909 if errInfo:
4910 reporter.log('%s' % (errInfo.text,));
4911 return False;
4912
4913 def gctrlGetRemainingTime(self, msTimeout, msStart):
4914 """
4915 Helper function to return the remaining time (in ms)
4916 based from a timeout value and the start time (both in ms).
4917 """
4918 if msTimeout == 0:
4919 return 0xFFFFFFFE; # Wait forever.
4920 msElapsed = base.timestampMilli() - msStart;
4921 if msElapsed > msTimeout:
4922 return 0; # No time left.
4923 return msTimeout - msElapsed;
4924
4925 def testGuestCtrlManual(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements,unused-argument,unused-variable
4926 """
4927 For manually testing certain bits.
4928 """
4929
4930 reporter.log('Manual testing ...');
4931 fRc = True;
4932
4933 sUser = 'Administrator';
4934 sPassword = 'password';
4935
4936 oGuest = oSession.o.console.guest;
4937 oGuestSession = oGuest.createSession(sUser,
4938 sPassword,
4939 "", "Manual Test");
4940
4941 aWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
4942 _ = oGuestSession.waitForArray(aWaitFor, 30 * 1000);
4943
4944 sCmd = SubTstDrvAddGuestCtrl.getGuestSystemShell(oTestVm);
4945 asArgs = [ sCmd, '/C', 'dir', '/S', 'c:\\windows' ];
4946 aEnv = [];
4947 afFlags = [];
4948
4949 for _ in xrange(100):
4950 oProc = oGuestSession.processCreate(sCmd, asArgs if self.fpApiVer >= 5.0 else asArgs[1:],
4951 aEnv, afFlags, 30 * 1000);
4952
4953 aWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate ];
4954 _ = oProc.waitForArray(aWaitFor, 30 * 1000);
4955
4956 oGuestSession.close();
4957 oGuestSession = None;
4958
4959 time.sleep(5);
4960
4961 oSession.o.console.PowerDown();
4962
4963 return (fRc, oTxsSession);
4964
4965if __name__ == '__main__':
4966 sys.exit(tdAddGuestCtrl().main(sys.argv));
Note: See TracBrowser for help on using the repository browser.

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