VirtualBox

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

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

Validation Kit/tdAddGuestCtrl: Pylint.

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

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