VirtualBox

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

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

Validation Kit/tdAddGuestCtrl: Bugfixes for gctrlExecute().

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