VirtualBox

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

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

Validation Kit/Guest Control: Some slash fixes in prepareGuestForTesting() needed for cross-platform testing.

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