VirtualBox

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

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

Validation Kit/tdAddGuestCtrl: Skip VBoxControl test in the execution tests for <= 5.2. Something for later to investigate.

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

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