VirtualBox

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

最後變更 在這個檔案從102100是 102076,由 vboxsync 提交於 17 月 前

ValKit: Simple algorithm for basic screenshot validation of a Windows VM (fix for Python 2)

  • 屬性 svn:eol-style 設為 LF
  • 屬性 svn:executable 設為 *
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 279.9 KB
 
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-2023 Oracle and/or its affiliates.
12
13This file is part of VirtualBox base platform packages, as
14available from https://www.alldomusa.eu.org.
15
16This program is free software; you can redistribute it and/or
17modify it under the terms of the GNU General Public License
18as published by the Free Software Foundation, in version 3 of the
19License.
20
21This program is distributed in the hope that it will be useful, but
22WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with this program; if not, see <https://www.gnu.org/licenses>.
28
29The contents of this file may alternatively be used under the terms
30of the Common Development and Distribution License Version 1.0
31(CDDL), a copy of it is provided in the "COPYING.CDDL" file included
32in the VirtualBox distribution, in which case the provisions of the
33CDDL are applicable instead of those of the GPL.
34
35You may elect to license modified versions of this file under the
36terms and conditions of either the GPL or the CDDL or both.
37
38SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
39"""
40__version__ = "$Revision: 102076 $"
41
42# Standard Python imports.
43import errno
44import os
45import random
46import string
47import struct
48import sys
49import threading
50import time
51
52# Only the main script needs to modify the path.
53try: __file__ # pylint: disable=used-before-assignment
54except: __file__ = sys.argv[0];
55g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
56sys.path.append(g_ksValidationKitDir);
57
58# Validation Kit imports.
59from testdriver import reporter;
60from testdriver import base;
61from testdriver import testfileset;
62from testdriver import vbox;
63from testdriver import vboxcon;
64from testdriver import vboxtestfileset;
65from testdriver import vboxwrappers;
66from common import utils;
67
68# Python 3 hacks:
69if sys.version_info[0] >= 3:
70 long = int # pylint: disable=redefined-builtin,invalid-name
71 xrange = range; # pylint: disable=redefined-builtin,invalid-name
72
73def limitString(sString, cLimit = 128):
74 """
75 Returns a string with ellipsis ("...") when exceeding the specified limit.
76 Useful for toning down logging. By default strings will be shortened at 128 characters.
77 """
78 if not isinstance(sString, str):
79 sString = str(sString);
80 cLen = len(sString);
81 if not cLen:
82 return '';
83 return (sString[:cLimit] + '...[%d more]' % (cLen - cLimit)) if cLen > cLimit else sString;
84
85class GuestStream(bytearray):
86 """
87 Class for handling a guest process input/output stream.
88
89 @todo write stdout/stderr tests.
90 """
91 def appendStream(self, stream, convertTo = '<b'):
92 """
93 Appends and converts a byte sequence to this object;
94 handy for displaying a guest stream.
95 """
96 self.extend(struct.pack(convertTo, stream));
97
98
99class tdCtxCreds(object):
100 """
101 Provides credentials to pass to the guest.
102 """
103 def __init__(self, sUser = None, sPassword = None, sDomain = None):
104 self.oTestVm = None;
105 self.sUser = sUser;
106 self.sPassword = sPassword;
107 self.sDomain = sDomain;
108
109 def applyDefaultsIfNotSet(self, oTestVm):
110 """
111 Applies credential defaults, based on the test VM (guest OS), if
112 no credentials were set yet.
113
114 Returns success status.
115 """
116 self.oTestVm = oTestVm;
117 if not self.oTestVm:
118 reporter.log('VM object is invalid -- did VBoxSVC or a client crash?');
119 return False;
120
121 if self.sUser is None:
122 self.sUser = self.oTestVm.getTestUser();
123
124 if self.sPassword is None:
125 self.sPassword = self.oTestVm.getTestUserPassword(self.sUser);
126
127 if self.sDomain is None:
128 self.sDomain = '';
129
130 return True;
131
132class tdTestGuestCtrlBase(object):
133 """
134 Base class for all guest control tests.
135
136 Note: This test ASSUMES that working Guest Additions
137 were installed and running on the guest to be tested.
138 """
139 def __init__(self, oCreds = None):
140 self.oGuest = None; ##< IGuest.
141 self.oTestVm = None;
142 self.oCreds = oCreds ##< type: tdCtxCreds
143 self.timeoutMS = 30 * 1000; ##< 30s timeout
144 self.oGuestSession = None; ##< IGuestSession reference or None.
145
146 def setEnvironment(self, oSession, oTxsSession, oTestVm):
147 """
148 Sets the test environment required for this test.
149
150 Returns success status.
151 """
152 _ = oTxsSession;
153
154 fRc = True;
155 try:
156 self.oGuest = oSession.o.console.guest;
157 self.oTestVm = oTestVm;
158 except:
159 fRc = reporter.errorXcpt();
160
161 if self.oCreds is None:
162 self.oCreds = tdCtxCreds();
163
164 fRc = fRc and self.oCreds.applyDefaultsIfNotSet(self.oTestVm);
165
166 if not fRc:
167 reporter.log('Error setting up Guest Control testing environment!');
168
169 return fRc;
170
171 def uploadLogData(self, oTstDrv, aData, sFileName, sDesc):
172 """
173 Uploads (binary) data to a log file for manual (later) inspection.
174 """
175 reporter.log('Creating + uploading log data file "%s"' % sFileName);
176 sHstFileName = os.path.join(oTstDrv.sScratchPath, sFileName);
177 try:
178 with open(sHstFileName, "wb") as oCurTestFile:
179 oCurTestFile.write(aData);
180 except:
181 return reporter.error('Unable to create temporary file for "%s"' % (sDesc,));
182 return reporter.addLogFile(sHstFileName, 'misc/other', sDesc);
183
184 def createSession(self, sName, fIsError = True):
185 """
186 Creates (opens) a guest session.
187 Returns (True, IGuestSession) on success or (False, None) on failure.
188 """
189 if self.oGuestSession is None:
190 if sName is None:
191 sName = "<untitled>";
192
193 reporter.log('Creating session "%s" ...' % (sName,));
194 try:
195 self.oGuestSession = self.oGuest.createSession(self.oCreds.sUser,
196 self.oCreds.sPassword,
197 self.oCreds.sDomain,
198 sName);
199 except:
200 # Just log, don't assume an error here (will be done in the main loop then).
201 reporter.maybeErrXcpt(fIsError, 'Creating a guest session "%s" failed; sUser="%s", pw="%s", sDomain="%s":'
202 % (sName, self.oCreds.sUser, self.oCreds.sPassword, self.oCreds.sDomain));
203 return (False, None);
204
205 tsStartMs = base.timestampMilli();
206 while base.timestampMilli() - tsStartMs < self.timeoutMS:
207 reporter.log('Waiting for session "%s" to start within %dms...' % (sName, self.timeoutMS));
208 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
209 try:
210 waitResult = self.oGuestSession.waitForArray(aeWaitFor, self.timeoutMS);
211
212 # Log session status changes.
213 if waitResult is vboxcon.GuestSessionWaitResult_Status:
214 reporter.log('Session "%s" indicated status change (status is now %d)' \
215 % (sName, self.oGuestSession.status));
216 if self.oGuestSession.status is vboxcon.GuestSessionStatus_Started:
217 # We indicate an error here, as we intentionally waited for the session start
218 # in the wait call above and got back a status change instead.
219 reporter.error('Session "%s" successfully started (thru status change)' % (sName,));
220 break;
221 continue; # Continue waiting for the session to start.
222
223 #
224 # Be nice to Guest Additions < 4.3: They don't support session handling and
225 # therefore return WaitFlagNotSupported.
226 #
227 if waitResult not in (vboxcon.GuestSessionWaitResult_Start, \
228 vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
229 # Just log, don't assume an error here (will be done in the main loop then).
230 reporter.maybeErr(fIsError, 'Session did not start successfully, returned wait result: %d' \
231 % (waitResult,));
232 return (False, None);
233 reporter.log('Session "%s" successfully started' % (sName,));
234
235 #
236 # Make sure that the test VM configuration and Guest Control use the same path separator style for the guest.
237 #
238 sGstSep = '\\' if self.oGuestSession.pathStyle is vboxcon.PathStyle_DOS else '/';
239 if self.oTestVm.pathSep() != sGstSep:
240 reporter.error('Configured test VM uses a different path style (%s) than Guest Control (%s)' \
241 % (self.oTestVm.pathSep(), sGstSep));
242 break;
243 except:
244 # Just log, don't assume an error here (will be done in the main loop then).
245 reporter.maybeErrXcpt(fIsError, 'Waiting for guest session "%s" (usr=%s;pw=%s;dom=%s) to start failed:'
246 % (sName, self.oCreds.sUser, self.oCreds.sPassword, self.oCreds.sDomain,));
247 return (False, None);
248 else:
249 reporter.log('Warning: Session already set; this is probably not what you want');
250 return (True, self.oGuestSession);
251
252 def setSession(self, oGuestSession):
253 """
254 Sets the current guest session and closes
255 an old one if necessary.
256 """
257 if self.oGuestSession is not None:
258 self.closeSession();
259 self.oGuestSession = oGuestSession;
260 return self.oGuestSession;
261
262 def closeSession(self, fIsError = True):
263 """
264 Closes the guest session.
265 """
266 if self.oGuestSession is not None:
267 try:
268 sName = self.oGuestSession.name;
269 except:
270 return reporter.errorXcpt();
271
272 reporter.log('Closing session "%s" ...' % (sName,));
273 try:
274 self.oGuestSession.close();
275 self.oGuestSession = None;
276 except:
277 # Just log, don't assume an error here (will be done in the main loop then).
278 reporter.maybeErrXcpt(fIsError, 'Closing guest session "%s" failed:' % (sName,));
279 return False;
280 return True;
281
282class tdTestCopyFrom(tdTestGuestCtrlBase):
283 """
284 Test for copying files from the guest to the host.
285 """
286 def __init__(self, sSrc = "", sDst = "", oCreds = None, afFlags = None, oSrc = None):
287 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
288 self.sSrc = sSrc;
289 self.sDst = sDst;
290 self.afFlags = afFlags;
291 self.oSrc = oSrc # type: testfileset.TestFsObj
292 if oSrc and not sSrc:
293 self.sSrc = oSrc.sPath;
294
295class tdTestCopyFromDir(tdTestCopyFrom):
296
297 def __init__(self, sSrc = "", sDst = "", oCreds = None, afFlags = None, oSrc = None, fIntoDst = False):
298 tdTestCopyFrom.__init__(self, sSrc, sDst, oCreds, afFlags, oSrc);
299 self.fIntoDst = fIntoDst; # hint to the verification code that sDst == oSrc, rather than sDst+oSrc.sNAme == oSrc.
300
301class tdTestCopyFromFile(tdTestCopyFrom):
302 pass;
303
304class tdTestRemoveHostDir(object):
305 """
306 Test step that removes a host directory tree.
307 """
308 def __init__(self, sDir):
309 self.sDir = sDir;
310
311 def execute(self, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
312 _ = oTstDrv; _ = oVmSession; _ = oTxsSession; _ = oTestVm; _ = sMsgPrefix;
313 if os.path.exists(self.sDir):
314 if base.wipeDirectory(self.sDir) != 0:
315 return False;
316 try:
317 os.rmdir(self.sDir);
318 except:
319 return reporter.errorXcpt('%s: sDir=%s' % (sMsgPrefix, self.sDir,));
320 return True;
321
322
323
324class tdTestCopyTo(tdTestGuestCtrlBase):
325 """
326 Test for copying files from the host to the guest.
327 """
328 def __init__(self, sSrc = "", sDst = "", oCreds = None, afFlags = None):
329 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
330 self.sSrc = sSrc;
331 self.sDst = sDst;
332 self.afFlags = afFlags;
333
334class tdTestCopyToFile(tdTestCopyTo):
335 pass;
336
337class tdTestCopyToDir(tdTestCopyTo):
338 pass;
339
340class tdTestDirCreate(tdTestGuestCtrlBase):
341 """
342 Test for directoryCreate call.
343 """
344 def __init__(self, sDirectory = "", oCreds = None, fMode = 0, afFlags = None):
345 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
346 self.sDirectory = sDirectory;
347 self.fMode = fMode;
348 self.afFlags = afFlags;
349
350class tdTestDirCreateTemp(tdTestGuestCtrlBase):
351 """
352 Test for the directoryCreateTemp call.
353 """
354 def __init__(self, sDirectory = "", sTemplate = "", oCreds = None, fMode = 0, fSecure = False):
355 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
356 self.sDirectory = sDirectory;
357 self.sTemplate = sTemplate;
358 self.fMode = fMode;
359 self.fSecure = fSecure;
360
361class tdTestDirOpen(tdTestGuestCtrlBase):
362 """
363 Test for the directoryOpen call.
364 """
365 def __init__(self, sDirectory = "", oCreds = None, sFilter = "", afFlags = None):
366 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
367 self.sDirectory = sDirectory;
368 self.sFilter = sFilter;
369 self.afFlags = afFlags or [];
370
371class tdTestDirRead(tdTestDirOpen):
372 """
373 Test for the opening, reading and closing a certain directory.
374 """
375 def __init__(self, sDirectory = "", oCreds = None, sFilter = "", afFlags = None):
376 tdTestDirOpen.__init__(self, sDirectory, oCreds, sFilter, afFlags);
377
378class tdTestExec(tdTestGuestCtrlBase):
379 """
380 Specifies exactly one guest control execution test.
381 Has a default timeout of 5 minutes (for safety).
382 """
383 def __init__(self, sCmd = "", sCwd = "", asArgs = None, aEnv = None, afFlags = None, # pylint: disable=too-many-arguments
384 timeoutMS = 5 * 60 * 1000, oCreds = None, fWaitForExit = True):
385 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
386 self.sCmd = sCmd;
387 self.sCwd = sCwd;
388 self.asArgs = asArgs if asArgs is not None else [sCmd,];
389 self.aEnv = aEnv;
390 self.afFlags = afFlags or [];
391 self.timeoutMS = timeoutMS;
392 self.fWaitForExit = fWaitForExit;
393 self.uExitStatus = 0;
394 self.iExitCode = 0;
395 self.cbStdOut = 0;
396 self.cbStdErr = 0;
397 self.sBuf = '';
398
399class tdTestFileExists(tdTestGuestCtrlBase):
400 """
401 Test for the file exists API call (fileExists).
402 """
403 def __init__(self, sFile = "", oCreds = None):
404 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
405 self.sFile = sFile;
406
407class tdTestFileRemove(tdTestGuestCtrlBase):
408 """
409 Test querying guest file information.
410 """
411 def __init__(self, sFile = "", oCreds = None):
412 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
413 self.sFile = sFile;
414
415class tdTestRemoveBase(tdTestGuestCtrlBase):
416 """
417 Removal base.
418 """
419 def __init__(self, sPath, fRcExpect = True, oCreds = None):
420 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
421 self.sPath = sPath;
422 self.fRcExpect = fRcExpect;
423
424 def execute(self, oSubTstDrv):
425 """
426 Executes the test, returns True/False.
427 """
428 _ = oSubTstDrv;
429 return True;
430
431 def checkRemoved(self, sType):
432 """ Check that the object was removed using fObjExists. """
433 try:
434 fExists = self.oGuestSession.fsObjExists(self.sPath, False);
435 except:
436 return reporter.errorXcpt('fsObjExists failed on "%s" after deletion (type: %s)' % (self.sPath, sType));
437 if fExists:
438 return reporter.error('fsObjExists says "%s" still exists after deletion (type: %s)!' % (self.sPath, sType));
439 return True;
440
441class tdTestRemoveFile(tdTestRemoveBase):
442 """
443 Remove a single file.
444 """
445 def __init__(self, sPath, fRcExpect = True, oCreds = None):
446 tdTestRemoveBase.__init__(self, sPath, fRcExpect, oCreds);
447
448 def execute(self, oSubTstDrv):
449 reporter.log2('Deleting file "%s" ...' % (limitString(self.sPath),));
450 try:
451 if oSubTstDrv.oTstDrv.fpApiVer >= 5.0:
452 self.oGuestSession.fsObjRemove(self.sPath);
453 else:
454 self.oGuestSession.fileRemove(self.sPath);
455 except:
456 reporter.maybeErrXcpt(self.fRcExpect, 'Removing "%s" failed' % (self.sPath,));
457 return not self.fRcExpect;
458 if not self.fRcExpect:
459 return reporter.error('Expected removing "%s" to failed, but it succeeded' % (self.sPath,));
460
461 return self.checkRemoved('file');
462
463class tdTestRemoveDir(tdTestRemoveBase):
464 """
465 Remove a single directory if empty.
466 """
467 def __init__(self, sPath, fRcExpect = True, oCreds = None):
468 tdTestRemoveBase.__init__(self, sPath, fRcExpect, oCreds);
469
470 def execute(self, oSubTstDrv):
471 _ = oSubTstDrv;
472 reporter.log2('Deleting directory "%s" ...' % (limitString(self.sPath),));
473 try:
474 self.oGuestSession.directoryRemove(self.sPath);
475 except:
476 reporter.maybeErrXcpt(self.fRcExpect, 'Removing "%s" (as a directory) failed' % (self.sPath,));
477 return not self.fRcExpect;
478 if not self.fRcExpect:
479 return reporter.error('Expected removing "%s" (dir) to failed, but it succeeded' % (self.sPath,));
480
481 return self.checkRemoved('directory');
482
483class tdTestRemoveTree(tdTestRemoveBase):
484 """
485 Recursively remove a directory tree.
486 """
487 def __init__(self, sPath, afFlags = None, fRcExpect = True, fNotExist = False, oCreds = None):
488 tdTestRemoveBase.__init__(self, sPath, fRcExpect, oCreds = None);
489 self.afFlags = afFlags if afFlags is not None else [];
490 self.fNotExist = fNotExist; # Hack for the ContentOnly scenario where the dir does not exist.
491
492 def execute(self, oSubTstDrv):
493 reporter.log2('Deleting tree "%s" ...' % (limitString(self.sPath),));
494 try:
495 oProgress = self.oGuestSession.directoryRemoveRecursive(self.sPath, self.afFlags);
496 except:
497 reporter.maybeErrXcpt(self.fRcExpect, 'Removing directory tree "%s" failed (afFlags=%s)'
498 % (self.sPath, self.afFlags));
499 return not self.fRcExpect;
500
501 oWrappedProgress = vboxwrappers.ProgressWrapper(oProgress, oSubTstDrv.oTstDrv.oVBoxMgr, oSubTstDrv.oTstDrv,
502 "remove-tree: %s" % (self.sPath,));
503 oWrappedProgress.wait();
504 if not oWrappedProgress.isSuccess():
505 oWrappedProgress.logResult(fIgnoreErrors = not self.fRcExpect);
506 return not self.fRcExpect;
507 if not self.fRcExpect:
508 return reporter.error('Expected removing "%s" (tree) to failed, but it succeeded' % (self.sPath,));
509
510 if vboxcon.DirectoryRemoveRecFlag_ContentAndDir not in self.afFlags and not self.fNotExist:
511 # Cannot use directoryExists here as it is buggy.
512 try:
513 if oSubTstDrv.oTstDrv.fpApiVer >= 5.0:
514 oFsObjInfo = self.oGuestSession.fsObjQueryInfo(self.sPath, False);
515 else:
516 oFsObjInfo = self.oGuestSession.fileQueryInfo(self.sPath);
517 eType = oFsObjInfo.type;
518 except:
519 return reporter.errorXcpt('sPath=%s' % (self.sPath,));
520 if eType != vboxcon.FsObjType_Directory:
521 return reporter.error('Found file type %d, expected directory (%d) for %s after rmtree/OnlyContent'
522 % (eType, vboxcon.FsObjType_Directory, self.sPath,));
523 return True;
524
525 return self.checkRemoved('tree');
526
527
528class tdTestFileStat(tdTestGuestCtrlBase):
529 """
530 Test querying guest file information.
531 """
532 def __init__(self, sFile = "", oCreds = None, cbSize = 0, eFileType = 0):
533 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
534 self.sFile = sFile;
535 self.cbSize = cbSize;
536 self.eFileType = eFileType;
537
538class tdTestFileIO(tdTestGuestCtrlBase):
539 """
540 Test for the IGuestFile object.
541 """
542 def __init__(self, sFile = "", oCreds = None):
543 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
544 self.sFile = sFile;
545
546class tdTestFileQuerySize(tdTestGuestCtrlBase):
547 """
548 Test for the file size query API call (fileQuerySize).
549 """
550 def __init__(self, sFile = "", oCreds = None):
551 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
552 self.sFile = sFile;
553
554class tdTestFileOpen(tdTestGuestCtrlBase):
555 """
556 Tests opening a guest files.
557 """
558 def __init__(self, sFile = "", eAccessMode = None, eAction = None, eSharing = None,
559 fCreationMode = 0o660, oCreds = None):
560 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
561 self.sFile = sFile;
562 self.eAccessMode = eAccessMode if eAccessMode is not None else vboxcon.FileAccessMode_ReadOnly;
563 self.eAction = eAction if eAction is not None else vboxcon.FileOpenAction_OpenExisting;
564 self.eSharing = eSharing if eSharing is not None else vboxcon.FileSharingMode_All;
565 self.fCreationMode = fCreationMode;
566 self.afOpenFlags = [];
567 self.oOpenedFile = None;
568
569 def toString(self):
570 """ Get a summary string. """
571 return 'eAccessMode=%s eAction=%s sFile=%s' % (self.eAccessMode, self.eAction, self.sFile);
572
573 def doOpenStep(self, fExpectSuccess):
574 """
575 Does the open step, putting the resulting file in oOpenedFile.
576 """
577 try:
578 self.oOpenedFile = self.oGuestSession.fileOpenEx(self.sFile, self.eAccessMode, self.eAction,
579 self.eSharing, self.fCreationMode, self.afOpenFlags);
580 except:
581 reporter.maybeErrXcpt(fExpectSuccess, 'fileOpenEx(%s, %s, %s, %s, %s, %s)'
582 % (self.sFile, self.eAccessMode, self.eAction, self.eSharing,
583 self.fCreationMode, self.afOpenFlags,));
584 return False;
585 return True;
586
587 def doStepsOnOpenedFile(self, fExpectSuccess, oSubTst):
588 """ Overridden by children to do more testing. """
589 _ = fExpectSuccess; _ = oSubTst;
590 return True;
591
592 def doCloseStep(self):
593 """ Closes the file. """
594 if self.oOpenedFile:
595 try:
596 self.oOpenedFile.close();
597 except:
598 return reporter.errorXcpt('close([%s, %s, %s, %s, %s, %s])'
599 % (self.sFile, self.eAccessMode, self.eAction, self.eSharing,
600 self.fCreationMode, self.afOpenFlags,));
601 self.oOpenedFile = None;
602 return True;
603
604 def doSteps(self, fExpectSuccess, oSubTst):
605 """ Do the tests. """
606 fRc = self.doOpenStep(fExpectSuccess);
607 if fRc is True:
608 fRc = self.doStepsOnOpenedFile(fExpectSuccess, oSubTst);
609 if self.oOpenedFile:
610 fRc = self.doCloseStep() and fRc;
611 return fRc;
612
613
614class tdTestFileOpenCheckSize(tdTestFileOpen):
615 """
616 Opens a file and checks the size.
617 """
618 def __init__(self, sFile = "", eAccessMode = None, eAction = None, eSharing = None,
619 fCreationMode = 0o660, cbOpenExpected = 0, oCreds = None):
620 tdTestFileOpen.__init__(self, sFile, eAccessMode, eAction, eSharing, fCreationMode, oCreds);
621 self.cbOpenExpected = cbOpenExpected;
622
623 def toString(self):
624 return 'cbOpenExpected=%s %s' % (self.cbOpenExpected, tdTestFileOpen.toString(self),);
625
626 def doStepsOnOpenedFile(self, fExpectSuccess, oSubTst):
627 #
628 # Call parent.
629 #
630 fRc = tdTestFileOpen.doStepsOnOpenedFile(self, fExpectSuccess, oSubTst);
631
632 #
633 # Check the size. Requires 6.0 or later (E_NOTIMPL in 5.2).
634 #
635 if oSubTst.oTstDrv.fpApiVer >= 6.0:
636 try:
637 oFsObjInfo = self.oOpenedFile.queryInfo();
638 except:
639 return reporter.errorXcpt('queryInfo([%s, %s, %s, %s, %s, %s])'
640 % (self.sFile, self.eAccessMode, self.eAction, self.eSharing,
641 self.fCreationMode, self.afOpenFlags,));
642 if oFsObjInfo is None:
643 return reporter.error('IGuestFile::queryInfo returned None');
644 try:
645 cbFile = oFsObjInfo.objectSize;
646 except:
647 return reporter.errorXcpt();
648 if cbFile != self.cbOpenExpected:
649 return reporter.error('Wrong file size after open (%d): %s, expected %s (file %s) (#1)'
650 % (self.eAction, cbFile, self.cbOpenExpected, self.sFile));
651
652 try:
653 cbFile = self.oOpenedFile.querySize();
654 except:
655 return reporter.errorXcpt('querySize([%s, %s, %s, %s, %s, %s])'
656 % (self.sFile, self.eAccessMode, self.eAction, self.eSharing,
657 self.fCreationMode, self.afOpenFlags,));
658 if cbFile != self.cbOpenExpected:
659 return reporter.error('Wrong file size after open (%d): %s, expected %s (file %s) (#2)'
660 % (self.eAction, cbFile, self.cbOpenExpected, self.sFile));
661
662 return fRc;
663
664
665class tdTestFileOpenAndWrite(tdTestFileOpen):
666 """
667 Opens the file and writes one or more chunks to it.
668
669 The chunks are a list of tuples(offset, bytes), where offset can be None
670 if no seeking should be performed.
671 """
672 def __init__(self, sFile = "", eAccessMode = None, eAction = None, eSharing = None, # pylint: disable=too-many-arguments
673 fCreationMode = 0o660, atChunks = None, fUseAtApi = False, abContent = None, oCreds = None):
674 tdTestFileOpen.__init__(self, sFile, eAccessMode if eAccessMode is not None else vboxcon.FileAccessMode_WriteOnly,
675 eAction, eSharing, fCreationMode, oCreds);
676 assert atChunks is not None;
677 self.atChunks = atChunks # type: list(tuple(int,bytearray))
678 self.fUseAtApi = fUseAtApi;
679 self.fAppend = ( eAccessMode in (vboxcon.FileAccessMode_AppendOnly, vboxcon.FileAccessMode_AppendRead)
680 or eAction == vboxcon.FileOpenAction_AppendOrCreate);
681 self.abContent = abContent # type: bytearray
682
683 def toString(self):
684 sChunks = ', '.join('%s LB %s' % (tChunk[0], len(tChunk[1]),) for tChunk in self.atChunks);
685 sApi = 'writeAt' if self.fUseAtApi else 'write';
686 return '%s [%s] %s' % (sApi, sChunks, tdTestFileOpen.toString(self),);
687
688 def doStepsOnOpenedFile(self, fExpectSuccess, oSubTst):
689 #
690 # Call parent.
691 #
692 fRc = tdTestFileOpen.doStepsOnOpenedFile(self, fExpectSuccess, oSubTst);
693
694 #
695 # Do the writing.
696 #
697 for offFile, abBuf in self.atChunks:
698 if self.fUseAtApi:
699 #
700 # writeAt:
701 #
702 assert offFile is not None;
703 reporter.log2('writeAt(%s, %s bytes)' % (offFile, len(abBuf),));
704 if self.fAppend:
705 if self.abContent is not None: # Try avoid seek as it updates the cached offset in GuestFileImpl.
706 offExpectAfter = len(self.abContent);
707 else:
708 try:
709 offSave = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_Current);
710 offExpectAfter = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_End);
711 self.oOpenedFile.seek(offSave, vboxcon.FileSeekOrigin_Begin);
712 except:
713 return reporter.errorXcpt();
714 offExpectAfter += len(abBuf);
715 else:
716 offExpectAfter = offFile + len(abBuf);
717
718 try:
719 cbWritten = self.oOpenedFile.writeAt(offFile, abBuf, 30*1000);
720 except:
721 return reporter.errorXcpt('writeAt(%s, %s bytes)' % (offFile, len(abBuf),));
722
723 else:
724 #
725 # write:
726 #
727 if self.fAppend:
728 if self.abContent is not None: # Try avoid seek as it updates the cached offset in GuestFileImpl.
729 offExpectAfter = len(self.abContent);
730 else:
731 try:
732 offSave = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_Current);
733 offExpectAfter = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_End);
734 self.oOpenedFile.seek(offSave, vboxcon.FileSeekOrigin_Begin);
735 except:
736 return reporter.errorXcpt('seek(0,End)');
737 if offFile is not None:
738 try:
739 self.oOpenedFile.seek(offFile, vboxcon.FileSeekOrigin_Begin);
740 except:
741 return reporter.errorXcpt('seek(%s,Begin)' % (offFile,));
742 else:
743 try:
744 offFile = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_Current);
745 except:
746 return reporter.errorXcpt();
747 if not self.fAppend:
748 offExpectAfter = offFile;
749 offExpectAfter += len(abBuf);
750
751 reporter.log2('write(%s bytes @ %s)' % (len(abBuf), offFile,));
752 try:
753 cbWritten = self.oOpenedFile.write(abBuf, 30*1000);
754 except:
755 return reporter.errorXcpt('write(%s bytes @ %s)' % (len(abBuf), offFile));
756
757 #
758 # Check how much was written, ASSUMING nothing we push thru here is too big:
759 #
760 if cbWritten != len(abBuf):
761 fRc = reporter.errorXcpt('Wrote less than expected: %s out of %s, expected all to be written'
762 % (cbWritten, len(abBuf),));
763 if not self.fAppend:
764 offExpectAfter -= len(abBuf) - cbWritten;
765
766 #
767 # Update the file content tracker if we've got one and can:
768 #
769 if self.abContent is not None:
770 if cbWritten < len(abBuf):
771 abBuf = abBuf[:cbWritten];
772
773 #
774 # In append mode, the current file offset shall be disregarded and the
775 # write always goes to the end of the file, regardless of writeAt or write.
776 # Note that RTFileWriteAt only naturally behaves this way on linux and
777 # (probably) windows, so VBoxService makes that behaviour generic across
778 # all OSes.
779 #
780 if self.fAppend:
781 reporter.log2('len(self.abContent)=%s + %s' % (len(self.abContent), cbWritten, ));
782 self.abContent.extend(abBuf);
783 else:
784 if offFile is None:
785 offFile = offExpectAfter - cbWritten;
786 reporter.log2('len(self.abContent)=%s + %s @ %s' % (len(self.abContent), cbWritten, offFile, ));
787 if offFile > len(self.abContent):
788 self.abContent.extend(bytearray(offFile - len(self.abContent)));
789 self.abContent[offFile:offFile + cbWritten] = abBuf;
790 reporter.log2('len(self.abContent)=%s' % (len(self.abContent),));
791
792 #
793 # Check the resulting file offset with IGuestFile::offset.
794 #
795 try:
796 offApi = self.oOpenedFile.offset; # Must be gotten first!
797 offSeek = self.oOpenedFile.seek(0, vboxcon.FileSeekOrigin_Current);
798 except:
799 fRc = reporter.errorXcpt();
800 else:
801 reporter.log2('offApi=%s offSeek=%s offExpectAfter=%s' % (offApi, offSeek, offExpectAfter,));
802 if offSeek != offExpectAfter:
803 fRc = reporter.error('Seek offset is %s, expected %s after %s bytes write @ %s (offApi=%s)'
804 % (offSeek, offExpectAfter, len(abBuf), offFile, offApi,));
805 if offApi != offExpectAfter:
806 fRc = reporter.error('IGuestFile::offset is %s, expected %s after %s bytes write @ %s (offSeek=%s)'
807 % (offApi, offExpectAfter, len(abBuf), offFile, offSeek,));
808 # for each chunk - end
809 return fRc;
810
811
812class tdTestFileOpenAndCheckContent(tdTestFileOpen):
813 """
814 Opens the file and checks the content using the read API.
815 """
816 def __init__(self, sFile = "", eSharing = None, abContent = None, cbContentExpected = None, oCreds = None):
817 tdTestFileOpen.__init__(self, sFile = sFile, eSharing = eSharing, oCreds = oCreds);
818 self.abContent = abContent # type: bytearray
819 self.cbContentExpected = cbContentExpected;
820
821 def toString(self):
822 return 'check content %s (%s) %s' % (len(self.abContent), self.cbContentExpected, tdTestFileOpen.toString(self),);
823
824 def doStepsOnOpenedFile(self, fExpectSuccess, oSubTst):
825 #
826 # Call parent.
827 #
828 fRc = tdTestFileOpen.doStepsOnOpenedFile(self, fExpectSuccess, oSubTst);
829
830 #
831 # Check the expected content size.
832 #
833 if self.cbContentExpected is not None:
834 if len(self.abContent) != self.cbContentExpected:
835 fRc = reporter.error('Incorrect abContent size: %s, expected %s'
836 % (len(self.abContent), self.cbContentExpected,));
837
838 #
839 # Read the file and compare it with the content.
840 #
841 offFile = 0;
842 while True:
843 try:
844 abChunk = self.oOpenedFile.read(512*1024, 30*1000);
845 except:
846 return reporter.errorXcpt('read(512KB) @ %s' % (offFile,));
847 cbChunk = len(abChunk);
848 if cbChunk == 0:
849 if offFile != len(self.abContent):
850 fRc = reporter.error('Unexpected EOF @ %s, len(abContent)=%s' % (offFile, len(self.abContent),));
851 break;
852 if offFile + cbChunk > len(self.abContent):
853 fRc = reporter.error('File is larger than expected: at least %s bytes, expected %s bytes'
854 % (offFile + cbChunk, len(self.abContent),));
855 elif not utils.areBytesEqual(abChunk, self.abContent[offFile:(offFile + cbChunk)]):
856 fRc = reporter.error('Mismatch in range %s LB %s!' % (offFile, cbChunk,));
857 offFile += cbChunk;
858
859 return fRc;
860
861
862class tdTestSession(tdTestGuestCtrlBase):
863 """
864 Test the guest session handling.
865 """
866 def __init__(self, sUser = None, sPassword = None, sDomain = None, sSessionName = ""):
867 tdTestGuestCtrlBase.__init__(self, oCreds = tdCtxCreds(sUser, sPassword, sDomain));
868 self.sSessionName = sSessionName;
869
870 def getSessionCount(self, oVBoxMgr):
871 """
872 Helper for returning the number of currently
873 opened guest sessions of a VM.
874 """
875 if self.oGuest is None:
876 return 0;
877 try:
878 aoSession = oVBoxMgr.getArray(self.oGuest, 'sessions')
879 except:
880 reporter.errorXcpt('sSessionName: %s' % (self.sSessionName,));
881 return 0;
882 return len(aoSession);
883
884
885class tdTestSessionEx(tdTestGuestCtrlBase):
886 """
887 Test the guest session.
888 """
889 def __init__(self, aoSteps = None, enmUser = None):
890 tdTestGuestCtrlBase.__init__(self);
891 assert enmUser is None; # For later.
892 self.enmUser = enmUser;
893 self.aoSteps = aoSteps if aoSteps is not None else [];
894
895 def execute(self, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
896 """
897 Executes the test.
898 """
899 #
900 # Create a session.
901 #
902 assert self.enmUser is None; # For later.
903 self.oCreds = tdCtxCreds();
904 fRc = self.setEnvironment(oVmSession, oTxsSession, oTestVm);
905 if not fRc:
906 return False;
907 reporter.log2('%s: %s steps' % (sMsgPrefix, len(self.aoSteps),));
908 fRc, oCurSession = self.createSession(sMsgPrefix);
909 if fRc is True:
910 #
911 # Execute the tests.
912 #
913 try:
914 fRc = self.executeSteps(oTstDrv, oCurSession, sMsgPrefix);
915 except:
916 fRc = reporter.errorXcpt('%s: Unexpected exception executing test steps' % (sMsgPrefix,));
917
918 #
919 # Close the session.
920 #
921 fRc2 = self.closeSession();
922 if fRc2 is False:
923 fRc = reporter.error('%s: Session could not be closed' % (sMsgPrefix,));
924 else:
925 fRc = reporter.error('%s: Session creation failed' % (sMsgPrefix,));
926 return fRc;
927
928 def executeSteps(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
929 """
930 Executes just the steps.
931 Returns True on success, False on test failure.
932 """
933 fRc = True;
934 for (i, oStep) in enumerate(self.aoSteps):
935 fRc2 = oStep.execute(oTstDrv, oGstCtrlSession, sMsgPrefix + ', step #%d' % i);
936 if fRc2 is True:
937 pass;
938 elif fRc2 is None:
939 reporter.log('%s: skipping remaining %d steps' % (sMsgPrefix, len(self.aoSteps) - i - 1,));
940 break;
941 else:
942 fRc = False;
943 return fRc;
944
945 @staticmethod
946 def executeListTestSessions(aoTests, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
947 """
948 Works thru a list of tdTestSessionEx object.
949 """
950 fRc = True;
951 for (i, oCurTest) in enumerate(aoTests):
952 try:
953 fRc2 = oCurTest.execute(oTstDrv, oVmSession, oTxsSession, oTestVm, '%s / %#d' % (sMsgPrefix, i,));
954 if fRc2 is not True:
955 fRc = False;
956 except:
957 fRc = reporter.errorXcpt('%s: Unexpected exception executing test #%d' % (sMsgPrefix, i ,));
958
959 return (fRc, oTxsSession);
960
961
962class tdSessionStepBase(object):
963 """
964 Base class for the guest control session test steps.
965 """
966
967 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
968 """
969 Executes the test step.
970
971 Returns True on success.
972 Returns False on failure (must be reported as error).
973 Returns None if to skip the remaining steps.
974 """
975 _ = oTstDrv;
976 _ = oGstCtrlSession;
977 return reporter.error('%s: Missing execute implementation: %s' % (sMsgPrefix, self,));
978
979
980class tdStepRequireMinimumApiVer(tdSessionStepBase):
981 """
982 Special test step which will cause executeSteps to skip the remaining step
983 if the VBox API is too old:
984 """
985 def __init__(self, fpMinApiVer):
986 self.fpMinApiVer = fpMinApiVer;
987
988 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
989 """ Returns None if API version is too old, otherwise True. """
990 if oTstDrv.fpApiVer >= self.fpMinApiVer:
991 return True;
992 _ = oGstCtrlSession;
993 _ = sMsgPrefix;
994 return None; # Special return value. Don't use elsewhere.
995
996
997#
998# Scheduling Environment Changes with the Guest Control Session.
999#
1000
1001class tdStepSessionSetEnv(tdSessionStepBase):
1002 """
1003 Guest session environment: schedule putenv
1004 """
1005 def __init__(self, sVar, sValue, hrcExpected = 0):
1006 self.sVar = sVar;
1007 self.sValue = sValue;
1008 self.hrcExpected = hrcExpected;
1009
1010 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
1011 """
1012 Executes the step.
1013 Returns True on success, False on test failure.
1014 """
1015 reporter.log2('tdStepSessionSetEnv: sVar=%s sValue=%s hrcExpected=%#x' % (self.sVar, self.sValue, self.hrcExpected,));
1016 try:
1017 if oTstDrv.fpApiVer >= 5.0:
1018 oGstCtrlSession.environmentScheduleSet(self.sVar, self.sValue);
1019 else:
1020 oGstCtrlSession.environmentSet(self.sVar, self.sValue);
1021 except vbox.ComException as oXcpt:
1022 # Is this an expected failure?
1023 if vbox.ComError.equal(oXcpt, self.hrcExpected):
1024 return True;
1025 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (setenv %s=%s)'
1026 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
1027 vbox.ComError.getXcptResult(oXcpt),
1028 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
1029 self.sVar, self.sValue,));
1030 except:
1031 return reporter.errorXcpt('%s: Unexpected exception in tdStepSessionSetEnv::execute (%s=%s)'
1032 % (sMsgPrefix, self.sVar, self.sValue,));
1033
1034 # Should we succeed?
1035 if self.hrcExpected != 0:
1036 return reporter.error('%s: Expected hrcExpected=%#x, got S_OK (putenv %s=%s)'
1037 % (sMsgPrefix, self.hrcExpected, self.sVar, self.sValue,));
1038 return True;
1039
1040class tdStepSessionUnsetEnv(tdSessionStepBase):
1041 """
1042 Guest session environment: schedule unset.
1043 """
1044 def __init__(self, sVar, hrcExpected = 0):
1045 self.sVar = sVar;
1046 self.hrcExpected = hrcExpected;
1047
1048 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
1049 """
1050 Executes the step.
1051 Returns True on success, False on test failure.
1052 """
1053 reporter.log2('tdStepSessionUnsetEnv: sVar=%s hrcExpected=%#x' % (self.sVar, self.hrcExpected,));
1054 try:
1055 if oTstDrv.fpApiVer >= 5.0:
1056 oGstCtrlSession.environmentScheduleUnset(self.sVar);
1057 else:
1058 oGstCtrlSession.environmentUnset(self.sVar);
1059 except vbox.ComException as oXcpt:
1060 # Is this an expected failure?
1061 if vbox.ComError.equal(oXcpt, self.hrcExpected):
1062 return True;
1063 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (unsetenv %s)'
1064 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
1065 vbox.ComError.getXcptResult(oXcpt),
1066 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
1067 self.sVar,));
1068 except:
1069 return reporter.errorXcpt('%s: Unexpected exception in tdStepSessionUnsetEnv::execute (%s)'
1070 % (sMsgPrefix, self.sVar,));
1071
1072 # Should we succeed?
1073 if self.hrcExpected != 0:
1074 return reporter.error('%s: Expected hrcExpected=%#x, got S_OK (unsetenv %s)'
1075 % (sMsgPrefix, self.hrcExpected, self.sVar,));
1076 return True;
1077
1078class tdStepSessionBulkEnv(tdSessionStepBase):
1079 """
1080 Guest session environment: Bulk environment changes.
1081 """
1082 def __init__(self, asEnv = None, hrcExpected = 0):
1083 self.asEnv = asEnv if asEnv is not None else [];
1084 self.hrcExpected = hrcExpected;
1085
1086 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
1087 """
1088 Executes the step.
1089 Returns True on success, False on test failure.
1090 """
1091 reporter.log2('tdStepSessionBulkEnv: asEnv=%s hrcExpected=%#x' % (self.asEnv, self.hrcExpected,));
1092 try:
1093 if oTstDrv.fpApiVer >= 5.0:
1094 oTstDrv.oVBoxMgr.setArray(oGstCtrlSession, 'environmentChanges', self.asEnv);
1095 else:
1096 oTstDrv.oVBoxMgr.setArray(oGstCtrlSession, 'environment', self.asEnv);
1097 except vbox.ComException as oXcpt:
1098 # Is this an expected failure?
1099 if vbox.ComError.equal(oXcpt, self.hrcExpected):
1100 return True;
1101 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (asEnv=%s)'
1102 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
1103 vbox.ComError.getXcptResult(oXcpt),
1104 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
1105 self.asEnv,));
1106 except:
1107 return reporter.errorXcpt('%s: Unexpected exception writing the environmentChanges property (asEnv=%s).'
1108 % (sMsgPrefix, self.asEnv));
1109 return True;
1110
1111class tdStepSessionClearEnv(tdStepSessionBulkEnv):
1112 """
1113 Guest session environment: clears the scheduled environment changes.
1114 """
1115 def __init__(self):
1116 tdStepSessionBulkEnv.__init__(self);
1117
1118
1119class tdStepSessionCheckEnv(tdSessionStepBase):
1120 """
1121 Check the currently scheduled environment changes of a guest control session.
1122 """
1123 def __init__(self, asEnv = None):
1124 self.asEnv = asEnv if asEnv is not None else [];
1125
1126 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
1127 """
1128 Executes the step.
1129 Returns True on success, False on test failure.
1130 """
1131 reporter.log2('tdStepSessionCheckEnv: asEnv=%s' % (self.asEnv,));
1132
1133 #
1134 # Get the environment change list.
1135 #
1136 try:
1137 if oTstDrv.fpApiVer >= 5.0:
1138 asCurEnv = oTstDrv.oVBoxMgr.getArray(oGstCtrlSession, 'environmentChanges');
1139 else:
1140 asCurEnv = oTstDrv.oVBoxMgr.getArray(oGstCtrlSession, 'environment');
1141 except:
1142 return reporter.errorXcpt('%s: Unexpected exception reading the environmentChanges property.' % (sMsgPrefix,));
1143
1144 #
1145 # Compare it with the expected one by trying to remove each expected value
1146 # and the list anything unexpected.
1147 #
1148 fRc = True;
1149 asCopy = list(asCurEnv); # just in case asCurEnv is immutable
1150 for sExpected in self.asEnv:
1151 try:
1152 asCopy.remove(sExpected);
1153 except:
1154 fRc = reporter.error('%s: Expected "%s" to be in the resulting environment' % (sMsgPrefix, sExpected,));
1155 for sUnexpected in asCopy:
1156 fRc = reporter.error('%s: Unexpected "%s" in the resulting environment' % (sMsgPrefix, sUnexpected,));
1157
1158 if fRc is not True:
1159 reporter.log2('%s: Current environment: %s' % (sMsgPrefix, asCurEnv));
1160 return fRc;
1161
1162
1163#
1164# File system object statistics (i.e. stat()).
1165#
1166
1167class tdStepStat(tdSessionStepBase):
1168 """
1169 Stats a file system object.
1170 """
1171 def __init__(self, sPath, hrcExpected = 0, fFound = True, fFollowLinks = True, enmType = None, oTestFsObj = None):
1172 self.sPath = sPath;
1173 self.hrcExpected = hrcExpected;
1174 self.fFound = fFound;
1175 self.fFollowLinks = fFollowLinks;
1176 self.enmType = enmType if enmType is not None else vboxcon.FsObjType_File;
1177 self.cbExactSize = None;
1178 self.cbMinSize = None;
1179 self.oTestFsObj = oTestFsObj # type: testfileset.TestFsObj
1180
1181 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
1182 """
1183 Execute the test step.
1184 """
1185 reporter.log2('tdStepStat: sPath=%s enmType=%s hrcExpected=%s fFound=%s fFollowLinks=%s'
1186 % (limitString(self.sPath), self.enmType, self.hrcExpected, self.fFound, self.fFollowLinks,));
1187
1188 # Don't execute non-file tests on older VBox version.
1189 if oTstDrv.fpApiVer >= 5.0 or self.enmType == vboxcon.FsObjType_File or not self.fFound:
1190 #
1191 # Call the API.
1192 #
1193 try:
1194 if oTstDrv.fpApiVer >= 5.0:
1195 oFsInfo = oGstCtrlSession.fsObjQueryInfo(self.sPath, self.fFollowLinks);
1196 else:
1197 oFsInfo = oGstCtrlSession.fileQueryInfo(self.sPath);
1198 except vbox.ComException as oXcpt:
1199 ## @todo: The error reporting in the API just plain sucks! Most of the errors are
1200 ## VBOX_E_IPRT_ERROR and there seems to be no way to distinguish between
1201 ## non-existing files/path and a lot of other errors. Fix API and test!
1202 if not self.fFound:
1203 return True;
1204 if vbox.ComError.equal(oXcpt, self.hrcExpected): # Is this an expected failure?
1205 return True;
1206 return reporter.errorXcpt('%s: Unexpected exception for exiting path "%s" (enmType=%s, hrcExpected=%s):'
1207 % (sMsgPrefix, self.sPath, self.enmType, self.hrcExpected,));
1208 except:
1209 return reporter.errorXcpt('%s: Unexpected exception in tdStepStat::execute (%s)'
1210 % (sMsgPrefix, self.sPath,));
1211 if oFsInfo is None:
1212 return reporter.error('%s: "%s" got None instead of IFsObjInfo instance!' % (sMsgPrefix, self.sPath,));
1213
1214 #
1215 # Check type expectations.
1216 #
1217 try:
1218 enmType = oFsInfo.type;
1219 except:
1220 return reporter.errorXcpt('%s: Unexpected exception in reading "IFsObjInfo::type"' % (sMsgPrefix,));
1221 if enmType != self.enmType:
1222 return reporter.error('%s: "%s" has type %s, expected %s'
1223 % (sMsgPrefix, self.sPath, enmType, self.enmType));
1224
1225 #
1226 # Check size expectations.
1227 # Note! This is unicode string here on windows, for some reason.
1228 # long long mapping perhaps?
1229 #
1230 try:
1231 cbObject = long(oFsInfo.objectSize);
1232 except:
1233 return reporter.errorXcpt('%s: Unexpected exception in reading "IFsObjInfo::objectSize"'
1234 % (sMsgPrefix,));
1235 if self.cbExactSize is not None \
1236 and cbObject != self.cbExactSize:
1237 return reporter.error('%s: "%s" has size %s bytes, expected %s bytes'
1238 % (sMsgPrefix, self.sPath, cbObject, self.cbExactSize));
1239 if self.cbMinSize is not None \
1240 and cbObject < self.cbMinSize:
1241 return reporter.error('%s: "%s" has size %s bytes, expected as least %s bytes'
1242 % (sMsgPrefix, self.sPath, cbObject, self.cbMinSize));
1243 return True;
1244
1245class tdStepStatDir(tdStepStat):
1246 """ Checks for an existing directory. """
1247 def __init__(self, sDirPath, oTestDir = None):
1248 tdStepStat.__init__(self, sPath = sDirPath, enmType = vboxcon.FsObjType_Directory, oTestFsObj = oTestDir);
1249
1250class tdStepStatDirEx(tdStepStatDir):
1251 """ Checks for an existing directory given a TestDir object. """
1252 def __init__(self, oTestDir): # type: (testfileset.TestDir)
1253 tdStepStatDir.__init__(self, oTestDir.sPath, oTestDir);
1254
1255class tdStepStatFile(tdStepStat):
1256 """ Checks for an existing file """
1257 def __init__(self, sFilePath = None, oTestFile = None):
1258 tdStepStat.__init__(self, sPath = sFilePath, enmType = vboxcon.FsObjType_File, oTestFsObj = oTestFile);
1259
1260class tdStepStatFileEx(tdStepStatFile):
1261 """ Checks for an existing file given a TestFile object. """
1262 def __init__(self, oTestFile): # type: (testfileset.TestFile)
1263 tdStepStatFile.__init__(self, oTestFile.sPath, oTestFile);
1264
1265class tdStepStatFileSize(tdStepStat):
1266 """ Checks for an existing file of a given expected size.. """
1267 def __init__(self, sFilePath, cbExactSize = 0):
1268 tdStepStat.__init__(self, sPath = sFilePath, enmType = vboxcon.FsObjType_File);
1269 self.cbExactSize = cbExactSize;
1270
1271class tdStepStatFileNotFound(tdStepStat):
1272 """ Checks for an existing directory. """
1273 def __init__(self, sPath):
1274 tdStepStat.__init__(self, sPath = sPath, fFound = False);
1275
1276class tdStepStatPathNotFound(tdStepStat):
1277 """ Checks for an existing directory. """
1278 def __init__(self, sPath):
1279 tdStepStat.__init__(self, sPath = sPath, fFound = False);
1280
1281
1282#
1283#
1284#
1285
1286class tdTestSessionFileRefs(tdTestGuestCtrlBase):
1287 """
1288 Tests session file (IGuestFile) reference counting.
1289 """
1290 def __init__(self, cRefs = 0):
1291 tdTestGuestCtrlBase.__init__(self);
1292 self.cRefs = cRefs;
1293
1294class tdTestSessionDirRefs(tdTestGuestCtrlBase):
1295 """
1296 Tests session directory (IGuestDirectory) reference counting.
1297 """
1298 def __init__(self, cRefs = 0):
1299 tdTestGuestCtrlBase.__init__(self);
1300 self.cRefs = cRefs;
1301
1302class tdTestSessionProcRefs(tdTestGuestCtrlBase):
1303 """
1304 Tests session process (IGuestProcess) reference counting.
1305 """
1306 def __init__(self, cRefs = 0):
1307 tdTestGuestCtrlBase.__init__(self);
1308 self.cRefs = cRefs;
1309
1310class tdTestUpdateAdditions(tdTestGuestCtrlBase):
1311 """
1312 Test updating the Guest Additions inside the guest.
1313 """
1314 def __init__(self, sSrc = "", asArgs = None, afFlags = None, oCreds = None):
1315 tdTestGuestCtrlBase.__init__(self, oCreds = oCreds);
1316 self.sSrc = sSrc;
1317 self.asArgs = asArgs;
1318 self.afFlags = afFlags;
1319
1320class tdTestResult(object):
1321 """
1322 Base class for test results.
1323 """
1324 def __init__(self, fRc = False):
1325 ## The overall test result.
1326 self.fRc = fRc;
1327
1328class tdTestResultFailure(tdTestResult):
1329 """
1330 Base class for test results.
1331 """
1332 def __init__(self):
1333 tdTestResult.__init__(self, fRc = False);
1334
1335class tdTestResultSuccess(tdTestResult):
1336 """
1337 Base class for test results.
1338 """
1339 def __init__(self):
1340 tdTestResult.__init__(self, fRc = True);
1341
1342class tdTestResultDirRead(tdTestResult):
1343 """
1344 Test result for reading guest directories.
1345 """
1346 def __init__(self, fRc = False, cFiles = 0, cDirs = 0, cOthers = None):
1347 tdTestResult.__init__(self, fRc = fRc);
1348 self.cFiles = cFiles;
1349 self.cDirs = cDirs;
1350 self.cOthers = cOthers;
1351
1352class tdTestResultExec(tdTestResult):
1353 """
1354 Holds a guest process execution test result,
1355 including the exit code, status + afFlags.
1356 """
1357 def __init__(self, fRc = False, uExitStatus = 500, iExitCode = 0, sBuf = None, cbBuf = 0, cbStdOut = None, cbStdErr = None):
1358 tdTestResult.__init__(self);
1359 ## The overall test result.
1360 self.fRc = fRc;
1361 ## Process exit stuff.
1362 self.uExitStatus = uExitStatus;
1363 self.iExitCode = iExitCode;
1364 ## Desired buffer length returned back from stdout/stderr.
1365 self.cbBuf = cbBuf;
1366 ## Desired buffer result from stdout/stderr. Use with caution!
1367 self.sBuf = sBuf;
1368 self.cbStdOut = cbStdOut;
1369 self.cbStdErr = cbStdErr;
1370
1371class tdTestResultFileStat(tdTestResult):
1372 """
1373 Test result for stat'ing guest files.
1374 """
1375 def __init__(self, fRc = False,
1376 cbSize = 0, eFileType = 0):
1377 tdTestResult.__init__(self, fRc = fRc);
1378 self.cbSize = cbSize;
1379 self.eFileType = eFileType;
1380 ## @todo Add more information.
1381
1382class tdTestResultFileReadWrite(tdTestResult):
1383 """
1384 Test result for reading + writing guest directories.
1385 """
1386 def __init__(self, fRc = False,
1387 cbProcessed = 0, offFile = 0, abBuf = None):
1388 tdTestResult.__init__(self, fRc = fRc);
1389 self.cbProcessed = cbProcessed;
1390 self.offFile = offFile;
1391 self.abBuf = abBuf;
1392
1393class tdTestResultSession(tdTestResult):
1394 """
1395 Test result for guest session counts.
1396 """
1397 def __init__(self, fRc = False, cNumSessions = 0):
1398 tdTestResult.__init__(self, fRc = fRc);
1399 self.cNumSessions = cNumSessions;
1400
1401class tdDebugSettings(object):
1402 """
1403 Contains local test debug settings.
1404 """
1405 def __init__(self, sVBoxServiceExeHst = None):
1406 self.sVBoxServiceExeHst = sVBoxServiceExeHst;
1407 self.sGstVBoxServiceLogPath = '';
1408
1409class SubTstDrvAddGuestCtrl(base.SubTestDriverBase):
1410 """
1411 Sub-test driver for executing guest control (VBoxService, IGuest) tests.
1412 """
1413
1414 def __init__(self, oTstDrv):
1415 base.SubTestDriverBase.__init__(self, oTstDrv, 'add-guest-ctrl', 'Guest Control');
1416
1417 ## @todo base.TestBase.
1418 self.asTestsDef = [
1419 'debug',
1420 'session_basic', 'session_env', 'session_file_ref', 'session_dir_ref', 'session_proc_ref', 'session_reboot',
1421 'exec_basic', 'exec_timeout',
1422 'dir_create', 'dir_create_temp', 'dir_read',
1423 'file_open', 'file_remove', 'file_stat', 'file_read', 'file_write',
1424 'copy_to', 'copy_from',
1425 'update_additions',
1426 '3d'
1427 ];
1428 self.asTests = self.asTestsDef;
1429 self.fSkipKnownBugs = False;
1430 self.oTestFiles = None # type: vboxtestfileset.TestFileSet
1431 self.oDebug = tdDebugSettings();
1432 self.sPathVBoxServiceExeGst = '';
1433 self.tpAdditionsVer = ();
1434
1435 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
1436 if asArgs[iArg] == '--add-guest-ctrl-tests':
1437 iArg += 1;
1438 iNext = self.oTstDrv.requireMoreArgs(1, asArgs, iArg);
1439 if asArgs[iArg] == 'all': # Nice for debugging scripts.
1440 self.asTests = self.asTestsDef;
1441 else:
1442 self.asTests = asArgs[iArg].split(':');
1443 for s in self.asTests:
1444 if s not in self.asTestsDef:
1445 raise base.InvalidOption('The "--add-guest-ctrl-tests" value "%s" is not valid; valid values are: %s'
1446 % (s, ' '.join(self.asTestsDef)));
1447 return iNext;
1448 if asArgs[iArg] == '--add-guest-ctrl-skip-known-bugs':
1449 self.fSkipKnownBugs = True;
1450 return iArg + 1;
1451 if asArgs[iArg] == '--no-add-guest-ctrl-skip-known-bugs':
1452 self.fSkipKnownBugs = False;
1453 return iArg + 1;
1454 if asArgs[iArg] == '--add-guest-ctrl-debug-img':
1455 iArg += 1;
1456 iNext = self.oTstDrv.requireMoreArgs(1, asArgs, iArg);
1457 self.oDebug.sVBoxServiceExeHst = asArgs[iArg];
1458 return iNext;
1459 return iArg;
1460
1461 def showUsage(self):
1462 base.SubTestDriverBase.showUsage(self);
1463 reporter.log(' --add-guest-ctrl-tests <s1[:s2[:]]>');
1464 reporter.log(' Default: %s (all)' % (':'.join(self.asTestsDef)));
1465 reporter.log(' --add-guest-ctrl-skip-known-bugs');
1466 reporter.log(' Skips known bugs. Default: --no-add-guest-ctrl-skip-known-bugs');
1467 reporter.log('Debugging:');
1468 reporter.log(' --add-guest-ctrl-debug-img');
1469 reporter.log(' Sets VBoxService image to deploy for debugging');
1470 return True;
1471
1472 def testIt(self, oTestVm, oSession, oTxsSession):
1473 """
1474 Executes the test.
1475
1476 Returns fRc, oTxsSession. The latter may have changed.
1477 """
1478
1479 self.sPathVBoxServiceExeGst = oTestVm.pathJoin(self.oTstDrv.getGuestSystemAdminDir(oTestVm), 'VBoxService') \
1480 + base.exeSuff();
1481
1482 # For some tests we need know the Guest Additions version, so fetch it now.
1483 self.tpAdditionsVer = self.oTstDrv.getGuestAdditionsVersion(oSession);
1484
1485 reporter.log("Active tests: %s" % (self.asTests,));
1486
1487 # The tests. Must-succeed tests should be first.
1488 atTests = [
1489 ( True, self.prepareGuestForDebugging, None, 'Manual Debugging',),
1490 ( True, self.prepareGuestForTesting, None, 'Preparations',),
1491 ( True, self.testGuestCtrlSession, 'session_basic', 'Session Basics',),
1492 ( True, self.testGuestCtrlExec, 'exec_basic', 'Execution',),
1493 ( False, self.testGuestCtrlExecTimeout, 'exec_timeout', 'Execution Timeouts',),
1494 ( False, self.testGuestCtrlSessionEnvironment, 'session_env', 'Session Environment',),
1495 ( False, self.testGuestCtrlSessionFileRefs, 'session_file_ref', 'Session File References',),
1496 #( False, self.testGuestCtrlSessionDirRefs, 'session_dir_ref', 'Session Directory References',),
1497 ( False, self.testGuestCtrlSessionProcRefs, 'session_proc_ref', 'Session Process References',),
1498 ( False, self.testGuestCtrlDirCreate, 'dir_create', 'Creating directories',),
1499 ( False, self.testGuestCtrlDirCreateTemp, 'dir_create_temp', 'Creating temporary directories',),
1500 ( False, self.testGuestCtrlDirRead, 'dir_read', 'Reading directories',),
1501 ( False, self.testGuestCtrlCopyTo, 'copy_to', 'Copy to guest',),
1502 ( False, self.testGuestCtrlCopyFrom, 'copy_from', 'Copy from guest',),
1503 ( False, self.testGuestCtrlFileStat, 'file_stat', 'Querying file information (stat)',),
1504 ( False, self.testGuestCtrlFileOpen, 'file_open', 'File open',),
1505 ( False, self.testGuestCtrlFileRead, 'file_read', 'File read',),
1506 ( False, self.testGuestCtrlFileWrite, 'file_write', 'File write',),
1507 ( False, self.testGuestCtrlFileRemove, 'file_remove', 'Removing files',), # Destroys prepped files.
1508 ( False, self.testGuestCtrlUpdateAdditions, 'update_additions', 'Updating Guest Additions',),
1509 ( False, self.testGuestCtrl3D, '3d', '3D acceleration',),
1510 ];
1511
1512 if not self.fSkipKnownBugs:
1513 atTests.extend([
1514 ## @todo Seems to (mainly?) fail on Linux guests, primarily running with systemd as service supervisor.
1515 # Needs to be investigated and fixed.
1516 ( False, self.testGuestCtrlSessionReboot, 'session_reboot', 'Session w/ Guest Reboot',), # May zap /tmp.
1517 ]);
1518
1519 fRc = True;
1520 for fMustSucceed, fnHandler, sShortNm, sTestNm in atTests:
1521
1522 # If for whatever reason the VM object became invalid, bail out.
1523 if not oTestVm:
1524 reporter.error('Test VM object invalid (VBoxSVC or client process crashed?), aborting tests');
1525 fRc = False;
1526 break;
1527
1528 reporter.testStart(sTestNm);
1529 if sShortNm is None or sShortNm in self.asTests:
1530 # Returns (fRc, oTxsSession, oSession) - but only the first one is mandatory.
1531 aoResult = fnHandler(oSession, oTxsSession, oTestVm);
1532 if aoResult is None or isinstance(aoResult, bool):
1533 fRcTest = aoResult;
1534 else:
1535 fRcTest = aoResult[0];
1536 if len(aoResult) > 1:
1537 oTxsSession = aoResult[1];
1538 if len(aoResult) > 2:
1539 oSession = aoResult[2];
1540 assert len(aoResult) == 3;
1541 else:
1542 fRcTest = None;
1543
1544 if fRcTest is False and reporter.testErrorCount() == 0:
1545 fRcTest = reporter.error('Buggy test! Returned False w/o logging the error!');
1546 if reporter.testDone(fRcTest is None)[1] != 0:
1547 fRcTest = False;
1548 fRc = False;
1549
1550 # Stop execution if this is a must-succeed test and it failed.
1551 if fRcTest is False and fMustSucceed is True:
1552 reporter.log('Skipping any remaining tests since the previous one failed.');
1553 break;
1554
1555 # Upload VBoxService logs on failure.
1556 if reporter.testErrorCount() > 0 \
1557 and self.oDebug.sGstVBoxServiceLogPath:
1558 sVBoxServiceLogsTarGz = 'ga-vboxservice-logs-%s.tar.gz' % oTestVm.sVmName;
1559 sGstVBoxServiceLogsTarGz = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), sVBoxServiceLogsTarGz);
1560 if self.oTstDrv.txsPackFile(oSession, oTxsSession, \
1561 sGstVBoxServiceLogsTarGz, self.oDebug.sGstVBoxServiceLogPath, fIgnoreErrors = True):
1562 self.oTstDrv.txsDownloadFiles(oSession, oTxsSession, [ (sGstVBoxServiceLogsTarGz, sVBoxServiceLogsTarGz) ], \
1563 fIgnoreErrors = True);
1564
1565 return (fRc, oTxsSession);
1566
1567 def prepareGuestForDebugging(self, oSession, oTxsSession, oTestVm): # pylint: disable=unused-argument
1568 """
1569 Prepares a guest for (manual) debugging.
1570
1571 This involves copying over and invoking a the locally built VBoxService binary.
1572 """
1573
1574 if self.oDebug.sVBoxServiceExeHst is None: # If no debugging enabled, bail out.
1575 reporter.log('Skipping debugging');
1576 return True;
1577
1578 reporter.log('Preparing for debugging ...');
1579
1580 try:
1581 self.vboxServiceControl(oTxsSession, oTestVm, fStart = False);
1582
1583 self.oTstDrv.sleep(5); # Fudge factor -- wait until the service stopped.
1584
1585 reporter.log('Uploading "%s" to "%s" ...' % (self.oDebug.sVBoxServiceExeHst, self.sPathVBoxServiceExeGst));
1586 oTxsSession.syncUploadFile(self.oDebug.sVBoxServiceExeHst, self.sPathVBoxServiceExeGst);
1587
1588 if oTestVm.isLinux():
1589 oTxsSession.syncChMod(self.sPathVBoxServiceExeGst, 0o755);
1590
1591 self.vboxServiceControl(oTxsSession, oTestVm, fStart = True);
1592
1593 self.oTstDrv.sleep(5); # Fudge factor -- wait until the service is ready.
1594
1595 except:
1596 return reporter.errorXcpt('Unable to prepare for debugging');
1597
1598 return True;
1599
1600 #
1601 # VBoxService handling.
1602 #
1603 def vboxServiceControl(self, oTxsSession, oTestVm, fStart):
1604 """
1605 Controls VBoxService on the guest by starting or stopping the service.
1606 Returns success indicator.
1607 """
1608
1609 fRc = True;
1610
1611 if oTestVm.isWindows():
1612 sPathSC = os.path.join(self.oTstDrv.getGuestSystemDir(oTestVm), 'sc.exe');
1613 if oTestVm.sKind in ('WindowsNT3x', 'WindowsNT4', 'Windows2000',): # W2K too?
1614 sPathSC = os.path.join(self.oTstDrv.getGuestSystemDir(oTestVm), 'net.exe');
1615 if fStart is True:
1616 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Starting VBoxService', 30 * 1000,
1617 sPathSC, (sPathSC, 'start', 'VBoxService'));
1618 else:
1619 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Stopping VBoxService', 30 * 1000,
1620 sPathSC, (sPathSC, 'stop', 'VBoxService'));
1621 elif oTestVm.isLinux():
1622 sPathService = "/sbin/rcvboxadd-service";
1623 if fStart is True:
1624 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Starting VBoxService', 30 * 1000,
1625 sPathService, (sPathService, 'start'));
1626 else:
1627 fRc = self.oTstDrv.txsRunTest(oTxsSession, 'Stopping VBoxService', 30 * 1000,
1628 sPathService, (sPathService, 'stop'));
1629 else:
1630 reporter.log('Controlling VBoxService not supported for this guest yet');
1631
1632 return fRc;
1633
1634 def waitForGuestFacility(self, oSession, eFacilityType, sDesc,
1635 eFacilityStatus, cMsTimeout = 30 * 1000):
1636 """
1637 Waits for a guest facility to enter a certain status.
1638 By default the "Active" status is being used.
1639
1640 Returns success status.
1641 """
1642
1643 reporter.log('Waiting for Guest Additions facility "%s" to change to status %s (%dms timeout)...'
1644 % (sDesc, str(eFacilityStatus), cMsTimeout));
1645
1646 fRc = False;
1647
1648 eStatusOld = None;
1649 tsStart = base.timestampMilli();
1650 while base.timestampMilli() - tsStart < cMsTimeout:
1651 try:
1652 eStatus, _ = oSession.o.console.guest.getFacilityStatus(eFacilityType);
1653 reporter.log('Current status is %s' % (str(eStatus)));
1654 if eStatusOld is None:
1655 eStatusOld = eStatus;
1656 except:
1657 reporter.errorXcpt('Getting facility status failed');
1658 break;
1659 if eStatus != eStatusOld:
1660 reporter.log('Status changed to %s' % (str(eStatus)));
1661 eStatusOld = eStatus;
1662 if eStatus == eFacilityStatus:
1663 fRc = True;
1664 break;
1665 self.oTstDrv.sleep(5); # Do some busy waiting.
1666
1667 if not fRc:
1668 reporter.error('Waiting for Guest Additions facility "%s" timed out' % (sDesc));
1669 else:
1670 reporter.log('Guest Additions facility "%s" reached requested status %s after %dms'
1671 % (sDesc, str(eFacilityStatus), base.timestampMilli() - tsStart));
1672
1673 return fRc;
1674
1675 #
1676 # Guest test files.
1677 #
1678
1679 def prepareGuestForTesting(self, oSession, oTxsSession, oTestVm):
1680 """
1681 Prepares the VM for testing, uploading a bunch of files and stuff via TXS.
1682 Returns success indicator.
1683 """
1684 _ = oSession;
1685
1686 #
1687 # Make sure the temporary directory exists.
1688 #
1689 for sDir in [self.oTstDrv.getGuestTempDir(oTestVm), ]:
1690 if oTxsSession.syncMkDirPath(sDir, 0o777) is not True:
1691 return reporter.error('Failed to create directory "%s"!' % (sDir,));
1692
1693 # Query the TestExecService (TXS) version first to find out on what we run.
1694 fGotTxsVer = self.oTstDrv.txsVer(oSession, oTxsSession, 30 * 100, fIgnoreErrors = True);
1695
1696 # Whether to enable verbose logging for VBoxService.
1697 fEnableVerboseLogging = False;
1698
1699 # On Windows guests we always can enable verbose logging. NT4 and W2K doesn't have reg.exe nor (at least NT4) sc.exe.
1700 if oTestVm.isWindows() and oTestVm.sKind not in ('WindowsNT4', 'Windows2000',):
1701 fEnableVerboseLogging = True;
1702
1703 # Old TxS versions had a bug which caused an infinite loop when executing stuff containing "$xxx",
1704 # so check if we got the version here first and skip enabling verbose logging nonetheless if needed.
1705 if not fGotTxsVer:
1706 reporter.log('Too old TxS service running')
1707 fEnableVerboseLogging = False;
1708
1709 # Some older Linux test VMs (like tst-rhel5) don't have a pre-configured 'vbox' user.
1710 # So make sure that this user exists and has the appropriate password set. Ignore any errors.
1711 if oTestVm.isLinux():
1712 sCmdUserAdd = oTestVm.pathJoin(self.oTstDrv.getGuestSystemAdminDir(oTestVm, sPathPrefix = '/usr'), 'useradd');
1713 asArgs = [ sCmdUserAdd, '-m', 'vbox' ];
1714 self.oTstDrv.txsRunTest(oTxsSession, sCmdUserAdd, 5 * 60 * 1000, sCmdUserAdd, asArgs,
1715 fCheckSessionStatus = False);
1716 # We must supply the password in an encrypted form using chpasswd (via stdin).
1717 sCmdChPasswd = oTestVm.pathJoin(self.oTstDrv.getGuestSystemAdminDir(oTestVm, sPathPrefix = '/usr'), 'chpasswd');
1718 asArgs = [ sCmdChPasswd ];
1719 self.oTstDrv.txsRunTestStdIn(oTxsSession, sCmdChPasswd, 5 * 60 * 1000, sCmdChPasswd, asArgs,
1720 sStdIn = 'vbox:password\n', fIgnoreErrors = True);
1721
1722 #
1723 # Enable VBoxService verbose logging.
1724 #
1725 reporter.log('Enabling verbose VBoxService logging: %s' % (fEnableVerboseLogging));
1726 if fEnableVerboseLogging:
1727 self.oDebug.sGstVBoxServiceLogPath = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), "VBoxService");
1728 if oTxsSession.syncMkDirPath(self.oDebug.sGstVBoxServiceLogPath, 0o777) is not True:
1729 return reporter.error('Failed to create directory "%s"!' % (self.oDebug.sGstVBoxServiceLogPath,));
1730 sPathLogFile = oTestVm.pathJoin(self.oDebug.sGstVBoxServiceLogPath, 'VBoxService.log');
1731
1732 reporter.log('VBoxService logs will be stored in "%s"' % (self.oDebug.sGstVBoxServiceLogPath,));
1733
1734 fRestartVBoxService = False;
1735 if oTestVm.isWindows() and oTestVm.sKind not in ('WindowsNT4', 'Windows2000',):
1736 sPathRegExe = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'reg.exe');
1737 sImagePath = '%s -vvvv --logfile %s' % (self.sPathVBoxServiceExeGst, sPathLogFile);
1738 fRestartVBoxService = self.oTstDrv.txsRunTest(oTxsSession, 'Enabling VBoxService verbose logging (via registry)',
1739 30 * 1000,
1740 sPathRegExe,
1741 (sPathRegExe, 'add',
1742 'HKLM\\SYSTEM\\CurrentControlSet\\Services\\VBoxService',
1743 '/v', 'ImagePath', '/t', 'REG_SZ', '/d', sImagePath, '/f'));
1744 elif oTestVm.isLinux():
1745 sPathSed = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'sed');
1746 fRestartVBoxService = self.oTstDrv.txsRunTest(oTxsSession, 'Enabling VBoxService verbose logging', 30 * 1000,
1747 sPathSed,
1748 (sPathSed, '-i', '-e', 's/'
1749 '\\$2 \\$3'
1750 '/'
1751 '\\$2 \\$3 -vvvv --logfile \\/var\\/tmp\\/VBoxService\\/VBoxService.log'
1752 '/g',
1753 '/sbin/rcvboxadd-service'));
1754 else:
1755 reporter.log('Verbose logging for VBoxService not supported for this guest yet');
1756
1757 if fRestartVBoxService:
1758 self.vboxServiceControl(oTxsSession, oTestVm, fStart = False);
1759 self.oTstDrv.sleep(5);
1760 self.vboxServiceControl(oTxsSession, oTestVm, fStart = True);
1761 else:
1762 reporter.testStart('Waiting for VBoxService to get started');
1763 fRc = self.waitForGuestFacility(oSession, vboxcon.AdditionsFacilityType_VBoxService, "VBoxService",
1764 vboxcon.AdditionsFacilityStatus_Active);
1765 reporter.testDone();
1766 if not fRc:
1767 return False;
1768
1769 #
1770 # Generate and upload some random files and dirs to the guest.
1771 # Note! Make sure we don't run into too-long-path issues when using
1772 # the test files on the host if.
1773 #
1774 cchGst = len(self.oTstDrv.getGuestTempDir(oTestVm)) + 1 + len('addgst-1') + 1;
1775 cchHst = len(self.oTstDrv.sScratchPath) + 1 + len('copyto/addgst-1') + 1;
1776 cchMaxPath = 230;
1777 if cchHst > cchGst:
1778 cchMaxPath -= cchHst - cchGst;
1779 reporter.log('cchMaxPath=%s (cchHst=%s, cchGst=%s)' % (cchMaxPath, cchHst, cchGst,));
1780 self.oTestFiles = vboxtestfileset.TestFileSet(oTestVm,
1781 self.oTstDrv.getGuestTempDir(oTestVm), 'addgst-1',
1782 # Make sure that we use a lowest common denominator across all supported
1783 # platforms, to make testing the randomly generated file paths work
1784 # reliably.
1785 cchMaxPath = cchMaxPath, asCompatibleWith = [ ('cross') ]);
1786 return self.oTestFiles.upload(oTxsSession, self.oTstDrv);
1787
1788
1789 #
1790 # gctrlXxxx stuff.
1791 #
1792
1793 def gctrlCopyFileFrom(self, oGuestSession, oTest, fExpected):
1794 """
1795 Helper function to copy a single file from the guest to the host.
1796 """
1797
1798 # As we pass-in randomly generated file names, the source sometimes can be empty, which
1799 # in turn will result in a (correct) error by the API. Simply skip this function then.
1800 if not oTest.sSrc:
1801 reporter.log2('Skipping guest file "%s"' % (limitString(oTest.sSrc)));
1802 return fExpected;
1803
1804 #
1805 # Do the copying.
1806 #
1807 reporter.log2('Copying guest file "%s" to host "%s"' % (limitString(oTest.sSrc), limitString(oTest.sDst)));
1808 try:
1809 if self.oTstDrv.fpApiVer >= 5.0:
1810 oCurProgress = oGuestSession.fileCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.afFlags);
1811 else:
1812 oCurProgress = oGuestSession.copyFrom(oTest.sSrc, oTest.sDst, oTest.afFlags);
1813 except:
1814 reporter.maybeErrXcpt(fExpected, 'Copy from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1815 return False;
1816 if oCurProgress is None:
1817 return reporter.error('No progress object returned');
1818 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlFileCopyFrom");
1819 oProgress.wait();
1820 if not oProgress.isSuccess():
1821 oProgress.logResult(fIgnoreErrors = not fExpected);
1822 return False;
1823
1824 #
1825 # Check the result if we can.
1826 #
1827 if oTest.oSrc:
1828 assert isinstance(oTest.oSrc, testfileset.TestFile);
1829 sDst = oTest.sDst;
1830 if os.path.isdir(sDst):
1831 sDst = os.path.join(sDst, oTest.oSrc.sName);
1832 try:
1833 oFile = open(sDst, 'rb'); # pylint: disable=consider-using-with
1834 except:
1835 # Don't report expected non-existing paths / files as an error.
1836 return reporter.maybeErrXcpt(fExpected, 'open(%s) failed during verfication (file / path not found)' % (sDst,));
1837 fEqual = oTest.oSrc.equalFile(oFile);
1838 oFile.close();
1839 if not fEqual:
1840 return reporter.error('Content differs for "%s"' % (sDst,));
1841
1842 return True;
1843
1844 def __compareTestDir(self, oDir, sHostPath): # type: (testfileset.TestDir, str) -> bool
1845 """
1846 Recursively compare the content of oDir and sHostPath.
1847
1848 Returns True on success, False + error logging on failure.
1849
1850 Note! This ASSUMES that nothing else was copied to sHostPath!
1851 """
1852 #
1853 # First check out all the entries and files in the directory.
1854 #
1855 dLeftUpper = dict(oDir.dChildrenUpper);
1856 try:
1857 asEntries = os.listdir(sHostPath);
1858 except:
1859 return reporter.errorXcpt('os.listdir(%s) failed' % (sHostPath,));
1860
1861 fRc = True;
1862 for sEntry in asEntries:
1863 sEntryUpper = sEntry.upper();
1864 if sEntryUpper not in dLeftUpper:
1865 fRc = reporter.error('Unexpected entry "%s" in "%s"' % (sEntry, sHostPath,));
1866 else:
1867 oFsObj = dLeftUpper[sEntryUpper];
1868 del dLeftUpper[sEntryUpper];
1869
1870 if isinstance(oFsObj, testfileset.TestFile):
1871 sFilePath = os.path.join(sHostPath, oFsObj.sName);
1872 try:
1873 oFile = open(sFilePath, 'rb'); # pylint: disable=consider-using-with
1874 except:
1875 fRc = reporter.errorXcpt('open(%s) failed during verfication' % (sFilePath,));
1876 else:
1877 fEqual = oFsObj.equalFile(oFile);
1878 oFile.close();
1879 if not fEqual:
1880 fRc = reporter.error('Content differs for "%s"' % (sFilePath,));
1881
1882 # List missing entries:
1883 for sKey in dLeftUpper:
1884 oEntry = dLeftUpper[sKey];
1885 fRc = reporter.error('%s: Missing %s "%s" (src path: %s)'
1886 % (sHostPath, oEntry.sName,
1887 'file' if isinstance(oEntry, testfileset.TestFile) else 'directory', oEntry.sPath));
1888
1889 #
1890 # Recurse into subdirectories.
1891 #
1892 for oFsObj in oDir.aoChildren:
1893 if isinstance(oFsObj, testfileset.TestDir):
1894 fRc = self.__compareTestDir(oFsObj, os.path.join(sHostPath, oFsObj.sName)) and fRc;
1895 return fRc;
1896
1897 def gctrlCopyDirFrom(self, oGuestSession, oTest, fExpected):
1898 """
1899 Helper function to copy a directory from the guest to the host.
1900 """
1901
1902 # As we pass-in randomly generated directories, the source sometimes can be empty, which
1903 # in turn will result in a (correct) error by the API. Simply skip this function then.
1904 if not oTest.sSrc:
1905 reporter.log2('Skipping guest dir "%s"' % (limitString(oTest.sSrc)));
1906 return fExpected;
1907
1908 #
1909 # Do the copying.
1910 #
1911 reporter.log2('Copying guest dir "%s" to host "%s"' % (limitString(oTest.sSrc), limitString(oTest.sDst)));
1912 try:
1913 if self.oTstDrv.fpApiVer >= 7.0:
1914 ## @todo Make the following new flags implicit for 7.0 for now. Develop dedicated tests for this later and remove.
1915 if not oTest.afFlags:
1916 oTest.afFlags = [ vboxcon.DirectoryCopyFlag_Recursive, ];
1917 elif vboxcon.DirectoryCopyFlag_Recursive not in oTest.afFlags:
1918 oTest.afFlags.append(vboxcon.DirectoryCopyFlag_Recursive);
1919 ## @todo Ditto.
1920 if not oTest.afFlags:
1921 oTest.afFlags = [ vboxcon.DirectoryCopyFlag_FollowLinks, ];
1922 elif vboxcon.DirectoryCopyFlag_FollowLinks not in oTest.afFlags:
1923 oTest.afFlags.append(vboxcon.DirectoryCopyFlag_FollowLinks);
1924 oCurProgress = oGuestSession.directoryCopyFromGuest(oTest.sSrc, oTest.sDst, oTest.afFlags);
1925 except:
1926 reporter.maybeErrXcpt(fExpected, 'Copy dir from exception for sSrc="%s", sDst="%s":' % (oTest.sSrc, oTest.sDst,));
1927 return False;
1928 if oCurProgress is None:
1929 return reporter.error('No progress object returned');
1930
1931 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlDirCopyFrom");
1932 oProgress.wait();
1933 if not oProgress.isSuccess():
1934 oProgress.logResult(fIgnoreErrors = not fExpected);
1935 return False;
1936
1937 #
1938 # Check the result if we can.
1939 #
1940 if oTest.oSrc:
1941 assert isinstance(oTest.oSrc, testfileset.TestDir);
1942 sDst = oTest.sDst;
1943 if oTest.fIntoDst:
1944 return self.__compareTestDir(oTest.oSrc, os.path.join(sDst, oTest.oSrc.sName));
1945 oDummy = testfileset.TestDir(None, 'dummy');
1946 oDummy.aoChildren = [oTest.oSrc,]
1947 oDummy.dChildrenUpper = { oTest.oSrc.sName.upper(): oTest.oSrc, };
1948 return self.__compareTestDir(oDummy, sDst);
1949 return True;
1950
1951 def gctrlCopyFileTo(self, oGuestSession, sSrc, sDst, afFlags, fIsError):
1952 """
1953 Helper function to copy a single file from the host to the guest.
1954
1955 afFlags is either None or an array of vboxcon.DirectoryCopyFlag_Xxxx values.
1956 """
1957 reporter.log2('Copying host file "%s" to guest "%s" (flags %s)' % (limitString(sSrc), limitString(sDst), afFlags));
1958 try:
1959 if self.oTstDrv.fpApiVer >= 5.0:
1960 oCurProgress = oGuestSession.fileCopyToGuest(sSrc, sDst, afFlags);
1961 else:
1962 oCurProgress = oGuestSession.copyTo(sSrc, sDst, afFlags);
1963 except:
1964 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1965 return False;
1966
1967 if oCurProgress is None:
1968 return reporter.error('No progress object returned');
1969 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1970
1971 try:
1972 oProgress.wait();
1973 if not oProgress.isSuccess():
1974 oProgress.logResult(fIgnoreErrors = not fIsError);
1975 return False;
1976 except:
1977 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1978 return False;
1979 return True;
1980
1981 def gctrlCopyDirTo(self, oGuestSession, sSrc, sDst, afFlags, fIsError):
1982 """
1983 Helper function to copy a directory (tree) from the host to the guest.
1984
1985 afFlags is either None or an array of vboxcon.DirectoryCopyFlag_Xxxx values.
1986 """
1987 reporter.log2('Copying host directory "%s" to guest "%s" (flags %s)' % (limitString(sSrc), limitString(sDst), afFlags));
1988 try:
1989 if self.oTstDrv.fpApiVer >= 7.0:
1990 ## @todo Make the following new flags implicit for 7.0 for now. Develop dedicated tests for this later and remove.
1991 if not afFlags:
1992 afFlags = [ vboxcon.DirectoryCopyFlag_Recursive, ];
1993 elif vboxcon.DirectoryCopyFlag_Recursive not in afFlags:
1994 afFlags.append(vboxcon.DirectoryCopyFlag_Recursive);
1995 ## @todo Ditto.
1996 if not afFlags:
1997 afFlags = [vboxcon.DirectoryCopyFlag_FollowLinks,];
1998 elif vboxcon.DirectoryCopyFlag_FollowLinks not in afFlags:
1999 afFlags.append(vboxcon.DirectoryCopyFlag_FollowLinks);
2000 oCurProgress = oGuestSession.directoryCopyToGuest(sSrc, sDst, afFlags);
2001 except:
2002 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
2003 return False;
2004
2005 if oCurProgress is None:
2006 return reporter.error('No progress object returned');
2007 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
2008
2009 try:
2010 oProgress.wait();
2011 if not oProgress.isSuccess():
2012 oProgress.logResult(fIgnoreErrors = not fIsError);
2013 return False;
2014 except:
2015 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
2016 return False;
2017 return True;
2018
2019 def gctrlCreateDir(self, oTest, oRes, oGuestSession):
2020 """
2021 Helper function to create a guest directory specified in the current test.
2022 """
2023 reporter.log2('Creating directory "%s"' % (limitString(oTest.sDirectory),));
2024 try:
2025 oGuestSession.directoryCreate(oTest.sDirectory, oTest.fMode, oTest.afFlags);
2026 except:
2027 reporter.maybeErrXcpt(oRes.fRc, 'Failed to create "%s" fMode=%o afFlags=%s'
2028 % (oTest.sDirectory, oTest.fMode, oTest.afFlags,));
2029 return not oRes.fRc;
2030 if oRes.fRc is not True:
2031 return reporter.error('Did not expect to create directory "%s"!' % (oTest.sDirectory,));
2032
2033 # Check if the directory now exists.
2034 try:
2035 if self.oTstDrv.fpApiVer >= 5.0:
2036 fDirExists = oGuestSession.directoryExists(oTest.sDirectory, False);
2037 else:
2038 fDirExists = oGuestSession.directoryExists(oTest.sDirectory);
2039 except:
2040 return reporter.errorXcpt('directoryExists failed on "%s"!' % (oTest.sDirectory,));
2041 if not fDirExists:
2042 return reporter.errorXcpt('directoryExists returned False on "%s" after directoryCreate succeeded!'
2043 % (oTest.sDirectory,));
2044 return True;
2045
2046 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, fUseDirList = False, cEntriesPerRead = 0, sSubDir = None):
2047 """
2048 Helper function to recursively read a guest directory tree specified in the current test.
2049 """
2050 sDir = oTest.sDirectory;
2051 sFilter = oTest.sFilter;
2052 afFlags = oTest.afFlags;
2053 oTestVm = oTest.oCreds.oTestVm;
2054 sCurDir = oTestVm.pathJoin(sDir, sSubDir) if sSubDir else sDir;
2055
2056 fRc = True; # Be optimistic.
2057 cDirs = 0; # Number of directories read.
2058 cFiles = 0; # Number of files read.
2059 cOthers = 0; # Other files.
2060
2061 cEntriesToRead = cEntriesPerRead; # Only used when listing directories.
2062 aFsObjInfo = [];
2063
2064 # Open the directory:
2065 reporter.log2('Directory="%s", filter="%s", afFlags="%s", fUseDirList=%s, cEntriesPerRead=%d'
2066 % (limitString(sCurDir), sFilter, afFlags, fUseDirList, cEntriesPerRead));
2067 try:
2068 oCurDir = oGuestSession.directoryOpen(sCurDir, sFilter, afFlags);
2069 except:
2070 reporter.maybeErrXcpt(fIsError, 'sCurDir=%s sFilter=%s afFlags=%s' % (sCurDir, sFilter, afFlags,))
2071 return (False, 0, 0, 0);
2072
2073 # Read the directory.
2074 fDone = False;
2075 while fRc is True:
2076 reporter.log3('Reading next batch ...');
2077 aFsObjInfo = [];
2078 try:
2079 if not fUseDirList:
2080 aFsObjInfo.append(oCurDir.read());
2081 else:
2082 if not cEntriesToRead:
2083 cEntriesToRead = random.randrange(1, 32768);
2084 aFsObjInfo = oCurDir.list(cEntriesToRead);
2085 except Exception as oXcpt:
2086 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
2087 if fUseDirList:
2088 fRc = reporter.errorXcpt('Error listing directory "%s" (cEntriesToRead=%d):' % (sCurDir, cEntriesToRead));
2089 else:
2090 if self.oTstDrv.fpApiVer > 5.2:
2091 reporter.errorXcpt('Error reading directory "%s":' % (sCurDir,));
2092 else:
2093 # Unlike fileOpen, directoryOpen will not fail if the directory does not exist.
2094 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,));
2095 fRc = False;
2096 else:
2097 reporter.log2('\tNo more directory entries for "%s"' % (limitString(sCurDir),));
2098 fDone = True;
2099 break;
2100
2101 if fDone or not fRc: # Abort reading?
2102 break;
2103
2104 reporter.log3('Processing next batch (%d items)...' % (len(aFsObjInfo)));
2105 for oFsObjInfo in aFsObjInfo:
2106 try:
2107 sName = oFsObjInfo.name;
2108 eType = oFsObjInfo.type;
2109 except:
2110 fRc = reporter.errorXcpt();
2111 break;
2112
2113 if sName in ('.', '..', ):
2114 if eType != vboxcon.FsObjType_Directory:
2115 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
2116 % (sName, eType, vboxcon.FsObjType_Directory));
2117 elif eType == vboxcon.FsObjType_Directory:
2118 reporter.log2(' Directory "%s"' % limitString(oFsObjInfo.name));
2119 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError,
2120 fUseDirList, cEntriesPerRead,
2121 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName);
2122 fRc = aSubResult[0];
2123 cDirs += aSubResult[1] + 1;
2124 cFiles += aSubResult[2];
2125 cOthers += aSubResult[3];
2126 elif eType is vboxcon.FsObjType_File:
2127 reporter.log4(' File "%s"' % oFsObjInfo.name);
2128 cFiles += 1;
2129 elif eType is vboxcon.FsObjType_Symlink:
2130 reporter.log4(' Symlink "%s" -- not tested yet' % oFsObjInfo.name);
2131 cOthers += 1;
2132 elif oTestVm.isWindows() \
2133 or oTestVm.isOS2() \
2134 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock,
2135 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut):
2136 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' %
2137 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,));
2138 else:
2139 cOthers += 1;
2140
2141 # Close the directory
2142 try:
2143 oCurDir.close();
2144 except:
2145 fRc = reporter.errorXcpt('sCurDir=%s' % (sCurDir));
2146
2147 return (fRc, cDirs, cFiles, cOthers);
2148
2149 def gctrlReadDirTree2(self, oGuestSession, oDir, fUseDirList = False, cEntriesPerRead = 0):
2150 # type: (testfileset.TestDir) -> bool
2151 """
2152 Helper function to recursively read a guest directory tree specified in the current test.
2153 """
2154
2155 #
2156 # Process the directory.
2157 #
2158
2159 # Open the directory:
2160 try:
2161 oCurDir = oGuestSession.directoryOpen(oDir.sPath, '', None);
2162 except:
2163 return reporter.errorXcpt('sPath=%s' % (oDir.sPath,));
2164
2165 # Read the directory.
2166 dLeftUpper = dict(oDir.dChildrenUpper);
2167 cDot = 0;
2168 cDotDot = 0;
2169 fRc = True;
2170 cEntriesToRead = cEntriesPerRead; # Only used when listing directories.
2171 aFsObjInfo = [];
2172 while True:
2173 reporter.log3('Reading next batch ...');
2174 aFsObjInfo = [];
2175 try:
2176 if not fUseDirList:
2177 aFsObjInfo.append(oCurDir.read());
2178 else:
2179 if not cEntriesToRead:
2180 cEntriesToRead = random.randrange(1, 32768);
2181 aFsObjInfo = oCurDir.list(cEntriesToRead);
2182 except Exception as oXcpt:
2183 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
2184 if fUseDirList:
2185 fRc = reporter.errorXcpt('Error listing directory "%s" (cEntriesToRead=%d):' % \
2186 (oDir.sPath, cEntriesToRead));
2187 else:
2188 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath));
2189 else:
2190 reporter.log2('\tNo more directory entries for "%s"' % (limitString(oDir.sPath),));
2191 break;
2192
2193 reporter.log3('Processing next batch (%d items)...' % (len(aFsObjInfo)));
2194 for oFsObjInfo in aFsObjInfo:
2195 try:
2196 sName = oFsObjInfo.name;
2197 eType = oFsObjInfo.type;
2198 cbFile = oFsObjInfo.objectSize;
2199 ## @todo check further attributes.
2200 except:
2201 fRc = reporter.errorXcpt();
2202 break;
2203
2204 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment:
2205 if sName in ('.', '..', ):
2206 if eType != vboxcon.FsObjType_Directory:
2207 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
2208 % (sName, eType, vboxcon.FsObjType_Directory));
2209 if sName == '.': cDot += 1;
2210 else: cDotDot += 1;
2211 else:
2212 # Find the child and remove it from the dictionary.
2213 sNameUpper = sName.upper();
2214 oFsObj = dLeftUpper.get(sNameUpper);
2215 if oFsObj is None:
2216 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!'
2217 % (sName, oDir.sPath, eType, cbFile,));
2218 else:
2219 del dLeftUpper[sNameUpper];
2220
2221 # Check type
2222 if isinstance(oFsObj, testfileset.TestDir):
2223 if eType != vboxcon.FsObjType_Directory:
2224 fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
2225 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
2226 elif isinstance(oFsObj, testfileset.TestFile):
2227 if eType != vboxcon.FsObjType_File:
2228 fRc = reporter.error('%s: expected file (%d), got eType=%d!'
2229 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,));
2230 else:
2231 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),));
2232
2233 # Check the name.
2234 if oFsObj.sName != sName:
2235 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % \
2236 (oFsObj.sPath, oFsObj.sName, sName,));
2237
2238 # Check the size if a file.
2239 if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent:
2240 fRc = reporter.error('%s: expected size %s, got %s instead!' % \
2241 (oFsObj.sPath, oFsObj.cbContent, cbFile,));
2242
2243 ## @todo check timestamps and attributes.
2244
2245 # Close the directory
2246 try:
2247 oCurDir.close();
2248 except:
2249 fRc = reporter.errorXcpt('oDir.sPath=%s' % (oDir.sPath,));
2250
2251 # Any files left over?
2252 for sKey in dLeftUpper:
2253 oFsObj = dLeftUpper[sKey];
2254 fRc = reporter.error('%s: Was not returned! (%s)' % (oFsObj.sPath, type(oFsObj),));
2255
2256 # Check the dot and dot-dot counts.
2257 if cDot != 1:
2258 fRc = reporter.error('%s: Found %s "." entries, expected exactly 1!' % (oDir.sPath, cDot,));
2259 if cDotDot != 1:
2260 fRc = reporter.error('%s: Found %s ".." entries, expected exactly 1!' % (oDir.sPath, cDotDot,));
2261
2262 #
2263 # Recurse into subdirectories using info from oDir.
2264 #
2265 for oFsObj in oDir.aoChildren:
2266 if isinstance(oFsObj, testfileset.TestDir):
2267 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj, fUseDirList, cEntriesPerRead) and fRc;
2268
2269 return fRc;
2270
2271 def gctrlExecDoTest(self, i, oTest, oRes, oGuestSession):
2272 """
2273 Wrapper function around gctrlExecute to provide more sanity checking
2274 when needed in actual execution tests.
2275 """
2276 reporter.log('Testing #%d, cmd="%s" ...' % (i, oTest.sCmd));
2277 fRcExec = self.gctrlExecute(oTest, oGuestSession, oRes.fRc);
2278 if fRcExec == oRes.fRc:
2279 fRc = True;
2280 if fRcExec is True:
2281 # Compare exit status / code on successful process execution.
2282 if oTest.uExitStatus != oRes.uExitStatus \
2283 or oTest.iExitCode != oRes.iExitCode:
2284 fRc = reporter.error('Test #%d (%s) failed: Got exit status + code %d,%d, expected %d,%d'
2285 % (i, oTest.asArgs, oTest.uExitStatus, oTest.iExitCode,
2286 oRes.uExitStatus, oRes.iExitCode));
2287
2288 # Compare test / result buffers on successful process execution.
2289 if oTest.sBuf is not None and oRes.sBuf is not None:
2290 if not utils.areBytesEqual(oTest.sBuf, oRes.sBuf):
2291 fRc = reporter.error('Test #%d (%s) failed: Got buffer\n%s (%d bytes), expected\n%s (%d bytes)'
2292 % (i, oTest.asArgs,
2293 map(hex, map(ord, oTest.sBuf)), len(oTest.sBuf),
2294 map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf)));
2295 reporter.log2('Test #%d passed: Buffers match (%d bytes)' % (i, len(oRes.sBuf)));
2296 elif oRes.sBuf and not oTest.sBuf:
2297 fRc = reporter.error('Test #%d (%s) failed: Got no buffer data, expected\n%s (%dbytes)' %
2298 (i, oTest.asArgs, map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf),));
2299
2300 if oRes.cbStdOut is not None and oRes.cbStdOut != oTest.cbStdOut:
2301 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stdout data, expected %d'
2302 % (i, oTest.asArgs, oTest.cbStdOut, oRes.cbStdOut));
2303 if oRes.cbStdErr is not None and oRes.cbStdErr != oTest.cbStdErr:
2304 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stderr data, expected %d'
2305 % (i, oTest.asArgs, oTest.cbStdErr, oRes.cbStdErr));
2306 else:
2307 fRc = reporter.error('Test #%d (%s) failed: Got %s, expected %s' % (i, oTest.asArgs, fRcExec, oRes.fRc));
2308 return fRc;
2309
2310 def processCreateWrapper(self, oGuestSession, sCmd, asArgs, sCwd, aEnv, afFlags, timeoutMS):
2311 """
2312 Wrapepr function to deal with different flavors of the IGuestProcess::processCreate call,
2313 depending on the API version.
2314
2315 Returns oProcess object on success, None on failure.
2316 """
2317 oProcess = None;
2318
2319 reporter.log2('Executing sCmd=%s, cCwd=%s, afFlags=%s, timeoutMS=%d, asArgs=%s, asEnv=%s'
2320 % (sCmd, sCwd, afFlags, timeoutMS, limitString(asArgs), limitString(aEnv),));
2321
2322 if self.oTstDrv.fpApiVer >= 7.1 and self.oTstDrv.uRevision >= 156485:
2323 # 7.1 adds a current working directory parameter.
2324 oProcess = oGuestSession.processCreate(sCmd, asArgs, sCwd, aEnv, afFlags, timeoutMS);
2325 else:
2326 oProcess = oGuestSession.processCreate(sCmd,
2327 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2328 aEnv, afFlags, timeoutMS);
2329 return oProcess;
2330
2331 def gctrlExecute(self, oTest, oGuestSession, fIsError): # pylint: disable=too-many-statements
2332 """
2333 Helper function to execute a program on a guest, specified in the current test.
2334
2335 Note! This weirdo returns results (process exitcode and status) in oTest.
2336 """
2337 fRc = True; # Be optimistic.
2338
2339 # Reset the weird result stuff:
2340 oTest.cbStdOut = 0;
2341 oTest.cbStdErr = 0;
2342 oTest.sBuf = '';
2343 oTest.uExitStatus = 0;
2344 oTest.iExitCode = 0;
2345
2346 ## @todo Compare execution timeouts!
2347 #tsStart = base.timestampMilli();
2348
2349 try:
2350 reporter.log2('Using session user=%s, sDomain=%s, name=%s, timeout=%d'
2351 % (oGuestSession.user, oGuestSession.domain, oGuestSession.name, oGuestSession.timeout,));
2352 except:
2353 return reporter.errorXcpt();
2354
2355 #
2356 # Start the process:
2357 #
2358
2359 try:
2360 oProcess = self.processCreateWrapper(oGuestSession, oTest.sCmd, oTest.asArgs, oTest.sCwd,
2361 oTest.aEnv, oTest.afFlags, oTest.timeoutMS);
2362 except:
2363 reporter.maybeErrXcpt(fIsError, 'type=%s, asArgs=%s' % (type(oTest.asArgs), oTest.asArgs,));
2364 return False;
2365 if oProcess is None:
2366 return reporter.error('oProcess is None! (%s)' % (oTest.asArgs,));
2367
2368 #time.sleep(5); # try this if you want to see races here.
2369
2370 # Wait for the process to start properly:
2371 reporter.log2('Process start requested, waiting for start (%dms) ...' % (oTest.timeoutMS,));
2372 iPid = -1;
2373 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Start, ];
2374 try:
2375 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
2376 except:
2377 reporter.maybeErrXcpt(fIsError, 'waitforArray failed for asArgs=%s' % (oTest.asArgs,));
2378 fRc = False;
2379 else:
2380 try:
2381 eStatus = oProcess.status;
2382 iPid = oProcess.PID;
2383 except:
2384 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2385 else:
2386 reporter.log2('Wait result returned: %d, current process status is: %d' % (eWaitResult, eStatus,));
2387
2388 #
2389 # Wait for the process to run to completion if necessary.
2390 #
2391 # Note! The above eWaitResult return value can be ignored as it will
2392 # (mostly) reflect the process status anyway.
2393 #
2394 if eStatus == vboxcon.ProcessStatus_Started:
2395
2396 # What to wait for:
2397 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate, ];
2398 if vboxcon.ProcessCreateFlag_WaitForStdOut in oTest.afFlags:
2399 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdOut);
2400 if vboxcon.ProcessCreateFlag_WaitForStdErr in oTest.afFlags:
2401 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdErr);
2402 ## @todo Add vboxcon.ProcessWaitForFlag_StdIn.
2403
2404 reporter.log2('Process (PID %d) started, waiting for termination (%dms), aeWaitFor=%s ...'
2405 % (iPid, oTest.timeoutMS, aeWaitFor));
2406 acbFdOut = [0,0,0];
2407 while True:
2408 try:
2409 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
2410 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
2411 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
2412 try: oProcess.close();
2413 except: pass;
2414 break;
2415 except:
2416 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2417 break;
2418 #reporter.log2('Wait returned: %d' % (eWaitResult,));
2419
2420 # Process output:
2421 for eFdResult, iFd, sFdNm in [ (vboxcon.ProcessWaitResult_StdOut, 1, 'stdout'),
2422 (vboxcon.ProcessWaitResult_StdErr, 2, 'stderr'), ]:
2423 if eWaitResult in (eFdResult, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
2424 try:
2425 abBuf = oProcess.read(iFd, 64 * 1024, oTest.timeoutMS);
2426 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
2427 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
2428 try: oProcess.close();
2429 except: pass;
2430 except:
2431 reporter.maybeErrXcpt(fIsError, 'asArgs=%s' % (oTest.asArgs,));
2432 else:
2433 if abBuf:
2434 reporter.log2('Process (PID %d) got %d bytes of %s data (type: %s)'
2435 % (iPid, len(abBuf), sFdNm, type(abBuf)));
2436 if reporter.getVerbosity() >= 4:
2437 sBuf = '';
2438 if sys.version_info >= (2, 7):
2439 if isinstance(abBuf, memoryview): ## @todo Why is this happening?
2440 abBuf = abBuf.tobytes();
2441 sBuf = abBuf.decode("utf-8");
2442 if sys.version_info <= (2, 7):
2443 if isinstance(abBuf, buffer): # (for 3.0+) pylint: disable=undefined-variable
2444 sBuf = str(abBuf);
2445 for sLine in sBuf.splitlines():
2446 reporter.log4('%s: %s' % (sFdNm, sLine));
2447 acbFdOut[iFd] += len(abBuf);
2448 oTest.sBuf = abBuf; ## @todo Figure out how to uniform + append!
2449
2450 ## Process input (todo):
2451 #if eWaitResult in (vboxcon.ProcessWaitResult_StdIn, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
2452 # reporter.log2('Process (PID %d) needs stdin data' % (iPid,));
2453
2454 # Termination or error?
2455 if eWaitResult in (vboxcon.ProcessWaitResult_Terminate,
2456 vboxcon.ProcessWaitResult_Error,
2457 vboxcon.ProcessWaitResult_Timeout,):
2458 try: eStatus = oProcess.status;
2459 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2460 reporter.log2('Process (PID %d) reported terminate/error/timeout: %d, status: %d'
2461 % (iPid, eWaitResult, eStatus,));
2462 break;
2463
2464 # End of the wait loop.
2465 _, oTest.cbStdOut, oTest.cbStdErr = acbFdOut;
2466
2467 try: eStatus = oProcess.status;
2468 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2469 reporter.log2('Final process status (PID %d) is: %d' % (iPid, eStatus));
2470 reporter.log2('Process (PID %d) %d stdout, %d stderr' % (iPid, oTest.cbStdOut, oTest.cbStdErr));
2471
2472 #
2473 # Get the final status and exit code of the process.
2474 #
2475 try:
2476 oTest.uExitStatus = oProcess.status;
2477 oTest.iExitCode = oProcess.exitCode;
2478 except:
2479 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
2480 reporter.log2('Process (PID %d) has exit code: %d; status: %d ' % (iPid, oTest.iExitCode, oTest.uExitStatus));
2481 return fRc;
2482
2483 def testGuestCtrlSessionEnvironment(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2484 """
2485 Tests the guest session environment changes.
2486 """
2487 aoTests = [
2488 # Check basic operations.
2489 tdTestSessionEx([ # Initial environment is empty.
2490 tdStepSessionCheckEnv(),
2491 # Check clearing empty env.
2492 tdStepSessionClearEnv(),
2493 tdStepSessionCheckEnv(),
2494 # Check set.
2495 tdStepSessionSetEnv('FOO', 'BAR'),
2496 tdStepSessionCheckEnv(['FOO=BAR',]),
2497 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
2498 tdStepSessionClearEnv(),
2499 tdStepSessionCheckEnv(),
2500 # Check unset.
2501 tdStepSessionUnsetEnv('BAR'),
2502 tdStepSessionCheckEnv(['BAR']),
2503 tdStepSessionClearEnv(),
2504 tdStepSessionCheckEnv(),
2505 # Set + unset.
2506 tdStepSessionSetEnv('FOO', 'BAR'),
2507 tdStepSessionCheckEnv(['FOO=BAR',]),
2508 tdStepSessionUnsetEnv('FOO'),
2509 tdStepSessionCheckEnv(['FOO']),
2510 # Bulk environment changes (via attrib) (shall replace existing 'FOO').
2511 tdStepSessionBulkEnv( ['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
2512 tdStepSessionCheckEnv(['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
2513 ]),
2514 tdTestSessionEx([ # Check that setting the same value several times works.
2515 tdStepSessionSetEnv('FOO','BAR'),
2516 tdStepSessionCheckEnv([ 'FOO=BAR',]),
2517 tdStepSessionSetEnv('FOO','BAR2'),
2518 tdStepSessionCheckEnv([ 'FOO=BAR2',]),
2519 tdStepSessionSetEnv('FOO','BAR3'),
2520 tdStepSessionCheckEnv([ 'FOO=BAR3',]),
2521 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
2522 # Add a little unsetting to the mix.
2523 tdStepSessionSetEnv('BAR', 'BEAR'),
2524 tdStepSessionCheckEnv([ 'FOO=BAR3', 'BAR=BEAR',]),
2525 tdStepSessionUnsetEnv('FOO'),
2526 tdStepSessionCheckEnv([ 'FOO', 'BAR=BEAR',]),
2527 tdStepSessionSetEnv('FOO','BAR4'),
2528 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR',]),
2529 # The environment is case sensitive.
2530 tdStepSessionSetEnv('foo','BAR5'),
2531 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo=BAR5']),
2532 tdStepSessionUnsetEnv('foo'),
2533 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo']),
2534 ]),
2535 tdTestSessionEx([ # Bulk settings merges stuff, last entry standing.
2536 tdStepSessionBulkEnv(['FOO=bar', 'foo=bar', 'FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
2537 tdStepSessionCheckEnv(['FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
2538 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
2539 tdStepSessionBulkEnv(['2=1+1', 'FOO=doofus2', ]),
2540 tdStepSessionCheckEnv(['2=1+1', 'FOO=doofus2' ]),
2541 ]),
2542 # Invalid variable names.
2543 tdTestSessionEx([
2544 tdStepSessionSetEnv('', 'FOO', vbox.ComError.E_INVALIDARG),
2545 tdStepSessionCheckEnv(),
2546 tdStepRequireMinimumApiVer(5.0), # 4.3 is too relaxed checking input!
2547 tdStepSessionBulkEnv(['', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2548 tdStepSessionCheckEnv(),
2549 tdStepSessionSetEnv('FOO=', 'BAR', vbox.ComError.E_INVALIDARG),
2550 tdStepSessionCheckEnv(),
2551 ]),
2552 # A bit more weird keys/values.
2553 tdTestSessionEx([ tdStepSessionSetEnv('$$$', ''),
2554 tdStepSessionCheckEnv([ '$$$=',]), ]),
2555 tdTestSessionEx([ tdStepSessionSetEnv('$$$', '%%%'),
2556 tdStepSessionCheckEnv([ '$$$=%%%',]),
2557 ]),
2558 tdTestSessionEx([ tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
2559 tdStepSessionSetEnv(u'ß$%ß&', ''),
2560 tdStepSessionCheckEnv([ u'ß$%ß&=',]),
2561 ]),
2562 # Misc stuff.
2563 tdTestSessionEx([ tdStepSessionSetEnv('FOO', ''),
2564 tdStepSessionCheckEnv(['FOO=',]),
2565 ]),
2566 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
2567 tdStepSessionCheckEnv(['FOO=BAR',])
2568 ],),
2569 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
2570 tdStepSessionSetEnv('BAR', 'BAZ'),
2571 tdStepSessionCheckEnv([ 'FOO=BAR', 'BAR=BAZ',]),
2572 ]),
2573 ];
2574 # Leading '=' in the name is okay for windows guests in 6.1 and later (for driver letter CWDs).
2575 if (self.oTstDrv.fpApiVer < 6.1 and self.oTstDrv.fpApiVer >= 5.0) or not oTestVm.isWindows():
2576 aoTests.append(tdTestSessionEx([tdStepSessionSetEnv('=', '===', vbox.ComError.E_INVALIDARG),
2577 tdStepSessionCheckEnv(),
2578 tdStepSessionSetEnv('=FOO', 'BAR', vbox.ComError.E_INVALIDARG),
2579 tdStepSessionCheckEnv(),
2580 tdStepSessionBulkEnv(['=', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2581 tdStepSessionCheckEnv(),
2582 tdStepSessionBulkEnv(['=FOO', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2583 tdStepSessionCheckEnv(),
2584 tdStepSessionBulkEnv(['=D:=D:/tmp', 'foo=bar'], vbox.ComError.E_INVALIDARG),
2585 tdStepSessionCheckEnv(),
2586 tdStepSessionSetEnv('=D:', 'D:/temp', vbox.ComError.E_INVALIDARG),
2587 tdStepSessionCheckEnv(),
2588 ]));
2589 elif self.oTstDrv.fpApiVer >= 6.1 and oTestVm.isWindows():
2590 aoTests.append(tdTestSessionEx([tdStepSessionSetEnv('=D:', 'D:/tmp'),
2591 tdStepSessionCheckEnv(['=D:=D:/tmp',]),
2592 tdStepSessionBulkEnv(['=D:=D:/temp', '=FOO', 'foo=bar']),
2593 tdStepSessionCheckEnv(['=D:=D:/temp', '=FOO', 'foo=bar']),
2594 tdStepSessionUnsetEnv('=D:'),
2595 tdStepSessionCheckEnv(['=D:', '=FOO', 'foo=bar']),
2596 ]));
2597
2598 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'SessionEnv');
2599
2600 def testGuestCtrlSession(self, oSession, oTxsSession, oTestVm):
2601 """
2602 Tests the guest session handling.
2603 """
2604
2605 #
2606 # Tests:
2607 #
2608 atTests = [
2609 # Invalid parameters.
2610 [ tdTestSession(sUser = ''), tdTestResultSession() ],
2611 # User account without a passwort - forbidden.
2612 [ tdTestSession(sPassword = "" ), tdTestResultSession() ],
2613 # Various wrong credentials.
2614 # Note! Only windows cares about sDomain, the other guests ignores it.
2615 # Note! On Guest Additions < 4.3 this always succeeds because these don't
2616 # support creating dedicated sessions. Instead, guest process creation
2617 # then will fail. See note below.
2618 [ tdTestSession(sPassword = 'bar'), tdTestResultSession() ],
2619 [ tdTestSession(sUser = 'foo', sPassword = 'bar'), tdTestResultSession() ],
2620 [ tdTestSession(sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
2621 [ tdTestSession(sUser = 'foo', sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
2622 ];
2623 if oTestVm.isWindows(): # domain is ignored elsewhere.
2624 atTests.append([ tdTestSession(sDomain = 'boo'), tdTestResultSession() ]);
2625
2626 # Finally, correct credentials.
2627 atTests.append([ tdTestSession(), tdTestResultSession(fRc = True, cNumSessions = 1) ]);
2628
2629 #
2630 # Run the tests.
2631 #
2632 fRc = True;
2633 for (i, tTest) in enumerate(atTests):
2634 oCurTest = tTest[0] # type: tdTestSession
2635 oCurRes = tTest[1] # type: tdTestResult
2636
2637 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2638 if not fRc:
2639 break;
2640 reporter.log('Testing #%d, user="%s", sPassword="%s", sDomain="%s" ...'
2641 % (i, oCurTest.oCreds.sUser, oCurTest.oCreds.sPassword, oCurTest.oCreds.sDomain));
2642 sCurGuestSessionName = 'testGuestCtrlSession: Test #%d' % (i,);
2643 fRc2, oCurGuestSession = oCurTest.createSession(sCurGuestSessionName, fIsError = oCurRes.fRc);
2644
2645 # See note about < 4.3 Guest Additions above.
2646 uProtocolVersion = 2;
2647 if oCurGuestSession is not None:
2648 try:
2649 uProtocolVersion = oCurGuestSession.protocolVersion;
2650 except:
2651 fRc = reporter.errorXcpt('Test #%d' % (i,));
2652
2653 if uProtocolVersion >= 2 and fRc2 is not oCurRes.fRc:
2654 fRc = reporter.error('Test #%d failed: Session creation failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
2655
2656 if fRc2 and oCurGuestSession is None:
2657 fRc = reporter.error('Test #%d failed: no session object' % (i,));
2658 fRc2 = False;
2659
2660 if fRc2:
2661 if uProtocolVersion >= 2: # For Guest Additions < 4.3 getSessionCount() always will return 1.
2662 cCurSessions = oCurTest.getSessionCount(self.oTstDrv.oVBoxMgr);
2663 if cCurSessions != oCurRes.cNumSessions:
2664 fRc = reporter.error('Test #%d failed: Session count does not match: Got %d, expected %d'
2665 % (i, cCurSessions, oCurRes.cNumSessions));
2666 try:
2667 sObjName = oCurGuestSession.name;
2668 except:
2669 fRc = reporter.errorXcpt('Test #%d' % (i,));
2670 else:
2671 if sObjName != sCurGuestSessionName:
2672 fRc = reporter.error('Test #%d failed: Session name does not match: Got "%s", expected "%s"'
2673 % (i, sObjName, sCurGuestSessionName));
2674 fRc2 = oCurTest.closeSession();
2675 if fRc2 is False:
2676 fRc = reporter.error('Test #%d failed: Session could not be closed' % (i,));
2677
2678 if fRc is False:
2679 return (False, oTxsSession);
2680
2681 #
2682 # Multiple sessions.
2683 #
2684 cMaxGuestSessions = 31; # Maximum number of concurrent guest session allowed.
2685 # Actually, this is 32, but we don't test session 0.
2686 aoMultiSessions = {};
2687 reporter.log2('Opening multiple guest tsessions at once ...');
2688 for i in xrange(cMaxGuestSessions + 1):
2689 aoMultiSessions[i] = tdTestSession(sSessionName = 'MultiSession #%d' % (i,));
2690 fRc = aoMultiSessions[i].setEnvironment(oSession, oTxsSession, oTestVm);
2691 if not fRc:
2692 break;
2693
2694 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
2695 reporter.log2('MultiSession test #%d count is %d' % (i, cCurSessions));
2696 if cCurSessions != i:
2697 return (reporter.error('MultiSession count is %d, expected %d' % (cCurSessions, i)), oTxsSession);
2698 fRc2, _ = aoMultiSessions[i].createSession('MultiSession #%d' % (i,), i < cMaxGuestSessions);
2699 if fRc2 is not True:
2700 if i < cMaxGuestSessions:
2701 return (reporter.error('MultiSession #%d test failed' % (i,)), oTxsSession);
2702 reporter.log('MultiSession #%d exceeded concurrent guest session count, good' % (i,));
2703 break;
2704
2705 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
2706 if cCurSessions is not cMaxGuestSessions:
2707 return (reporter.error('Final session count %d, expected %d ' % (cCurSessions, cMaxGuestSessions,)), oTxsSession);
2708
2709 reporter.log2('Closing MultiSessions ...');
2710 for i in xrange(cMaxGuestSessions):
2711 # Close this session:
2712 oClosedGuestSession = aoMultiSessions[i].oGuestSession;
2713 fRc2 = aoMultiSessions[i].closeSession();
2714 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr)
2715 reporter.log2('MultiSession #%d count is %d' % (i, cCurSessions,));
2716 if fRc2 is False:
2717 fRc = reporter.error('Closing MultiSession #%d failed' % (i,));
2718 elif cCurSessions != cMaxGuestSessions - (i + 1):
2719 fRc = reporter.error('Expected %d session after closing #%d, got %d instead'
2720 % (cMaxGuestSessions - (i + 1), cCurSessions, i,));
2721 assert aoMultiSessions[i].oGuestSession is None or not fRc2;
2722 ## @todo any way to check that the session is closed other than the 'sessions' attribute?
2723
2724 # Try check that none of the remaining sessions got closed.
2725 try:
2726 aoGuestSessions = self.oTstDrv.oVBoxMgr.getArray(atTests[0][0].oGuest, 'sessions');
2727 except:
2728 return (reporter.errorXcpt('i=%d/%d' % (i, cMaxGuestSessions,)), oTxsSession);
2729 if oClosedGuestSession in aoGuestSessions:
2730 fRc = reporter.error('i=%d/%d: %s should not be in %s'
2731 % (i, cMaxGuestSessions, oClosedGuestSession, aoGuestSessions));
2732 if i + 1 < cMaxGuestSessions: # Not sure what xrange(2,2) does...
2733 for j in xrange(i + 1, cMaxGuestSessions):
2734 if aoMultiSessions[j].oGuestSession not in aoGuestSessions:
2735 fRc = reporter.error('i=%d/j=%d/%d: %s should be in %s'
2736 % (i, j, cMaxGuestSessions, aoMultiSessions[j].oGuestSession, aoGuestSessions));
2737 ## @todo any way to check that they work?
2738
2739 ## @todo Test session timeouts.
2740
2741 return (fRc, oTxsSession);
2742
2743 def testGuestCtrlSessionFileRefs(self, oSession, oTxsSession, oTestVm):
2744 """
2745 Tests the guest session file reference handling.
2746 """
2747
2748 # Find a file to play around with:
2749 sFile = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
2750
2751 # Use credential defaults.
2752 oCreds = tdCtxCreds();
2753 oCreds.applyDefaultsIfNotSet(oTestVm);
2754
2755 # Number of stale guest files to create.
2756 cStaleFiles = 10;
2757
2758 #
2759 # Start a session.
2760 #
2761 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2762 try:
2763 oGuest = oSession.o.console.guest;
2764 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionFileRefs");
2765 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2766 except:
2767 return (reporter.errorXcpt(), oTxsSession);
2768
2769 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2770 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2771 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2772 reporter.log('Session successfully started');
2773
2774 #
2775 # Open guest files and "forget" them (stale entries).
2776 # For them we don't have any references anymore intentionally.
2777 #
2778 reporter.log2('Opening stale files');
2779 fRc = True;
2780 for i in xrange(0, cStaleFiles):
2781 try:
2782 if self.oTstDrv.fpApiVer >= 5.0:
2783 oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly, vboxcon.FileOpenAction_OpenExisting, 0);
2784 else:
2785 oGuestSession.fileOpen(sFile, "r", "oe", 0);
2786 # Note: Use a timeout in the call above for not letting the stale processes
2787 # hanging around forever. This can happen if the installed Guest Additions
2788 # do not support terminating guest processes.
2789 except:
2790 fRc = reporter.errorXcpt('Opening stale file #%d failed:' % (i,));
2791 break;
2792
2793 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2794 except: fRc = reporter.errorXcpt();
2795 else:
2796 if cFiles != cStaleFiles:
2797 fRc = reporter.error('Got %d stale files, expected %d' % (cFiles, cStaleFiles));
2798
2799 if fRc is True:
2800 #
2801 # Open non-stale files and close them again.
2802 #
2803 reporter.log2('Opening non-stale files');
2804 aoFiles = [];
2805 for i in xrange(0, cStaleFiles):
2806 try:
2807 if self.oTstDrv.fpApiVer >= 5.0:
2808 oCurFile = oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly,
2809 vboxcon.FileOpenAction_OpenExisting, 0);
2810 else:
2811 oCurFile = oGuestSession.fileOpen(sFile, "r", "oe", 0);
2812 aoFiles.append(oCurFile);
2813 except:
2814 fRc = reporter.errorXcpt('Opening non-stale file #%d failed:' % (i,));
2815 break;
2816
2817 # Check the count.
2818 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2819 except: fRc = reporter.errorXcpt();
2820 else:
2821 if cFiles != cStaleFiles * 2:
2822 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles * 2));
2823
2824 # Close them.
2825 reporter.log2('Closing all non-stale files again ...');
2826 for i, oFile in enumerate(aoFiles):
2827 try:
2828 oFile.close();
2829 except:
2830 fRc = reporter.errorXcpt('Closing non-stale file #%d failed:' % (i,));
2831
2832 # Check the count again.
2833 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2834 except: fRc = reporter.errorXcpt();
2835 # Here we count the stale files (that is, files we don't have a reference
2836 # anymore for) and the opened and then closed non-stale files (that we still keep
2837 # a reference in aoFiles[] for).
2838 if cFiles != cStaleFiles:
2839 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles));
2840
2841 #
2842 # Check that all (referenced) non-stale files are now in the "closed" state.
2843 #
2844 reporter.log2('Checking statuses of all non-stale files ...');
2845 for i, oFile in enumerate(aoFiles):
2846 try:
2847 eFileStatus = aoFiles[i].status;
2848 except:
2849 fRc = reporter.errorXcpt('Checking status of file #%d failed:' % (i,));
2850 else:
2851 if eFileStatus != vboxcon.FileStatus_Closed:
2852 fRc = reporter.error('Non-stale file #%d has status %d, expected %d'
2853 % (i, eFileStatus, vboxcon.FileStatus_Closed));
2854
2855 if fRc is True:
2856 reporter.log2('All non-stale files closed');
2857
2858 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
2859 except: fRc = reporter.errorXcpt();
2860 else: reporter.log2('Final guest session file count: %d' % (cFiles,));
2861
2862 #
2863 # Now try to close the session and see what happens.
2864 # Note! Session closing is why we've been doing all the 'if fRc is True' stuff above rather than returning.
2865 #
2866 reporter.log2('Closing guest session ...');
2867 try:
2868 oGuestSession.close();
2869 except:
2870 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2871
2872 return (fRc, oTxsSession);
2873
2874 #def testGuestCtrlSessionDirRefs(self, oSession, oTxsSession, oTestVm):
2875 # """
2876 # Tests the guest session directory reference handling.
2877 # """
2878
2879 # fRc = True;
2880 # return (fRc, oTxsSession);
2881
2882 def testGuestCtrlSessionProcRefs(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements
2883 """
2884 Tests the guest session process reference handling.
2885 """
2886
2887 sShell = self.oTstDrv.getGuestSystemShell(oTestVm);
2888 asArgs = [sShell,];
2889
2890 # Use credential defaults.
2891 oCreds = tdCtxCreds();
2892 oCreds.applyDefaultsIfNotSet(oTestVm);
2893
2894 # Number of guest processes per group to create.
2895 cProcsPerGroup = 10;
2896
2897 #
2898 # Start a session.
2899 #
2900 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2901 try:
2902 oGuest = oSession.o.console.guest;
2903 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionProcRefs");
2904 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2905 except:
2906 return (reporter.errorXcpt(), oTxsSession);
2907
2908 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2909 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2910 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2911 reporter.log('Session successfully started');
2912
2913 #
2914 # Fire off forever-running processes and "forget" them (stale entries).
2915 # For them we don't have any references anymore intentionally.
2916 #
2917 reporter.log('Starting stale processes...');
2918 fRc = True;
2919 for i in xrange(0, cProcsPerGroup):
2920 try:
2921 reporter.log2('Starting stale process #%d...' % (i));
2922 self.processCreateWrapper(oGuestSession, sShell, asArgs, "", # Working directory.
2923 [], # Environment changes.
2924 [ vboxcon.ProcessCreateFlag_WaitForStdOut ], 30 * 1000);
2925 # Note: Not keeping a process reference from the created process above is intentional and part of the test!
2926
2927 # Note: Use a timeout in the call above for not letting the stale processes
2928 # hanging around forever. This can happen if the installed Guest Additions
2929 # do not support terminating guest processes.
2930 except:
2931 fRc = reporter.errorXcpt('Creating stale process #%d failed:' % (i,));
2932 break;
2933
2934 if fRc:
2935 reporter.log2('Starting stale processes successful');
2936 try: cProcs = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2937 except: fRc = reporter.errorXcpt();
2938 else:
2939 reporter.log2('Proccess count is: %d' % (cProcs));
2940 if cProcs != cProcsPerGroup:
2941 fRc = reporter.error('Got %d stale processes, expected %d (stale)' % (cProcs, cProcsPerGroup));
2942
2943 if fRc:
2944 #
2945 # Fire off non-stale processes and wait for termination.
2946 #
2947 if oTestVm.isWindows() or oTestVm.isOS2():
2948 asArgs = [ sShell, '/C', 'dir', '/S', self.oTstDrv.getGuestSystemDir(oTestVm), ];
2949 else:
2950 asArgs = [ sShell, '-c', 'ls -la ' + self.oTstDrv.getGuestSystemDir(oTestVm), ];
2951 reporter.log('Starting non-stale processes...');
2952 aoProcs = [];
2953 for i in xrange(0, cProcsPerGroup):
2954 try:
2955 reporter.log2('Starting non-stale process #%d...' % (i));
2956 oCurProc = self.processCreateWrapper(oGuestSession, sShell, asArgs,
2957 "", # Working directory.
2958 [], [], 0); # Infinite timeout.
2959 aoProcs.append(oCurProc);
2960 except:
2961 fRc = reporter.errorXcpt('Creating non-stale process #%d failed:' % (i,));
2962 break;
2963
2964 try: cProcs = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2965 except: fRc = reporter.errorXcpt();
2966 else:
2967 reporter.log2('Proccess count is: %d' % (cProcs));
2968
2969 reporter.log('Waiting for non-stale processes to terminate...');
2970 for i, oProcess in enumerate(aoProcs):
2971 try:
2972 reporter.log('Waiting for non-stale process #%d...' % (i));
2973 eWaitResult = oProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 30 * 1000);
2974 eProcessStatus = oProcess.status;
2975 except:
2976 fRc = reporter.errorXcpt('Waiting for non-stale process #%d failed:' % (i,));
2977 else:
2978 if eProcessStatus != vboxcon.ProcessStatus_TerminatedNormally:
2979 fRc = reporter.error('Waiting for non-stale processes #%d resulted in status %d, expected %d (wr=%d)'
2980 % (i, eProcessStatus, vboxcon.ProcessStatus_TerminatedNormally, eWaitResult));
2981 if fRc:
2982 reporter.log('All non-stale processes ended successfully');
2983
2984 try: cProcs = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2985 except: fRc = reporter.errorXcpt();
2986 else:
2987 reporter.log2('Proccess count is: %d' % (cProcs));
2988
2989 # Here we count the stale processes (that is, processes we don't have a reference
2990 # anymore for) and the started + ended non-stale processes (that we still keep
2991 # a reference in aoProcesses[] for).
2992 cProcsExpected = cProcsPerGroup * 2;
2993 if cProcs != cProcsExpected:
2994 fRc = reporter.error('Got %d total processes, expected %d (stale vs. non-stale)' \
2995 % (cProcs, cProcsExpected));
2996 #
2997 # Fire off non-stale blocking processes which are terminated via terminate().
2998 #
2999 if oTestVm.isWindows() or oTestVm.isOS2():
3000 sCmd = sShell;
3001 asArgs = [ sCmd, '/C', 'pause'];
3002 else:
3003 sCmd = '/usr/bin/yes';
3004 asArgs = [ sCmd ];
3005 reporter.log('Starting blocking processes...');
3006 aoProcs = [];
3007 for i in xrange(0, cProcsPerGroup):
3008 try:
3009 reporter.log2('Starting blocking process #%d...' % (i));
3010 oCurProc = self.processCreateWrapper(oGuestSession, sCmd, asArgs,
3011 "", # Working directory.
3012 [], [], 30 * 1000);
3013
3014 # Note: Use a timeout in the call above for not letting the stale processes
3015 # hanging around forever. This can happen if the installed Guest Additions
3016 # do not support terminating guest processes.
3017 try:
3018 reporter.log('Waiting for blocking process #%d getting started...' % (i));
3019 eWaitResult = oCurProc.waitForArray([ vboxcon.ProcessWaitForFlag_Start, ], 30 * 1000);
3020 eProcessStatus = oCurProc.status;
3021 except:
3022 fRc = reporter.errorXcpt('Waiting for blocking process #%d failed:' % (i,));
3023 else:
3024 if eProcessStatus != vboxcon.ProcessStatus_Started:
3025 fRc = reporter.error('Waiting for blocking processes #%d resulted in status %d, expected %d (wr=%d)'
3026 % (i, eProcessStatus, vboxcon.ProcessStatus_Started, eWaitResult));
3027 aoProcs.append(oCurProc);
3028 except:
3029 fRc = reporter.errorXcpt('Creating blocking process #%d failed:' % (i,));
3030 break;
3031
3032 if fRc:
3033 reporter.log2('Starting blocking processes successful');
3034
3035 reporter.log2('Terminating blocking processes...');
3036 for i, oProcess in enumerate(aoProcs):
3037 try:
3038 reporter.log('Terminating blocking process #%d...' % (i));
3039 oProcess.terminate();
3040 except: # Termination might not be supported, just skip and log it.
3041 reporter.logXcpt('Termination of blocking process #%d failed, skipped:' % (i,));
3042 if self.oTstDrv.fpApiVer >= 6.1: # Termination is supported since 5.2 or so.
3043 fRc = False;
3044 if fRc:
3045 reporter.log('All blocking processes were terminated successfully');
3046
3047 try: cProcs = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
3048 except: fRc = reporter.errorXcpt();
3049 else:
3050 # There still should be 20 processes because we just terminated the 10 blocking ones above.
3051 cProcsExpected = cProcsPerGroup * 2;
3052 if cProcs != cProcsExpected:
3053 fRc = reporter.error('Got %d total processes, expected %d (final)' % (cProcs, cProcsExpected));
3054 reporter.log2('Final guest session processes count: %d' % (cProcs,));
3055
3056 if not fRc:
3057 aoProcs = self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes');
3058 for i, oProc in enumerate(aoProcs):
3059 try:
3060 aoArgs = self.oTstDrv.oVBoxMgr.getArray(oProc, 'arguments');
3061 reporter.log('Process %d (\'%s\') still around, status is %d' \
3062 % (i, ' '.join([str(x) for x in aoArgs]), oProc.status));
3063 except:
3064 reporter.errorXcpt('Process lookup failed:');
3065 #
3066 # Now try to close the session and see what happens.
3067 #
3068 reporter.log('Closing guest session ...');
3069 try:
3070 oGuestSession.close();
3071 except:
3072 fRc = reporter.errorXcpt('Closing session for testing process references failed:');
3073
3074 return (fRc, oTxsSession);
3075
3076 def testGuestCtrlExec(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements
3077 """
3078 Tests the basic execution feature.
3079 """
3080
3081 # Paths:
3082 sVBoxControl = None; ## @todo Get path of installed Guest Additions. Later.
3083 sShell = self.oTstDrv.getGuestSystemShell(oTestVm);
3084 sShellOpt = '/C' if oTestVm.isWindows() or oTestVm.isOS2() else '-c';
3085 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3086 sTempDir = self.oTstDrv.getGuestTempDir(oTestVm);
3087 sFileForReading = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
3088 if oTestVm.isWindows() or oTestVm.isOS2():
3089 sImageOut = self.oTstDrv.getGuestSystemShell(oTestVm);
3090 if oTestVm.isWindows():
3091 sVBoxControl = "C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\VBoxControl.exe";
3092 else:
3093 # Really old guests (like OL 6) have their coreutils in /bin instead of /usr/bin.
3094 if self.oTstDrv.txsIsFile(oSession, oTxsSession, "/bin/ls", fIgnoreErrors = True):
3095 sImageOut = "/bin/ls";
3096 else:
3097 sImageOut = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'ls');
3098 if oTestVm.isLinux(): ## @todo check solaris and darwin.
3099 sVBoxControl = "/usr/bin/VBoxControl"; # Symlink
3100
3101 # Use credential defaults.
3102 oCreds = tdCtxCreds();
3103 oCreds.applyDefaultsIfNotSet(oTestVm);
3104
3105 atInvalid = [
3106 # Invalid parameters.
3107 [ tdTestExec(), tdTestResultExec() ],
3108 # Non-existent / invalid image.
3109 [ tdTestExec(sCmd = "non-existent"), tdTestResultExec() ],
3110 [ tdTestExec(sCmd = "non-existent2"), tdTestResultExec() ],
3111 # Use an invalid format string.
3112 [ tdTestExec(sCmd = "%$%%%&"), tdTestResultExec() ],
3113 # More stuff.
3114 [ tdTestExec(sCmd = u"ƒ‰‹ˆ÷‹¸"), tdTestResultExec() ],
3115 [ tdTestExec(sCmd = "???://!!!"), tdTestResultExec() ],
3116 [ tdTestExec(sCmd = "<>!\\"), tdTestResultExec() ],
3117 # Enable as soon as ERROR_BAD_DEVICE is implemented.
3118 #[ tdTestExec(sCmd = "CON", tdTestResultExec() ],
3119 ];
3120
3121 atExec = [];
3122 if oTestVm.isWindows() or oTestVm.isOS2():
3123 atExec += [
3124 # Basic execution.
3125 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
3126 tdTestResultExec(fRc = True) ],
3127 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sFileForReading ]),
3128 tdTestResultExec(fRc = True) ],
3129 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir + '\\nonexist.dll' ]),
3130 tdTestResultExec(fRc = True, iExitCode = 1) ],
3131 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', '/wrongparam' ]),
3132 tdTestResultExec(fRc = True, iExitCode = 1) ],
3133 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
3134 tdTestResultExec(fRc = True, iExitCode = 1) ],
3135 # StdOut.
3136 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
3137 tdTestResultExec(fRc = True) ],
3138 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdout-non-existing' ]),
3139 tdTestResultExec(fRc = True, iExitCode = 1) ],
3140 # StdErr.
3141 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
3142 tdTestResultExec(fRc = True) ],
3143 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stderr-non-existing' ]),
3144 tdTestResultExec(fRc = True, iExitCode = 1) ],
3145 # StdOut + StdErr.
3146 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
3147 tdTestResultExec(fRc = True) ],
3148 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdouterr-non-existing' ]),
3149 tdTestResultExec(fRc = True, iExitCode = 1) ],
3150 ];
3151
3152 if self.oTstDrv.isVersionEqualOrBigger(self.tpAdditionsVer, "7.1.0"):
3153 atExec.extend([
3154 # Current working directory set (VBox >= 7.1).
3155 [ tdTestExec(sCmd = sImageOut, sCwd = sTempDir, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
3156 tdTestResultExec(fRc = True) ]
3157 ]);
3158
3159 # atExec.extend([
3160 # FIXME: Failing tests.
3161 # Environment variables.
3162 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
3163 # tdTestResultExec(fRc = True, iExitCode = 1) ]
3164 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
3165 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3166 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
3167 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
3168 # aEnv = [ 'TEST_FOO=BAR' ],
3169 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3170 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
3171 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
3172 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
3173 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3174 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
3175
3176 ## @todo Create some files (or get files) we know the output size of to validate output length!
3177 ## @todo Add task which gets killed at some random time while letting the guest output something.
3178 #];
3179 else:
3180 atExec += [
3181 # Basic execution.
3182 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '-R', sSystemDir ]),
3183 tdTestResultExec(fRc = True) ],
3184 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sFileForReading ]),
3185 tdTestResultExec(fRc = True) ],
3186 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '--wrong-parameter' ]),
3187 tdTestResultExec(fRc = True, iExitCode = 2) ],
3188 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/non/existent' ]),
3189 tdTestResultExec(fRc = True, iExitCode = 2) ],
3190 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
3191 tdTestResultExec(fRc = True, iExitCode = 127) ],
3192 # StdOut.
3193 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
3194 tdTestResultExec(fRc = True) ],
3195 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdout-non-existing' ]),
3196 tdTestResultExec(fRc = True, iExitCode = 2) ],
3197 # StdErr.
3198 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
3199 tdTestResultExec(fRc = True) ],
3200 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stderr-non-existing' ]),
3201 tdTestResultExec(fRc = True, iExitCode = 2) ],
3202 # StdOut + StdErr.
3203 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
3204 tdTestResultExec(fRc = True) ],
3205 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdouterr-non-existing' ]),
3206 tdTestResultExec(fRc = True, iExitCode = 2) ],
3207 ];
3208
3209 if self.oTstDrv.isVersionEqualOrBigger(self.tpAdditionsVer, "7.1.0"):
3210 atExec.extend([
3211 # Current working directory set (VBox >= 7.1).
3212 [ tdTestExec(sCmd = sImageOut, sCwd = sTempDir, asArgs = [ sImageOut, '-R', sSystemDir ]),
3213 tdTestResultExec(fRc = True) ]
3214 ]);
3215
3216 # atExec.extend([
3217 # FIXME: Failing tests.
3218 # Environment variables.
3219 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
3220 # tdTestResultExec(fRc = True, iExitCode = 1) ]
3221 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
3222 #
3223 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3224 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
3225 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
3226 # aEnv = [ 'TEST_FOO=BAR' ],
3227 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3228 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
3229 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
3230 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
3231 # afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3232 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
3233
3234 ## @todo Create some files (or get files) we know the output size of to validate output length!
3235 ## @todo Add task which gets killed at some random time while letting the guest output something.
3236 #];
3237
3238 #
3239 #for iExitCode in xrange(0, 127):
3240 # atExec.append([ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'exit %s' % iExitCode ]),
3241 # tdTestResultExec(fRc = True, iExitCode = iExitCode) ]);
3242
3243 if sVBoxControl \
3244 and self.oTstDrv.fpApiVer >= 6.0: # Investigate with this doesn't work on (<) 5.2.
3245 # Paths with spaces on windows.
3246 atExec.append([ tdTestExec(sCmd = sVBoxControl, asArgs = [ sVBoxControl, 'version' ],
3247 afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut,
3248 vboxcon.ProcessCreateFlag_WaitForStdErr ]),
3249 tdTestResultExec(fRc = True) ]);
3250
3251 # Test very long arguments. Be careful when tweaking this to not break the tests.
3252 # Regarding paths:
3253 # - We have RTPATH_BIG_MAX (64K)
3254 # - MSDN says 32K for CreateFileW()
3255 # - On Windows, each path component must not be longer than MAX_PATH (260), see
3256 # https://docs.microsoft.com/en-us/windows/win32/fileio/filesystem-functionality-comparison#limits
3257 #
3258 # Old(er) Windows OSes tend to crash in cmd.exe, so skip this on these OSes.
3259 if self.oTstDrv.fpApiVer >= 6.1 \
3260 and oTestVm.sKind not in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
3261 sEndMarker = '--end-marker';
3262 if oTestVm.isWindows() \
3263 or oTestVm.isOS2():
3264 sCmd = sShell;
3265 else:
3266 # Really old guests (like OL 6) have their coreutils in /bin instead of /usr/bin.
3267 if self.oTstDrv.txsIsFile(oSession, oTxsSession, "/bin/echo", fIgnoreErrors = True):
3268 sCmd = "/bin/echo";
3269 else:
3270 sCmd = oTestVm.pathJoin(self.oTstDrv.getGuestSystemDir(oTestVm), 'echo');
3271
3272 for _ in xrange(0, 16):
3273 if oTestVm.isWindows() \
3274 or oTestVm.isOS2():
3275 asArgs = [ sShell, sShellOpt, "echo" ];
3276 else:
3277 asArgs = [ sCmd ];
3278
3279 # Append a random number of arguments with random length.
3280 for _ in xrange(0, self.oTestFiles.oRandom.randrange(1, 64)):
3281 asArgs.append(''.join(random.choice(string.ascii_lowercase)
3282 for _ in range(self.oTestFiles.oRandom.randrange(1, 196))));
3283
3284 asArgs.append(sEndMarker);
3285
3286 reporter.log2('asArgs=%s (%d args), type=%s' % (limitString(asArgs), len(asArgs), type(asArgs)));
3287
3288 ## @todo Check limits; on Ubuntu with 256KB IPRT returns VERR_NOT_IMPLEMENTED.
3289 # Use a higher timeout (15 min) than usual for these long checks.
3290 atExec.append([ tdTestExec(sCmd = sCmd, asArgs = asArgs,
3291 afFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut,
3292 vboxcon.ProcessCreateFlag_WaitForStdErr ],
3293 timeoutMS = 15 * 60 * 1000),
3294 tdTestResultExec(fRc = True) ]);
3295
3296 # Build up the final test array for the first batch.
3297 atTests = atInvalid + atExec;
3298
3299 #
3300 # First batch: One session per guest process.
3301 #
3302 reporter.log('One session per guest process ...');
3303 fRc = True;
3304 for (i, tTest) in enumerate(atTests):
3305 oCurTest = tTest[0] # type: tdTestExec
3306 oCurRes = tTest[1] # type: tdTestResultExec
3307 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3308 if not fRc:
3309 break;
3310 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlExec: Test #%d' % (i,));
3311 if fRc2 is not True:
3312 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3313 break;
3314 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession) and fRc;
3315 fRc = oCurTest.closeSession() and fRc;
3316
3317 reporter.log('Execution of all tests done, checking for stale sessions');
3318
3319 # No sessions left?
3320 try:
3321 aSessions = self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions');
3322 except:
3323 fRc = reporter.errorXcpt();
3324 else:
3325 cSessions = len(aSessions);
3326 if cSessions != 0:
3327 fRc = reporter.error('Found %d stale session(s), expected 0:' % (cSessions,));
3328 for (i, aSession) in enumerate(aSessions):
3329 try: reporter.log(' Stale session #%d ("%s")' % (aSession.id, aSession.name));
3330 except: reporter.errorXcpt();
3331
3332 if fRc is not True:
3333 return (fRc, oTxsSession);
3334
3335 reporter.log('Now using one guest session for all tests ...');
3336
3337 #
3338 # Second batch: One session for *all* guest processes.
3339 #
3340
3341 # Create session.
3342 reporter.log('Creating session for all tests ...');
3343 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
3344 try:
3345 oGuest = oSession.o.console.guest;
3346 oCurGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain,
3347 'testGuestCtrlExec: One session for all tests');
3348 except:
3349 return (reporter.errorXcpt(), oTxsSession);
3350
3351 try:
3352 eWaitResult = oCurGuestSession.waitForArray(aeWaitFor, 30 * 1000);
3353 except:
3354 fRc = reporter.errorXcpt('Waiting for guest session to start failed:');
3355 else:
3356 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3357 fRc = reporter.error('Session did not start successfully, returned wait result: %d' % (eWaitResult,));
3358 else:
3359 reporter.log('Session successfully started');
3360
3361 # Do the tests within this session.
3362 for (i, tTest) in enumerate(atTests):
3363 oCurTest = tTest[0] # type: tdTestExec
3364 oCurRes = tTest[1] # type: tdTestResultExec
3365
3366 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3367 if not fRc:
3368 break;
3369 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
3370 if fRc is False:
3371 break;
3372
3373 # Close the session.
3374 reporter.log2('Closing guest session ...');
3375 try:
3376 oCurGuestSession.close();
3377 oCurGuestSession = None;
3378 except:
3379 fRc = reporter.errorXcpt('Closing guest session failed:');
3380
3381 # No sessions left?
3382 reporter.log('Execution of all tests done, checking for stale sessions again');
3383 try: cSessions = len(self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions'));
3384 except: fRc = reporter.errorXcpt();
3385 else:
3386 if cSessions != 0:
3387 fRc = reporter.error('Found %d stale session(s), expected 0' % (cSessions,));
3388 return (fRc, oTxsSession);
3389
3390 def threadForTestGuestCtrlSessionReboot(self, oGuestProcess):
3391 """
3392 Thread routine which waits for the stale guest process getting terminated (or some error)
3393 while the main test routine reboots the guest. It then compares the expected guest process result
3394 and logs an error if appropriate.
3395 """
3396 reporter.log('Waiting for process to get terminated at reboot ...');
3397 try:
3398 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate ], 5 * 60 * 1000);
3399 except:
3400 return reporter.errorXcpt('waitForArray failed');
3401 try:
3402 eStatus = oGuestProcess.status
3403 except:
3404 return reporter.errorXcpt('failed to get status (wait result %d)' % (eWaitResult,));
3405
3406 if eWaitResult == vboxcon.ProcessWaitResult_Terminate and eStatus == vboxcon.ProcessStatus_Down:
3407 reporter.log('Stale process was correctly terminated (status: down)');
3408 return True;
3409
3410 return reporter.error('Process wait across reboot failed: eWaitResult=%d, expected %d; eStatus=%d, expected %d'
3411 % (eWaitResult, vboxcon.ProcessWaitResult_Terminate, eStatus, vboxcon.ProcessStatus_Down,));
3412
3413 def testGuestCtrlSessionReboot(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3414 """
3415 Tests guest object notifications when a guest gets rebooted / shutdown.
3416
3417 These notifications gets sent from the guest sessions in order to make API clients
3418 aware of guest session changes.
3419
3420 To test that we create a stale guest process and trigger a reboot of the guest.
3421 """
3422
3423 ## @todo backport fixes to 6.0 and maybe 5.2
3424 if self.oTstDrv.fpApiVer <= 6.0:
3425 reporter.log('Skipping: Required fixes not yet backported!');
3426 return None;
3427
3428 # Use credential defaults.
3429 oCreds = tdCtxCreds();
3430 oCreds.applyDefaultsIfNotSet(oTestVm);
3431
3432 fRebooted = False;
3433 fRc = True;
3434
3435 #
3436 # Start a session.
3437 #
3438 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
3439 try:
3440 oGuest = oSession.o.console.guest;
3441 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionReboot");
3442 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
3443 except:
3444 return (reporter.errorXcpt(), oTxsSession);
3445
3446 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
3447 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3448 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
3449 reporter.log('Session successfully started');
3450
3451 #
3452 # Create a process.
3453 #
3454 # That process will also be used later to see if the session cleanup worked upon reboot.
3455 #
3456 sImage = self.oTstDrv.getGuestSystemShell(oTestVm);
3457 asArgs = [ sImage, ];
3458 aEnv = [];
3459 afFlags = [];
3460 try:
3461 oGuestProcess = self.processCreateWrapper(oGuestSession, sImage, asArgs,
3462 "", # Working directory.
3463 aEnv, afFlags, 30 * 1000);
3464 except:
3465 fRc = reporter.error('Failed to start shell process (%s)' % (sImage,));
3466 else:
3467 try:
3468 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3469 except:
3470 fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
3471 else:
3472 # Check the result and state:
3473 try: eStatus = oGuestProcess.status;
3474 except: fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
3475 else:
3476 reporter.log2('Starting process wait result returned: %d; Process status is: %d' % (eWaitResult, eStatus,));
3477 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3478 fRc = reporter.error('wait for ProcessWaitForFlag_Start failed: %d, expected %d (Start)'
3479 % (eWaitResult, vboxcon.ProcessWaitResult_Start,));
3480 elif eStatus != vboxcon.ProcessStatus_Started:
3481 fRc = reporter.error('Unexpected process status after startup: %d, wanted %d (Started)'
3482 % (eStatus, vboxcon.ProcessStatus_Started,));
3483 else:
3484 # Create a thread that waits on the process to terminate
3485 reporter.log('Creating reboot thread ...');
3486 oThreadReboot = threading.Thread(target = self.threadForTestGuestCtrlSessionReboot,
3487 args = (oGuestProcess,),
3488 name = 'threadForTestGuestCtrlSessionReboot');
3489 oThreadReboot.setDaemon(True); # pylint: disable=deprecated-method
3490 oThreadReboot.start();
3491
3492 # Do the reboot.
3493 reporter.log('Rebooting guest and reconnecting TXS ...');
3494 (oSession, oTxsSession) = self.oTstDrv.txsRebootAndReconnectViaTcp(oSession, oTxsSession,
3495 cMsTimeout = 3 * 60000);
3496 if oSession \
3497 and oTxsSession:
3498 # Set reboot flag (needed later for session closing).
3499 fRebooted = True;
3500 else:
3501 reporter.error('Rebooting via TXS failed');
3502 try: oGuestProcess.terminate();
3503 except: reporter.logXcpt();
3504 fRc = False;
3505
3506 reporter.log('Waiting for thread to finish ...');
3507 oThreadReboot.join();
3508
3509 # Check that the guest session now still has the formerly guest process object created above,
3510 # but with the "down" status now (because of guest reboot).
3511 try:
3512 aoGuestProcs = self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes');
3513 if len(aoGuestProcs) == 1:
3514 enmProcSts = aoGuestProcs[0].status;
3515 if enmProcSts != vboxcon.ProcessStatus_Down:
3516 fRc = reporter.error('Old guest process (before reboot) has status %d, expected %s' \
3517 % (enmProcSts, vboxcon.ProcessStatus_Down));
3518 else:
3519 fRc = reporter.error('Old guest session (before reboot) has %d processes registered, expected 1' \
3520 % (len(aoGuestProcs)));
3521 except:
3522 fRc = reporter.errorXcpt();
3523 #
3524 # Try make sure we don't leave with a stale process on failure.
3525 #
3526 try: oGuestProcess.terminate();
3527 except: reporter.logXcpt();
3528
3529 #
3530 # Close the session.
3531 #
3532 reporter.log2('Closing guest session ...');
3533 try:
3534 oGuestSession.close();
3535 except:
3536 # Closing the guest session will fail when the guest reboot has been triggered,
3537 # as the session object will be cleared on a guest reboot.
3538 if fRebooted:
3539 reporter.logXcpt('Closing guest session failed, good (guest rebooted)');
3540 else: # ... otherwise this (still) should succeed. Report so if it doesn't.
3541 reporter.errorXcpt('Closing guest session failed');
3542
3543 return (fRc, oTxsSession);
3544
3545 def testGuestCtrlExecTimeout(self, oSession, oTxsSession, oTestVm):
3546 """
3547 Tests handling of timeouts of started guest processes.
3548 """
3549
3550 sShell = self.oTstDrv.getGuestSystemShell(oTestVm);
3551
3552 # Use credential defaults.
3553 oCreds = tdCtxCreds();
3554 oCreds.applyDefaultsIfNotSet(oTestVm);
3555
3556 #
3557 # Create a session.
3558 #
3559 try:
3560 oGuest = oSession.o.console.guest;
3561 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlExecTimeout");
3562 eWaitResult = oGuestSession.waitForArray([ vboxcon.GuestSessionWaitForFlag_Start, ], 30 * 1000);
3563 except:
3564 return (reporter.errorXcpt(), oTxsSession);
3565
3566 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
3567 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
3568 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
3569 reporter.log('Session successfully started');
3570
3571 #
3572 # Create a process which never terminates and should timeout when
3573 # waiting for termination.
3574 #
3575 fRc = True;
3576 try:
3577 oCurProcess = self.processCreateWrapper(oGuestSession, sShell, [ sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
3578 "", # Working directory.
3579 [], [], 30 * 1000);
3580 except:
3581 fRc = reporter.errorXcpt();
3582 else:
3583 reporter.log('Waiting for process 1 being started ...');
3584 try:
3585 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3586 except:
3587 fRc = reporter.errorXcpt();
3588 else:
3589 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3590 fRc = reporter.error('Waiting for process 1 to start failed, got status %d' % (eWaitResult,));
3591 else:
3592 for msWait in (1, 32, 2000,):
3593 reporter.log('Waiting for process 1 to time out within %sms ...' % (msWait,));
3594 try:
3595 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], msWait);
3596 except:
3597 fRc = reporter.errorXcpt();
3598 break;
3599 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
3600 fRc = reporter.error('Waiting for process 1 did not time out in %sms as expected: %d'
3601 % (msWait, eWaitResult,));
3602 break;
3603 reporter.log('Waiting for process 1 timed out in %u ms, good' % (msWait,));
3604
3605 try:
3606 oCurProcess.terminate();
3607 except:
3608 reporter.errorXcpt();
3609 oCurProcess = None;
3610
3611 #
3612 # Create another process that doesn't terminate, but which will be killed by VBoxService
3613 # because it ran out of execution time (3 seconds).
3614 #
3615 try:
3616 oCurProcess = self.processCreateWrapper(oGuestSession, sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
3617 "", # Working directory.
3618 [], [], 3 * 1000);
3619 except:
3620 fRc = reporter.errorXcpt();
3621 else:
3622 reporter.log('Waiting for process 2 being started ...');
3623 try:
3624 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
3625 except:
3626 fRc = reporter.errorXcpt();
3627 else:
3628 if eWaitResult != vboxcon.ProcessWaitResult_Start:
3629 fRc = reporter.error('Waiting for process 2 to start failed, got status %d' % (eWaitResult,));
3630 else:
3631 reporter.log('Waiting for process 2 to get killed for running out of execution time ...');
3632 try:
3633 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 15 * 1000);
3634 except:
3635 fRc = reporter.errorXcpt();
3636 else:
3637 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
3638 fRc = reporter.error('Waiting for process 2 did not time out when it should, got wait result %d'
3639 % (eWaitResult,));
3640 else:
3641 reporter.log('Waiting for process 2 did not time out, good: %s' % (eWaitResult,));
3642 try:
3643 eStatus = oCurProcess.status;
3644 except:
3645 fRc = reporter.errorXcpt();
3646 else:
3647 if eStatus != vboxcon.ProcessStatus_TimedOutKilled:
3648 fRc = reporter.error('Status of process 2 wrong; excepted %d, got %d'
3649 % (vboxcon.ProcessStatus_TimedOutKilled, eStatus));
3650 else:
3651 reporter.log('Status of process 2 is TimedOutKilled (%d) is it should be.'
3652 % (vboxcon.ProcessStatus_TimedOutKilled,));
3653 try:
3654 oCurProcess.terminate();
3655 except:
3656 reporter.logXcpt();
3657 oCurProcess = None;
3658
3659 #
3660 # Clean up the session.
3661 #
3662 try:
3663 oGuestSession.close();
3664 except:
3665 fRc = reporter.errorXcpt();
3666
3667 return (fRc, oTxsSession);
3668
3669 def testGuestCtrlDirCreate(self, oSession, oTxsSession, oTestVm):
3670 """
3671 Tests creation of guest directories.
3672 """
3673
3674 sScratch = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'testGuestCtrlDirCreate');
3675
3676 atTests = [
3677 # Invalid stuff.
3678 [ tdTestDirCreate(sDirectory = '' ), tdTestResultFailure() ],
3679 # More unusual stuff.
3680 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '.') ), tdTestResultFailure() ],
3681 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '..') ), tdTestResultFailure() ],
3682 [ tdTestDirCreate(sDirectory = '..' ), tdTestResultFailure() ],
3683 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
3684 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
3685 [ tdTestDirCreate(sDirectory = '/' ), tdTestResultFailure() ],
3686 [ tdTestDirCreate(sDirectory = '/..' ), tdTestResultFailure() ],
3687 [ tdTestDirCreate(sDirectory = '/../' ), tdTestResultFailure() ],
3688 ];
3689 if oTestVm.isWindows() or oTestVm.isOS2():
3690 atTests.extend([
3691 [ tdTestDirCreate(sDirectory = 'C:\\' ), tdTestResultFailure() ],
3692 [ tdTestDirCreate(sDirectory = 'C:\\..' ), tdTestResultFailure() ],
3693 [ tdTestDirCreate(sDirectory = 'C:\\..\\' ), tdTestResultFailure() ],
3694 [ tdTestDirCreate(sDirectory = 'C:/' ), tdTestResultFailure() ],
3695 [ tdTestDirCreate(sDirectory = 'C:/.' ), tdTestResultFailure() ],
3696 [ tdTestDirCreate(sDirectory = 'C:/./' ), tdTestResultFailure() ],
3697 [ tdTestDirCreate(sDirectory = 'C:/..' ), tdTestResultFailure() ],
3698 [ tdTestDirCreate(sDirectory = 'C:/../' ), tdTestResultFailure() ],
3699 [ tdTestDirCreate(sDirectory = '\\\\uncrulez\\foo' ), tdTestResultFailure() ],
3700 ]);
3701 atTests.extend([
3702 # Existing directories and files.
3703 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemDir(oTestVm) ), tdTestResultFailure() ],
3704 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemShell(oTestVm) ), tdTestResultFailure() ],
3705 [ tdTestDirCreate(sDirectory = self.oTstDrv.getGuestSystemFileForReading(oTestVm) ), tdTestResultFailure() ],
3706 # Creating directories.
3707 [ tdTestDirCreate(sDirectory = sScratch ), tdTestResultSuccess() ],
3708 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
3709 afFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
3710 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
3711 afFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
3712 # Try format strings as directories.
3713 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo%sbar%sbaz%d' )), tdTestResultSuccess() ],
3714 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, '%f%%boo%%bar%RI32' )), tdTestResultSuccess() ],
3715 # Long random names.
3716 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(36, 28))),
3717 tdTestResultSuccess() ],
3718 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(140, 116))),
3719 tdTestResultSuccess() ],
3720 # Too long names. ASSUMES a guests has a 255 filename length limitation.
3721 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
3722 tdTestResultFailure() ],
3723 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
3724 tdTestResultFailure() ],
3725 # Missing directory in path.
3726 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo1', 'bar') ), tdTestResultFailure() ],
3727 ]);
3728
3729 fRc = True;
3730 for (i, tTest) in enumerate(atTests):
3731 oCurTest = tTest[0] # type: tdTestDirCreate
3732 oCurRes = tTest[1] # type: tdTestResult
3733 reporter.log('Testing #%d, sDirectory="%s" ...' % (i, limitString(oCurTest.sDirectory),));
3734
3735 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3736 if not fRc:
3737 break;
3738 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreate: Test #%d' % (i,));
3739 if fRc is False:
3740 return reporter.error('Test #%d failed: Could not create session' % (i,));
3741
3742 fRc = self.gctrlCreateDir(oCurTest, oCurRes, oCurGuestSession);
3743
3744 fRc = oCurTest.closeSession() and fRc;
3745 if fRc is False:
3746 fRc = reporter.error('Test #%d failed' % (i,));
3747
3748 return (fRc, oTxsSession);
3749
3750 def testGuestCtrlDirCreateTemp(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3751 """
3752 Tests creation of temporary directories.
3753 """
3754
3755 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3756 atTests = [
3757 # Invalid stuff (template must have one or more trailin 'X'es (upper case only), or a cluster of three or more).
3758 [ tdTestDirCreateTemp(sDirectory = ''), tdTestResultFailure() ],
3759 [ tdTestDirCreateTemp(sDirectory = sSystemDir, fMode = 1234), tdTestResultFailure() ],
3760 [ tdTestDirCreateTemp(sTemplate = 'xXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3761 [ tdTestDirCreateTemp(sTemplate = 'xxx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3762 [ tdTestDirCreateTemp(sTemplate = 'XXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
3763 [ tdTestDirCreateTemp(sTemplate = 'bar', sDirectory = 'whatever', fMode = 0o700), tdTestResultFailure() ],
3764 [ tdTestDirCreateTemp(sTemplate = 'foo', sDirectory = 'it is not used', fMode = 0o700), tdTestResultFailure() ],
3765 [ tdTestDirCreateTemp(sTemplate = 'X,so', sDirectory = 'pointless test', fMode = 0o700), tdTestResultFailure() ],
3766 # Non-existing stuff.
3767 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX',
3768 sDirectory = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'non', 'existing')),
3769 tdTestResultFailure() ],
3770 # Working stuff:
3771 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3772 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3773 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
3774 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3775 tdTestResultFailure() ],
3776 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3777 tdTestResultFailure() ],
3778 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3779 tdTestResultFailure() ],
3780 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm)),
3781 tdTestResultFailure() ],
3782 ];
3783
3784 if self.oTstDrv.fpApiVer >= 7.0:
3785 # Weird mode set.
3786 atTests.extend([
3787 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o42333),
3788 tdTestResultFailure() ]
3789 ]);
3790 # Same as working stuff above, but with a different mode set.
3791 atTests.extend([
3792 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3793 tdTestResultFailure() ],
3794 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3795 tdTestResultFailure() ],
3796 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3797 tdTestResultFailure() ],
3798 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3799 tdTestResultFailure() ],
3800 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3801 tdTestResultFailure() ],
3802 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3803 tdTestResultFailure() ],
3804 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fMode = 0o777),
3805 tdTestResultFailure() ]
3806 ]);
3807 # Same as working stuff above, but with secure mode set.
3808 atTests.extend([
3809 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fSecure = True),
3810 tdTestResultFailure() ],
3811 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fSecure = True),
3812 tdTestResultFailure() ],
3813 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fSecure = True),
3814 tdTestResultFailure() ],
3815 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm), fSecure = True),
3816 tdTestResultFailure() ],
3817 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm),
3818 fSecure = True),
3819 tdTestResultFailure() ],
3820 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm),
3821 fSecure = True),
3822 tdTestResultFailure() ],
3823 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.oTstDrv.getGuestTempDir(oTestVm),
3824 fSecure = True),
3825 tdTestResultFailure() ]
3826 ]);
3827
3828 fRc = True;
3829 for (i, tTest) in enumerate(atTests):
3830 oCurTest = tTest[0] # type: tdTestDirCreateTemp
3831 oCurRes = tTest[1] # type: tdTestResult
3832 reporter.log('Testing #%d, sTemplate="%s", fMode=%#o, path="%s", secure="%s" ...' %
3833 (i, oCurTest.sTemplate, oCurTest.fMode, oCurTest.sDirectory, oCurTest.fSecure));
3834
3835 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3836 if not fRc:
3837 break;
3838 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreateTemp: Test #%d' % (i,));
3839 if fRc is False:
3840 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3841 break;
3842
3843 sDirTemp = '';
3844 try:
3845 sDirTemp = oCurGuestSession.directoryCreateTemp(oCurTest.sTemplate, oCurTest.fMode,
3846 oCurTest.sDirectory, oCurTest.fSecure);
3847 except:
3848 if oCurRes.fRc is True:
3849 fRc = reporter.errorXcpt('Creating temp directory "%s" failed:' % (oCurTest.sDirectory,));
3850 else:
3851 reporter.logXcpt('Creating temp directory "%s" failed expectedly, skipping:' % (oCurTest.sDirectory,));
3852 else:
3853 reporter.log2('Temporary directory is: "%s"' % (limitString(sDirTemp),));
3854 if not sDirTemp:
3855 fRc = reporter.error('Resulting directory is empty!');
3856 else:
3857 ## @todo This does not work for some unknown reason.
3858 #try:
3859 # if self.oTstDrv.fpApiVer >= 5.0:
3860 # fExists = oCurGuestSession.directoryExists(sDirTemp, False);
3861 # else:
3862 # fExists = oCurGuestSession.directoryExists(sDirTemp);
3863 #except:
3864 # fRc = reporter.errorXcpt('sDirTemp=%s' % (sDirTemp,));
3865 #else:
3866 # if fExists is not True:
3867 # fRc = reporter.error('Test #%d failed: Temporary directory "%s" does not exists (%s)'
3868 # % (i, sDirTemp, fExists));
3869 try:
3870 oFsObjInfo = oCurGuestSession.fsObjQueryInfo(sDirTemp, False);
3871 eType = oFsObjInfo.type;
3872 except:
3873 fRc = reporter.errorXcpt('sDirTemp="%s"' % (sDirTemp,));
3874 else:
3875 reporter.log2('%s: eType=%s (dir=%d)' % (limitString(sDirTemp), eType, vboxcon.FsObjType_Directory,));
3876 if eType != vboxcon.FsObjType_Directory:
3877 fRc = reporter.error('Temporary directory "%s" not created as a directory: eType=%d'
3878 % (sDirTemp, eType));
3879 fRc = oCurTest.closeSession() and fRc;
3880 return (fRc, oTxsSession);
3881
3882 def testGuestCtrlDirRead(self, oSession, oTxsSession, oTestVm):
3883 """
3884 Tests opening and reading (enumerating) guest directories.
3885 """
3886
3887 sSystemDir = self.oTstDrv.getGuestSystemDir(oTestVm);
3888 atTests = [
3889 # Invalid stuff.
3890 [ tdTestDirRead(sDirectory = ''), tdTestResultDirRead() ],
3891 [ tdTestDirRead(sDirectory = sSystemDir, afFlags = [ 1234 ]), tdTestResultDirRead() ],
3892 [ tdTestDirRead(sDirectory = sSystemDir, sFilter = '*.foo'), tdTestResultDirRead() ],
3893 # Non-existing stuff.
3894 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'really-no-such-subdir')), tdTestResultDirRead() ],
3895 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'non', 'existing')), tdTestResultDirRead() ],
3896 ];
3897
3898 if oTestVm.isWindows() or oTestVm.isOS2():
3899 atTests.extend([
3900 # More unusual stuff.
3901 [ tdTestDirRead(sDirectory = 'z:\\'), tdTestResultDirRead() ],
3902 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
3903 ]);
3904
3905 # Read the system directory (ASSUMES at least 5 files in it):
3906 # Windows 7+ has inaccessible system32/com/dmp directory that screws up this test, so skip it on windows:
3907 if not oTestVm.isWindows():
3908 atTests.append([ tdTestDirRead(sDirectory = sSystemDir),
3909 tdTestResultDirRead(fRc = True, cFiles = -5, cDirs = None) ]);
3910 ## @todo trailing slash
3911
3912 # Read from the test file set.
3913 atTests.extend([
3914 [ tdTestDirRead(sDirectory = self.oTestFiles.oEmptyDir.sPath),
3915 tdTestResultDirRead(fRc = True, cFiles = 0, cDirs = 0, cOthers = 0) ],
3916 [ tdTestDirRead(sDirectory = self.oTestFiles.oManyDir.sPath),
3917 tdTestResultDirRead(fRc = True, cFiles = len(self.oTestFiles.oManyDir.aoChildren), cDirs = 0, cOthers = 0) ],
3918 [ tdTestDirRead(sDirectory = self.oTestFiles.oTreeDir.sPath),
3919 tdTestResultDirRead(fRc = True, cFiles = self.oTestFiles.cTreeFiles, cDirs = self.oTestFiles.cTreeDirs,
3920 cOthers = self.oTestFiles.cTreeOthers) ],
3921 ]);
3922
3923
3924 fRc = True;
3925 for (i, tTest) in enumerate(atTests):
3926 oCurTest = tTest[0] # type: tdTestExec
3927 oCurRes = tTest[1] # type: tdTestResultDirRead
3928
3929 reporter.log('Testing #%d, dir="%s" ...' % (i, oCurTest.sDirectory));
3930 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3931 if not fRc:
3932 break;
3933 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: Test #%d' % (i,));
3934 if fRc is not True:
3935 break;
3936 fUseDirList = False;
3937 cEntriesPerRead = random.randrange(1, 32768);
3938 if self.oTstDrv.fpApiVer >= 7.1 and self.oTstDrv.uRevision >= 156485 \
3939 and self.oTstDrv.isVersionEqualOrBigger(self.tpAdditionsVer, "7.1.0"):
3940 # Listing directories only is available for >= VBox 7.1.
3941 fUseDirList = random.choice( [True, False] );
3942 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc,
3943 fUseDirList, cEntriesPerRead);
3944 fRc = oCurTest.closeSession() and fRc;
3945
3946 reporter.log2('Test #%d: Returned %d directories, %d files total' % (i, cDirs, cFiles));
3947 if fRc2 is oCurRes.fRc:
3948 if fRc2 is True:
3949 if oCurRes.cFiles is None:
3950 pass; # ignore
3951 elif oCurRes.cFiles >= 0 and cFiles != oCurRes.cFiles:
3952 fRc = reporter.error('Test #%d failed: Got %d files, expected %d' % (i, cFiles, oCurRes.cFiles));
3953 elif oCurRes.cFiles < 0 and cFiles < -oCurRes.cFiles:
3954 fRc = reporter.error('Test #%d failed: Got %d files, expected at least %d'
3955 % (i, cFiles, -oCurRes.cFiles));
3956 if oCurRes.cDirs is None:
3957 pass; # ignore
3958 elif oCurRes.cDirs >= 0 and cDirs != oCurRes.cDirs:
3959 fRc = reporter.error('Test #%d failed: Got %d directories, expected %d' % (i, cDirs, oCurRes.cDirs));
3960 elif oCurRes.cDirs < 0 and cDirs < -oCurRes.cDirs:
3961 fRc = reporter.error('Test #%d failed: Got %d directories, expected at least %d'
3962 % (i, cDirs, -oCurRes.cDirs));
3963 if oCurRes.cOthers is None:
3964 pass; # ignore
3965 elif oCurRes.cOthers >= 0 and cOthers != oCurRes.cOthers:
3966 fRc = reporter.error('Test #%d failed: Got %d other types, expected %d' % (i, cOthers, oCurRes.cOthers));
3967 elif oCurRes.cOthers < 0 and cOthers < -oCurRes.cOthers:
3968 fRc = reporter.error('Test #%d failed: Got %d other types, expected at least %d'
3969 % (i, cOthers, -oCurRes.cOthers));
3970
3971 else:
3972 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3973
3974
3975 #
3976 # Go over a few directories in the test file set and compare names,
3977 # types and sizes rather than just the counts like we did above.
3978 #
3979 if fRc is True:
3980 oCurTest = tdTestDirRead();
3981 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3982 if fRc:
3983 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: gctrlReadDirTree2');
3984 if fRc is True:
3985 for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir):
3986 reporter.log('Checking "%s" ...' % (oDir.sPath,));
3987 fUseDirList = False;
3988 cEntriesPerRead = random.randrange(1, 32768);
3989 if self.oTstDrv.fpApiVer >= 7.1 and self.oTstDrv.uRevision >= 156485 \
3990 and self.oTstDrv.isVersionEqualOrBigger(self.tpAdditionsVer, "7.1.0"):
3991 # Listing directories only is available for >= VBox 7.1.
3992 fUseDirList = random.choice( [True, False] );
3993 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir, fUseDirList, cEntriesPerRead) and fRc;
3994 fRc = oCurTest.closeSession() and fRc;
3995
3996 return (fRc, oTxsSession);
3997
3998
3999 def testGuestCtrlFileRemove(self, oSession, oTxsSession, oTestVm):
4000 """
4001 Tests removing guest files.
4002 """
4003
4004 #
4005 # Create a directory with a few files in it using TXS that we'll use for the initial tests.
4006 #
4007 asTestDirs = [
4008 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1'), # [0]
4009 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1', 'subdir-1'), # [1]
4010 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-1', 'subdir-1', 'subsubdir-1'), # [2]
4011 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2'), # [3]
4012 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2', 'subdir-2'), # [4]
4013 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-2', 'subdir-2', 'subsbudir-2'), # [5]
4014 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-3'), # [6]
4015 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-4'), # [7]
4016 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-5'), # [8]
4017 oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'rmtestdir-5', 'subdir-5'), # [9]
4018 ]
4019 asTestFiles = [
4020 oTestVm.pathJoin(asTestDirs[0], 'file-0'), # [0]
4021 oTestVm.pathJoin(asTestDirs[0], 'file-1'), # [1]
4022 oTestVm.pathJoin(asTestDirs[0], 'file-2'), # [2]
4023 oTestVm.pathJoin(asTestDirs[1], 'file-3'), # [3] - subdir-1
4024 oTestVm.pathJoin(asTestDirs[1], 'file-4'), # [4] - subdir-1
4025 oTestVm.pathJoin(asTestDirs[2], 'file-5'), # [5] - subsubdir-1
4026 oTestVm.pathJoin(asTestDirs[3], 'file-6'), # [6] - rmtestdir-2
4027 oTestVm.pathJoin(asTestDirs[4], 'file-7'), # [7] - subdir-2
4028 oTestVm.pathJoin(asTestDirs[5], 'file-8'), # [8] - subsubdir-2
4029 ];
4030 for sDir in asTestDirs:
4031 if oTxsSession.syncMkDir(sDir, 0o777) is not True:
4032 return reporter.error('Failed to create test dir "%s"!' % (sDir,));
4033 for sFile in asTestFiles:
4034 if oTxsSession.syncUploadString(sFile, sFile, 0o666) is not True:
4035 return reporter.error('Failed to create test file "%s"!' % (sFile,));
4036
4037 #
4038 # Tear down the directories and files.
4039 #
4040 aoTests = [
4041 # Negative tests first:
4042 tdTestRemoveFile(asTestDirs[0], fRcExpect = False),
4043 tdTestRemoveDir(asTestDirs[0], fRcExpect = False),
4044 tdTestRemoveDir(asTestFiles[0], fRcExpect = False),
4045 tdTestRemoveFile(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-file'), fRcExpect = False),
4046 tdTestRemoveDir(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir'), fRcExpect = False),
4047 tdTestRemoveFile(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir', 'no-file'), fRcExpect = False),
4048 tdTestRemoveDir(oTestVm.pathJoin(self.oTestFiles.oEmptyDir.sPath, 'no-such-dir', 'no-subdir'), fRcExpect = False),
4049 tdTestRemoveTree(asTestDirs[0], afFlags = [], fRcExpect = False), # Only removes empty dirs, this isn't empty.
4050 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_None,], fRcExpect = False), # ditto
4051 # Empty paths:
4052 tdTestRemoveFile('', fRcExpect = False),
4053 tdTestRemoveDir('', fRcExpect = False),
4054 tdTestRemoveTree('', fRcExpect = False),
4055 # Now actually remove stuff:
4056 tdTestRemoveDir(asTestDirs[7], fRcExpect = True),
4057 tdTestRemoveFile(asTestDirs[6], fRcExpect = False),
4058 tdTestRemoveDir(asTestDirs[6], fRcExpect = True),
4059 tdTestRemoveFile(asTestFiles[0], fRcExpect = True),
4060 tdTestRemoveFile(asTestFiles[0], fRcExpect = False),
4061 # 17:
4062 tdTestRemoveTree(asTestDirs[8], fRcExpect = True), # Removes empty subdirs and leaves the dir itself.
4063 tdTestRemoveDir(asTestDirs[8], fRcExpect = True),
4064 tdTestRemoveTree(asTestDirs[3], fRcExpect = False), # Have subdirs & files,
4065 tdTestRemoveTree(asTestDirs[3], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,], fRcExpect = True),
4066 tdTestRemoveDir(asTestDirs[3], fRcExpect = True),
4067 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,], fRcExpect = True),
4068 # No error if already delete (RTDirRemoveRecursive artifact).
4069 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,], fRcExpect = True),
4070 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,],
4071 fNotExist = True, fRcExpect = True),
4072 tdTestRemoveTree(asTestDirs[0], afFlags = [vboxcon.DirectoryRemoveRecFlag_None,], fNotExist = True, fRcExpect = True),
4073 ];
4074
4075 #
4076 # Execution loop
4077 #
4078 fRc = True;
4079 for (i, oTest) in enumerate(aoTests): # int, tdTestRemoveBase
4080 reporter.log('Testing #%d, path="%s" %s ...' % (i, oTest.sPath, oTest.__class__.__name__));
4081 fRc = oTest.setEnvironment(oSession, oTxsSession, oTestVm);
4082 if not fRc:
4083 break;
4084 fRc, _ = oTest.createSession('testGuestCtrlFileRemove: Test #%d' % (i,));
4085 if fRc is False:
4086 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4087 break;
4088 fRc = oTest.execute(self) and fRc;
4089 fRc = oTest.closeSession() and fRc;
4090
4091 if fRc is True:
4092 oCurTest = tdTestDirRead();
4093 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4094 if fRc:
4095 fRc, oCurGuestSession = oCurTest.createSession('remove final');
4096 if fRc is True:
4097
4098 #
4099 # Delete all the files in the many subdir of the test set.
4100 #
4101 reporter.log('Deleting the file in "%s" ...' % (self.oTestFiles.oManyDir.sPath,));
4102 for oFile in self.oTestFiles.oManyDir.aoChildren:
4103 reporter.log2('"%s"' % (limitString(oFile.sPath),));
4104 try:
4105 if self.oTstDrv.fpApiVer >= 5.0:
4106 oCurGuestSession.fsObjRemove(oFile.sPath);
4107 else:
4108 oCurGuestSession.fileRemove(oFile.sPath);
4109 except:
4110 fRc = reporter.errorXcpt('Removing "%s" failed' % (oFile.sPath,));
4111
4112 # Remove the directory itself to verify that we've removed all the files in it:
4113 reporter.log('Removing the directory "%s" ...' % (self.oTestFiles.oManyDir.sPath,));
4114 try:
4115 oCurGuestSession.directoryRemove(self.oTestFiles.oManyDir.sPath);
4116 except:
4117 fRc = reporter.errorXcpt('Removing directory "%s" failed' % (self.oTestFiles.oManyDir.sPath,));
4118
4119 #
4120 # Recursively delete the entire test file tree from the root up.
4121 #
4122 # Note! On unix we cannot delete the root dir itself since it is residing
4123 # in /var/tmp where only the owner may delete it. Root is the owner.
4124 #
4125 if oTestVm.isWindows() or oTestVm.isOS2():
4126 afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentAndDir,];
4127 else:
4128 afFlags = [vboxcon.DirectoryRemoveRecFlag_ContentOnly,];
4129 try:
4130 oProgress = oCurGuestSession.directoryRemoveRecursive(self.oTestFiles.oRoot.sPath, afFlags);
4131 except:
4132 fRc = reporter.errorXcpt('Removing tree "%s" failed' % (self.oTestFiles.oRoot.sPath,));
4133 else:
4134 oWrappedProgress = vboxwrappers.ProgressWrapper(oProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv,
4135 "remove-tree-root: %s" % (self.oTestFiles.oRoot.sPath,));
4136 reporter.log2('waiting ...')
4137 oWrappedProgress.wait();
4138 reporter.log2('isSuccess=%s' % (oWrappedProgress.isSuccess(),));
4139 if not oWrappedProgress.isSuccess():
4140 fRc = oWrappedProgress.logResult();
4141
4142 fRc = oCurTest.closeSession() and fRc;
4143
4144 return (fRc, oTxsSession);
4145
4146
4147 def testGuestCtrlFileStat(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4148 """
4149 Tests querying file information through stat.
4150 """
4151
4152 # Basic stuff, existing stuff.
4153 aoTests = [
4154 tdTestSessionEx([
4155 tdStepStatDir('.'),
4156 tdStepStatDir('..'),
4157 tdStepStatDir(self.oTstDrv.getGuestTempDir(oTestVm)),
4158 tdStepStatDir(self.oTstDrv.getGuestSystemDir(oTestVm)),
4159 tdStepStatDirEx(self.oTestFiles.oRoot),
4160 tdStepStatDirEx(self.oTestFiles.oEmptyDir),
4161 tdStepStatDirEx(self.oTestFiles.oTreeDir),
4162 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
4163 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
4164 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
4165 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
4166 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
4167 tdStepStatDirEx(self.oTestFiles.chooseRandomDirFromTree()),
4168 tdStepStatFile(self.oTstDrv.getGuestSystemFileForReading(oTestVm)),
4169 tdStepStatFile(self.oTstDrv.getGuestSystemShell(oTestVm)),
4170 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
4171 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
4172 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
4173 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
4174 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
4175 tdStepStatFileEx(self.oTestFiles.chooseRandomFile()),
4176 ]),
4177 ];
4178
4179 # None existing stuff.
4180 sSysDir = self.oTstDrv.getGuestSystemDir(oTestVm);
4181 sSep = oTestVm.pathSep();
4182 aoTests += [
4183 tdTestSessionEx([
4184 tdStepStatFileNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory')),
4185 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory') + sSep),
4186 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', '.')),
4187 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory')),
4188 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory') + sSep),
4189 tdStepStatPathNotFound(oTestVm.pathJoin(sSysDir, 'NoSuchFileOrDirectory', 'NoSuchFileOrSubDirectory', '.')),
4190 #tdStepStatPathNotFound('N:\\'), # ASSUMES nothing mounted on N:!
4191 #tdStepStatPathNotFound('\\\\NoSuchUncServerName\\NoSuchShare'),
4192 ]),
4193 ];
4194 # Invalid parameter check.
4195 aoTests += [ tdTestSessionEx([ tdStepStat('', vbox.ComError.E_INVALIDARG), ]), ];
4196
4197 #
4198 # Execute the tests.
4199 #
4200 fRc, oTxsSession = tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession,
4201 oTestVm, 'FsStat');
4202 #
4203 # Test the full test file set.
4204 #
4205 if self.oTstDrv.fpApiVer < 5.0:
4206 return (fRc, oTxsSession);
4207
4208 oTest = tdTestGuestCtrlBase();
4209 fRc = oTest.setEnvironment(oSession, oTxsSession, oTestVm);
4210 if not fRc:
4211 return (False, oTxsSession);
4212 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet');
4213 if fRc2 is not True:
4214 return (False, oTxsSession);
4215
4216 for oFsObj in self.oTestFiles.dPaths.values():
4217 reporter.log2('testGuestCtrlFileStat: %s sPath=%s'
4218 % ('file' if isinstance(oFsObj, testfileset.TestFile) else 'dir ', limitString(oFsObj.sPath),));
4219
4220 # Query the information:
4221 try:
4222 oFsInfo = oGuestSession.fsObjQueryInfo(oFsObj.sPath, False);
4223 except:
4224 fRc = reporter.errorXcpt('sPath=%s type=%s: fsObjQueryInfo trouble!' % (oFsObj.sPath, type(oFsObj),));
4225 continue;
4226 if oFsInfo is None:
4227 fRc = reporter.error('sPath=%s type=%s: No info object returned!' % (oFsObj.sPath, type(oFsObj),));
4228 continue;
4229
4230 # Check attributes:
4231 try:
4232 eType = oFsInfo.type;
4233 cbObject = oFsInfo.objectSize;
4234 except:
4235 fRc = reporter.errorXcpt('sPath=%s type=%s: attribute access trouble!' % (oFsObj.sPath, type(oFsObj),));
4236 continue;
4237
4238 if isinstance(oFsObj, testfileset.TestFile):
4239 if eType != vboxcon.FsObjType_File:
4240 fRc = reporter.error('sPath=%s type=file: eType=%s, expected %s!'
4241 % (oFsObj.sPath, eType, vboxcon.FsObjType_File));
4242 if cbObject != oFsObj.cbContent:
4243 fRc = reporter.error('sPath=%s type=file: cbObject=%s, expected %s!'
4244 % (oFsObj.sPath, cbObject, oFsObj.cbContent));
4245 fFileExists = True;
4246 fDirExists = False;
4247 elif isinstance(oFsObj, testfileset.TestDir):
4248 if eType != vboxcon.FsObjType_Directory:
4249 fRc = reporter.error('sPath=%s type=dir: eType=%s, expected %s!'
4250 % (oFsObj.sPath, eType, vboxcon.FsObjType_Directory));
4251 fFileExists = False;
4252 fDirExists = True;
4253 else:
4254 fRc = reporter.error('sPath=%s type=%s: Unexpected oFsObj type!' % (oFsObj.sPath, type(oFsObj),));
4255 continue;
4256
4257 # Check the directoryExists and fileExists results too.
4258 try:
4259 fExistsResult = oGuestSession.fileExists(oFsObj.sPath, False);
4260 except:
4261 fRc = reporter.errorXcpt('sPath=%s type=%s: fileExists trouble!' % (oFsObj.sPath, type(oFsObj),));
4262 else:
4263 if fExistsResult != fFileExists:
4264 fRc = reporter.error('sPath=%s type=%s: fileExists returned %s, expected %s!'
4265 % (oFsObj.sPath, type(oFsObj), fExistsResult, fFileExists));
4266 try:
4267 fExistsResult = oGuestSession.directoryExists(oFsObj.sPath, False);
4268 except:
4269 fRc = reporter.errorXcpt('sPath=%s type=%s: directoryExists trouble!' % (oFsObj.sPath, type(oFsObj),));
4270 else:
4271 if fExistsResult != fDirExists:
4272 fRc = reporter.error('sPath=%s type=%s: directoryExists returned %s, expected %s!'
4273 % (oFsObj.sPath, type(oFsObj), fExistsResult, fDirExists));
4274
4275 fRc = oTest.closeSession() and fRc;
4276 return (fRc, oTxsSession);
4277
4278 def testGuestCtrlFileOpen(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4279 """
4280 Tests opening guest files.
4281 """
4282 if self.oTstDrv.fpApiVer < 5.0:
4283 reporter.log('Skipping because of pre 5.0 API');
4284 return None;
4285
4286 #
4287 # Paths.
4288 #
4289 sTempDir = self.oTstDrv.getGuestTempDir(oTestVm);
4290 sFileForReading = self.oTstDrv.getGuestSystemFileForReading(oTestVm);
4291 asFiles = [
4292 oTestVm.pathJoin(sTempDir, 'file-open-0'),
4293 oTestVm.pathJoin(sTempDir, 'file-open-1'),
4294 oTestVm.pathJoin(sTempDir, 'file-open-2'),
4295 oTestVm.pathJoin(sTempDir, 'file-open-3'),
4296 oTestVm.pathJoin(sTempDir, 'file-open-4'),
4297 ];
4298 asNonEmptyFiles = [
4299 oTestVm.pathJoin(sTempDir, 'file-open-10'),
4300 oTestVm.pathJoin(sTempDir, 'file-open-11'),
4301 oTestVm.pathJoin(sTempDir, 'file-open-12'),
4302 oTestVm.pathJoin(sTempDir, 'file-open-13'),
4303 ];
4304 sContent = 'abcdefghijklmnopqrstuvwxyz0123456789';
4305 for sFile in asNonEmptyFiles:
4306 if oTxsSession.syncUploadString(sContent, sFile, 0o666) is not True:
4307 return reporter.error('Failed to create "%s" via TXS' % (sFile,));
4308
4309 #
4310 # The tests.
4311 #
4312 atTests = [
4313 # Invalid stuff.
4314 [ tdTestFileOpen(sFile = ''), tdTestResultFailure() ],
4315 # Wrong open mode.
4316 [ tdTestFileOpen(sFile = sFileForReading, eAccessMode = -1), tdTestResultFailure() ],
4317 # Wrong disposition.
4318 [ tdTestFileOpen(sFile = sFileForReading, eAction = -1), tdTestResultFailure() ],
4319 # Non-existing file or path.
4320 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir')), tdTestResultFailure() ],
4321 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
4322 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
4323 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
4324 eAccessMode = vboxcon.FileAccessMode_WriteOnly,
4325 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
4326 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-file-or-dir'),
4327 eAccessMode = vboxcon.FileAccessMode_ReadWrite,
4328 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultFailure() ],
4329 [ tdTestFileOpen(sFile = oTestVm.pathJoin(sTempDir, 'no-such-dir', 'no-such-file')), tdTestResultFailure() ],
4330 ];
4331 if self.oTstDrv.fpApiVer > 5.2: # Fixed since 6.0.
4332 atTests.extend([
4333 # Wrong type:
4334 [ tdTestFileOpen(sFile = self.oTstDrv.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
4335 [ tdTestFileOpen(sFile = self.oTstDrv.getGuestSystemDir(oTestVm)), tdTestResultFailure() ],
4336 ]);
4337 atTests.extend([
4338 # O_EXCL and such:
4339 [ tdTestFileOpen(sFile = sFileForReading, eAction = vboxcon.FileOpenAction_CreateNew,
4340 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultFailure() ],
4341 [ tdTestFileOpen(sFile = sFileForReading, eAction = vboxcon.FileOpenAction_CreateNew), tdTestResultFailure() ],
4342 # Open a file.
4343 [ tdTestFileOpen(sFile = sFileForReading), tdTestResultSuccess() ],
4344 [ tdTestFileOpen(sFile = sFileForReading,
4345 eAction = vboxcon.FileOpenAction_OpenOrCreate), tdTestResultSuccess() ],
4346 # Create a new file.
4347 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateNew,
4348 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4349 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateNew,
4350 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultFailure() ],
4351 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenExisting,
4352 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4353 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_CreateOrReplace,
4354 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4355 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenOrCreate,
4356 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4357 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_OpenExistingTruncated,
4358 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4359 [ tdTestFileOpenCheckSize(sFile = asFiles[0], eAction = vboxcon.FileOpenAction_AppendOrCreate,
4360 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4361 # Open or create a new file.
4362 [ tdTestFileOpenCheckSize(sFile = asFiles[1], eAction = vboxcon.FileOpenAction_OpenOrCreate,
4363 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4364 # Create or replace a new file.
4365 [ tdTestFileOpenCheckSize(sFile = asFiles[2], eAction = vboxcon.FileOpenAction_CreateOrReplace,
4366 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4367 # Create and append to file (weird stuff).
4368 [ tdTestFileOpenCheckSize(sFile = asFiles[3], eAction = vboxcon.FileOpenAction_AppendOrCreate,
4369 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4370 [ tdTestFileOpenCheckSize(sFile = asFiles[4], eAction = vboxcon.FileOpenAction_AppendOrCreate,
4371 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4372 # Open the non-empty files in non-destructive modes.
4373 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent)), tdTestResultSuccess() ],
4374 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
4375 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4376 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
4377 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4378
4379 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent),
4380 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4381 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4382 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
4383 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4384 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4385 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
4386 eAction = vboxcon.FileOpenAction_OpenOrCreate,
4387 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4388
4389 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], cbOpenExpected = len(sContent),
4390 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4391 eAccessMode = vboxcon.FileAccessMode_ReadWrite), tdTestResultSuccess() ],
4392 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], cbOpenExpected = len(sContent),
4393 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4394 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4395 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], cbOpenExpected = len(sContent),
4396 eAction = vboxcon.FileOpenAction_AppendOrCreate,
4397 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4398
4399 # Now the destructive stuff:
4400 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[0], eAccessMode = vboxcon.FileAccessMode_WriteOnly,
4401 eAction = vboxcon.FileOpenAction_OpenExistingTruncated), tdTestResultSuccess() ],
4402 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[1], eAccessMode = vboxcon.FileAccessMode_WriteOnly,
4403 eAction = vboxcon.FileOpenAction_CreateOrReplace), tdTestResultSuccess() ],
4404 [ tdTestFileOpenCheckSize(sFile = asNonEmptyFiles[2], eAction = vboxcon.FileOpenAction_CreateOrReplace,
4405 eAccessMode = vboxcon.FileAccessMode_WriteOnly), tdTestResultSuccess() ],
4406 ]);
4407
4408 #
4409 # Do the testing.
4410 #
4411 fRc = True;
4412 for (i, tTest) in enumerate(atTests):
4413 oCurTest = tTest[0] # type: tdTestFileOpen
4414 oCurRes = tTest[1] # type: tdTestResult
4415
4416 reporter.log('Testing #%d: %s - sFile="%s", eAccessMode=%d, eAction=%d, (%s, %s, %s) ...'
4417 % (i, oCurTest.__class__.__name__, oCurTest.sFile, oCurTest.eAccessMode, oCurTest.eAction,
4418 oCurTest.eSharing, oCurTest.fCreationMode, oCurTest.afOpenFlags,));
4419
4420 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4421 if not fRc:
4422 break;
4423 fRc, _ = oCurTest.createSession('testGuestCtrlFileOpen: Test #%d' % (i,));
4424 if fRc is not True:
4425 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4426 break;
4427
4428 fRc2 = oCurTest.doSteps(oCurRes.fRc, self);
4429 if fRc2 != oCurRes.fRc:
4430 fRc = reporter.error('Test #%d result mismatch: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
4431
4432 fRc = oCurTest.closeSession() and fRc;
4433
4434 return (fRc, oTxsSession);
4435
4436
4437 def testGuestCtrlFileRead(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-branches,too-many-statements
4438 """
4439 Tests reading from guest files.
4440 """
4441 if self.oTstDrv.fpApiVer < 5.0:
4442 reporter.log('Skipping because of pre 5.0 API');
4443 return None;
4444
4445 #
4446 # Do everything in one session.
4447 #
4448 oTest = tdTestGuestCtrlBase();
4449 fRc = oTest.setEnvironment(oSession, oTxsSession, oTestVm);
4450 if not fRc:
4451 return (False, oTxsSession);
4452 fRc2, oGuestSession = oTest.createSession('FsStat on TestFileSet');
4453 if fRc2 is not True:
4454 return (False, oTxsSession);
4455
4456 #
4457 # Create a really big zero filled, up to 1 GiB, adding it to the list of
4458 # files from the set.
4459 #
4460 # Note! This code sucks a bit because we don't have a working setSize nor
4461 # any way to figure out how much free space there is in the guest.
4462 #
4463 aoExtraFiles = [];
4464 sBigName = self.oTestFiles.generateFilenameEx();
4465 sBigPath = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sBigName);
4466 fRc = True;
4467 try:
4468 oFile = oGuestSession.fileOpenEx(sBigPath, vboxcon.FileAccessMode_ReadWrite, vboxcon.FileOpenAction_CreateOrReplace,
4469 vboxcon.FileSharingMode_All, 0, []);
4470 except:
4471 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4472 else:
4473 # Does setSize work now?
4474 fUseFallback = True;
4475 try:
4476 oFile.setSize(0);
4477 oFile.setSize(64);
4478 fUseFallback = False;
4479 except:
4480 reporter.logXcpt();
4481
4482 # Grow the file till we hit trouble, typical VERR_DISK_FULL, then
4483 # reduce the file size if we have a working setSize.
4484 cbBigFile = 0;
4485 while cbBigFile < (1024 + 32)*1024*1024:
4486 if not fUseFallback:
4487 cbBigFile += 16*1024*1024;
4488 try:
4489 oFile.setSize(cbBigFile);
4490 except Exception:
4491 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4492 try:
4493 cbBigFile -= 16*1024*1024;
4494 oFile.setSize(cbBigFile);
4495 except:
4496 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4497 break;
4498 else:
4499 cbBigFile += 32*1024*1024;
4500 try:
4501 oFile.seek(cbBigFile, vboxcon.FileSeekOrigin_Begin);
4502 oFile.write(bytearray(1), 60*1000);
4503 except:
4504 reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
4505 break;
4506 try:
4507 cbBigFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
4508 except:
4509 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4510 try:
4511 oFile.close();
4512 except:
4513 fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
4514 if fRc is True:
4515 reporter.log('Big file: %s bytes: %s' % (cbBigFile, sBigPath,));
4516 aoExtraFiles.append(testfileset.TestFileZeroFilled(None, sBigPath, cbBigFile));
4517 else:
4518 try:
4519 oGuestSession.fsObjRemove(sBigPath);
4520 except:
4521 reporter.errorXcpt('fsObjRemove(sBigName=%s)' % (sBigPath,));
4522
4523 #
4524 # Open and read all the files in the test file set.
4525 #
4526 for oTestFile in aoExtraFiles + self.oTestFiles.aoFiles: # type: testfileset.TestFile
4527 reporter.log2('Test file: %s bytes, "%s" ...' % (oTestFile.cbContent, limitString(oTestFile.sPath),));
4528
4529 #
4530 # Open it:
4531 #
4532 try:
4533 oFile = oGuestSession.fileOpenEx(oTestFile.sPath, vboxcon.FileAccessMode_ReadOnly,
4534 vboxcon.FileOpenAction_OpenExisting, vboxcon.FileSharingMode_All, 0, []);
4535 except:
4536 fRc = reporter.errorXcpt('sPath=%s' % (oTestFile.sPath, ));
4537 continue;
4538
4539 #
4540 # Read the file in different sized chunks:
4541 #
4542 if oTestFile.cbContent < 128:
4543 acbChunks = xrange(1,128);
4544 elif oTestFile.cbContent < 1024:
4545 acbChunks = (2048, 127, 63, 32, 29, 17, 16, 15, 9);
4546 elif oTestFile.cbContent < 8*1024*1024:
4547 acbChunks = (128*1024, 32*1024, 8191, 255);
4548 else:
4549 acbChunks = (768*1024, 128*1024);
4550
4551 reporter.log2('Chunked reads');
4552
4553 for cbChunk in acbChunks:
4554 # Read the whole file straight thru:
4555 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... cbChunk=%s' % (cbChunk,));
4556 offFile = 0;
4557 cReads = 0;
4558 while offFile <= oTestFile.cbContent:
4559 try:
4560 abRead = oFile.read(cbChunk, 30*1000);
4561 except:
4562 fRc = reporter.errorXcpt('%s: offFile=%s cbChunk=%s cbContent=%s'
4563 % (oTestFile.sPath, offFile, cbChunk, oTestFile.cbContent));
4564 break;
4565 cbRead = len(abRead);
4566 if cbRead == 0 and offFile == oTestFile.cbContent:
4567 break;
4568 if cbRead <= 0:
4569 fRc = reporter.error('%s @%s: cbRead=%s, cbContent=%s'
4570 % (oTestFile.sPath, offFile, cbRead, oTestFile.cbContent));
4571 break;
4572 if not oTestFile.equalMemory(abRead, offFile):
4573 fRc = reporter.error('%s: read mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead));
4574 break;
4575 offFile += cbRead;
4576 cReads += 1;
4577 if cReads > 8192:
4578 break;
4579
4580 # Seek to start of file.
4581 try:
4582 offFile = oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
4583 except:
4584 fRc = reporter.errorXcpt('%s: error seeking to start of file' % (oTestFile.sPath,));
4585 break;
4586 if offFile != 0:
4587 fRc = reporter.error('%s: seek to start of file returned %u, expected 0' % (oTestFile.sPath, offFile));
4588 break;
4589
4590 #
4591 # Random reads.
4592 #
4593 reporter.log2('Random reads (seek)');
4594 for _ in xrange(8):
4595 offFile = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
4596 cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
4597 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s' % (offFile, cbToRead,));
4598
4599 try:
4600 offActual = oFile.seek(offFile, vboxcon.FileSeekOrigin_Begin);
4601 except:
4602 fRc = reporter.errorXcpt('%s: error seeking to %s' % (oTestFile.sPath, offFile));
4603 break;
4604 if offActual != offFile:
4605 fRc = reporter.error('%s: seek(%s,Begin) -> %s, expected %s'
4606 % (oTestFile.sPath, offFile, offActual, offFile));
4607 break;
4608
4609 try:
4610 abRead = oFile.read(cbToRead, 30*1000);
4611 except:
4612 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s'
4613 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4614 cbRead = 0;
4615 else:
4616 cbRead = len(abRead);
4617 if not oTestFile.equalMemory(abRead, offFile):
4618 fRc = reporter.error('%s: random read mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
4619
4620 try:
4621 offActual = oFile.offset;
4622 except:
4623 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#1)'
4624 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4625 else:
4626 if offActual != offFile + cbRead:
4627 fRc = reporter.error('%s: IFile.offset is %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#1)'
4628 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4629 try:
4630 offActual = oFile.seek(0, vboxcon.FileSeekOrigin_Current);
4631 except:
4632 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#1)'
4633 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4634 else:
4635 if offActual != offFile + cbRead:
4636 fRc = reporter.error('%s: seek(0,cur) -> %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#1)'
4637 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4638
4639 #
4640 # Random reads using readAt.
4641 #
4642 reporter.log2('Random reads (readAt)');
4643 for _ in xrange(12):
4644 offFile = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
4645 cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
4646 #if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s (readAt)' % (offFile, cbToRead,));
4647
4648 try:
4649 abRead = oFile.readAt(offFile, cbToRead, 30*1000);
4650 except:
4651 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s'
4652 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4653 cbRead = 0;
4654 else:
4655 cbRead = len(abRead);
4656 if not oTestFile.equalMemory(abRead, offFile):
4657 fRc = reporter.error('%s: random readAt mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
4658
4659 try:
4660 offActual = oFile.offset;
4661 except:
4662 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#2)'
4663 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4664 else:
4665 if offActual != offFile + cbRead:
4666 fRc = reporter.error('%s: IFile.offset is %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#2)'
4667 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4668
4669 try:
4670 offActual = oFile.seek(0, vboxcon.FileSeekOrigin_Current);
4671 except:
4672 fRc = reporter.errorXcpt('%s: offFile=%s cbToRead=%s cbContent=%s (#2)'
4673 % (oTestFile.sPath, offFile, cbToRead, oTestFile.cbContent));
4674 else:
4675 if offActual != offFile + cbRead:
4676 fRc = reporter.error('%s: seek(0,cur) -> %s, expected %s (offFile=%s cbToRead=%s cbRead=%s) (#2)'
4677 % (oTestFile.sPath, offActual, offFile + cbRead, offFile, cbToRead, cbRead));
4678
4679 #
4680 # A few negative things.
4681 #
4682
4683 # Zero byte reads -> E_INVALIDARG.
4684 reporter.log2('Zero byte reads');
4685 try:
4686 abRead = oFile.read(0, 30*1000);
4687 except Exception as oXcpt:
4688 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
4689 fRc = reporter.errorXcpt('read(0,30s) did not raise E_INVALIDARG as expected!');
4690 else:
4691 fRc = reporter.error('read(0,30s) did not fail!');
4692
4693 try:
4694 abRead = oFile.readAt(0, 0, 30*1000);
4695 except Exception as oXcpt:
4696 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
4697 fRc = reporter.errorXcpt('readAt(0,0,30s) did not raise E_INVALIDARG as expected!');
4698 else:
4699 fRc = reporter.error('readAt(0,0,30s) did not fail!');
4700
4701 # See what happens when we read 1GiB. We should get a max of 1MiB back.
4702 ## @todo Document this behaviour in VirtualBox.xidl.
4703 reporter.log2('1GB reads');
4704 try:
4705 oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
4706 except:
4707 fRc = reporter.error('seek(0)');
4708 try:
4709 abRead = oFile.read(1024*1024*1024, 30*1000);
4710 except:
4711 fRc = reporter.errorXcpt('read(1GiB,30s)');
4712 else:
4713 if len(abRead) != min(oTestFile.cbContent, 1024*1024):
4714 fRc = reporter.error('Expected read(1GiB,30s) to return %s bytes, got %s bytes instead'
4715 % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
4716
4717 try:
4718 abRead = oFile.readAt(0, 1024*1024*1024, 30*1000);
4719 except:
4720 fRc = reporter.errorXcpt('readAt(0,1GiB,30s)');
4721 else:
4722 if len(abRead) != min(oTestFile.cbContent, 1024*1024):
4723 reporter.error('Expected readAt(0, 1GiB,30s) to return %s bytes, got %s bytes instead'
4724 % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
4725
4726 #
4727 # Check stat info on the file as well as querySize.
4728 #
4729 if self.oTstDrv.fpApiVer > 5.2:
4730 try:
4731 oFsObjInfo = oFile.queryInfo();
4732 except:
4733 fRc = reporter.errorXcpt('%s: queryInfo()' % (oTestFile.sPath,));
4734 else:
4735 if oFsObjInfo is None:
4736 fRc = reporter.error('IGuestFile::queryInfo returned None');
4737 else:
4738 try:
4739 cbFile = oFsObjInfo.objectSize;
4740 except:
4741 fRc = reporter.errorXcpt();
4742 else:
4743 if cbFile != oTestFile.cbContent:
4744 fRc = reporter.error('%s: queryInfo returned incorrect file size: %s, expected %s'
4745 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4746
4747 try:
4748 cbFile = oFile.querySize();
4749 except:
4750 fRc = reporter.errorXcpt('%s: querySize()' % (oTestFile.sPath,));
4751 else:
4752 if cbFile != oTestFile.cbContent:
4753 fRc = reporter.error('%s: querySize returned incorrect file size: %s, expected %s'
4754 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4755
4756 #
4757 # Use seek to test the file size and do a few other end-relative seeks.
4758 #
4759 try:
4760 cbFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
4761 except:
4762 fRc = reporter.errorXcpt('%s: seek(0,End)' % (oTestFile.sPath,));
4763 else:
4764 if cbFile != oTestFile.cbContent:
4765 fRc = reporter.error('%s: seek(0,End) returned incorrect file size: %s, expected %s'
4766 % (oTestFile.sPath, cbFile, oTestFile.cbContent));
4767 if oTestFile.cbContent > 0:
4768 for _ in xrange(5):
4769 offSeek = self.oTestFiles.oRandom.randrange(oTestFile.cbContent + 1);
4770 try:
4771 offFile = oFile.seek(-offSeek, vboxcon.FileSeekOrigin_End);
4772 except:
4773 fRc = reporter.errorXcpt('%s: seek(%s,End)' % (oTestFile.sPath, -offSeek,));
4774 else:
4775 if offFile != oTestFile.cbContent - offSeek:
4776 fRc = reporter.error('%s: seek(%s,End) returned incorrect offset: %s, expected %s (cbContent=%s)'
4777 % (oTestFile.sPath, -offSeek, offSeek, oTestFile.cbContent - offSeek,
4778 oTestFile.cbContent,));
4779
4780 #
4781 # Close it and we're done with this file.
4782 #
4783 try:
4784 oFile.close();
4785 except:
4786 fRc = reporter.errorXcpt('%s: error closing the file' % (oTestFile.sPath,));
4787
4788 #
4789 # Clean up.
4790 #
4791 for oTestFile in aoExtraFiles:
4792 try:
4793 oGuestSession.fsObjRemove(sBigPath);
4794 except:
4795 fRc = reporter.errorXcpt('fsObjRemove(%s)' % (sBigPath,));
4796
4797 fRc = oTest.closeSession() and fRc;
4798
4799 return (fRc, oTxsSession);
4800
4801
4802 def testGuestCtrlFileWrite(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4803 """
4804 Tests writing to guest files.
4805 """
4806 if self.oTstDrv.fpApiVer < 5.0:
4807 reporter.log('Skipping because of pre 5.0 API');
4808 return None;
4809
4810 #
4811 # The test file and its content.
4812 #
4813 sFile = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'gctrl-write-1');
4814 abContent = bytearray(0);
4815
4816 #
4817 # The tests.
4818 #
4819 def randBytes(cbHowMany):
4820 """ Returns an bytearray of random bytes. """
4821 return bytearray(self.oTestFiles.oRandom.getrandbits(8) for _ in xrange(cbHowMany));
4822
4823 aoTests = [
4824 # Write at end:
4825 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_CreateNew, abContent = abContent,
4826 atChunks = [(None, randBytes(1)), (None, randBytes(77)), (None, randBytes(98)),]),
4827 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1+77+98), # 176
4828 # Appending:
4829 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_AppendOrCreate, abContent = abContent,
4830 atChunks = [(None, randBytes(255)), (None, randBytes(33)),]),
4831 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 176 + 255+33), # 464
4832 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_AppendOrCreate, abContent = abContent,
4833 atChunks = [(10, randBytes(44)),]),
4834 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 464 + 44), # 508
4835 # Write within existing:
4836 tdTestFileOpenAndWrite(sFile = sFile, eAction = vboxcon.FileOpenAction_OpenExisting, abContent = abContent,
4837 atChunks = [(0, randBytes(1)), (50, randBytes(77)), (255, randBytes(199)),]),
4838 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 508),
4839 # Writing around and over the end:
4840 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent,
4841 atChunks = [(500, randBytes(9)), (508, randBytes(15)), (512, randBytes(12)),]),
4842 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 512+12),
4843
4844 # writeAt appending:
4845 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4846 atChunks = [(0, randBytes(23)), (6, randBytes(1018)),]),
4847 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 6+1018), # 1024
4848 # writeAt within existing:
4849 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4850 atChunks = [(1000, randBytes(23)), (1, randBytes(990)),]),
4851 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1024),
4852 # writeAt around and over the end:
4853 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True,
4854 atChunks = [(1024, randBytes(63)), (1080, randBytes(968)),]),
4855 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 1080+968), # 2048
4856
4857 # writeAt beyond the end (gap is filled with zeros):
4858 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, fUseAtApi = True, atChunks = [(3070, randBytes(2)),]),
4859 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 3072),
4860 # write beyond the end (gap is filled with zeros):
4861 tdTestFileOpenAndWrite(sFile = sFile, abContent = abContent, atChunks = [(4090, randBytes(6)),]),
4862 tdTestFileOpenAndCheckContent(sFile = sFile, abContent = abContent, cbContentExpected = 4096),
4863 ];
4864
4865 for (i, oCurTest) in enumerate(aoTests):
4866 reporter.log('Testing #%d: %s ...' % (i, oCurTest.toString(),));
4867 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
4868 if not fRc:
4869 break;
4870 fRc, _ = oCurTest.createSession('testGuestCtrlFileWrite: Test #%d' % (i,));
4871 if fRc is not True:
4872 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
4873 break;
4874
4875 fRc2 = oCurTest.doSteps(True, self);
4876 if fRc2 is not True:
4877 fRc = reporter.error('Test #%d failed!' % (i,));
4878
4879 fRc = oCurTest.closeSession() and fRc;
4880
4881 #
4882 # Cleanup
4883 #
4884 if oTxsSession.syncRmFile(sFile) is not True:
4885 fRc = reporter.error('Failed to remove write-test file: %s' % (sFile, ));
4886
4887 return (fRc, oTxsSession);
4888
4889 @staticmethod
4890 def __generateFile(sName, cbFile):
4891 """ Helper for generating a file with a given size. """
4892 with open(sName, 'wb') as oFile:
4893 while cbFile > 0:
4894 cb = cbFile if cbFile < 256*1024 else 256*1024;
4895 oFile.write(bytearray(random.getrandbits(8) for _ in xrange(cb)));
4896 cbFile -= cb;
4897 return True;
4898
4899 def testGuestCtrlCopyTo(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
4900 """
4901 Tests copying files from host to the guest.
4902 """
4903
4904 #
4905 # Paths and test files.
4906 #
4907 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, 'copyto');
4908 sScratchTestFilesHst = os.path.join(sScratchHst, self.oTestFiles.sSubDir);
4909 sScratchEmptyDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oEmptyDir.sName);
4910 sScratchNonEmptyDirHst = self.oTestFiles.chooseRandomDirFromTree().buildPath(sScratchHst, os.path.sep);
4911 sScratchTreeDirHst = os.path.join(sScratchTestFilesHst, self.oTestFiles.oTreeDir.sName);
4912
4913 sScratchGst = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'copyto');
4914 sScratchDstDir1Gst = oTestVm.pathJoin(sScratchGst, 'dstdir1');
4915 sScratchDstDir2Gst = oTestVm.pathJoin(sScratchGst, 'dstdir2');
4916 sScratchDstDir3Gst = oTestVm.pathJoin(sScratchGst, 'dstdir3');
4917 sScratchDstDir4Gst = oTestVm.pathJoin(sScratchGst, 'dstdir4');
4918 sScratchDotDotDirGst = oTestVm.pathJoin(sScratchGst, '..');
4919 #sScratchGstNotExist = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'no-such-file-or-directory');
4920 sScratchHstNotExist = os.path.join(self.oTstDrv.sScratchPath, 'no-such-file-or-directory');
4921 sScratchGstPathNotFound = oTestVm.pathJoin(self.oTstDrv.getGuestTempDir(oTestVm), 'no-such-directory', 'or-file');
4922 #sScratchHstPathNotFound = os.path.join(self.oTstDrv.sScratchPath, 'no-such-directory', 'or-file');
4923
4924 if oTestVm.isWindows() or oTestVm.isOS2():
4925 sScratchGstInvalid = "?*|<invalid-name>";
4926 else:
4927 sScratchGstInvalid = None;
4928 if utils.getHostOs() in ('win', 'os2'):
4929 sScratchHstInvalid = "?*|<invalid-name>";
4930 else:
4931 sScratchHstInvalid = None;
4932
4933 for sDir in (sScratchGst, sScratchDstDir1Gst, sScratchDstDir2Gst, sScratchDstDir3Gst, sScratchDstDir4Gst):
4934 if oTxsSession.syncMkDir(sDir, 0o777) is not True:
4935 return reporter.error('TXS failed to create directory "%s"!' % (sDir,));
4936
4937 # Put the test file set under sScratchHst.
4938 if os.path.exists(sScratchHst):
4939 if base.wipeDirectory(sScratchHst) != 0:
4940 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
4941 else:
4942 try:
4943 os.mkdir(sScratchHst);
4944 except:
4945 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
4946 if self.oTestFiles.writeToDisk(sScratchHst) is not True:
4947 return reporter.error('Filed to write test files to "%s" on the host!' % (sScratchHst,));
4948
4949 # If for whatever reason the directory tree does not exist on the host, let us know.
4950 # Copying an non-existing tree *will* fail the tests which otherwise should succeed!
4951 assert os.path.exists(sScratchTreeDirHst);
4952
4953 # Generate a test file in 32MB to 64 MB range.
4954 sBigFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-random.data');
4955 cbBigFileHst = random.randrange(32*1024*1024, 64*1024*1024);
4956 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
4957 cbLeft = cbBigFileHst;
4958 try:
4959 self.__generateFile(sBigFileHst, cbBigFileHst);
4960 except:
4961 return reporter.errorXcpt('sBigFileHst=%s cbBigFileHst=%s cbLeft=%s' % (sBigFileHst, cbBigFileHst, cbLeft,));
4962 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
4963
4964 # Generate an empty file on the host that we can use to save space in the guest.
4965 sEmptyFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-empty.data');
4966 try:
4967 open(sEmptyFileHst, "wb").close(); # pylint: disable=consider-using-with
4968 except:
4969 return reporter.errorXcpt('sEmptyFileHst=%s' % (sEmptyFileHst,));
4970
4971 # os.path.join() is too clever for "..", so we just build up the path here ourselves.
4972 sScratchDotDotFileHst = sScratchHst + os.path.sep + '..' + os.path.sep + 'gctrl-empty.data';
4973
4974 #
4975 # Tests.
4976 #
4977 atTests = [
4978 # Nothing given:
4979 [ tdTestCopyToFile(), tdTestResultFailure() ],
4980 [ tdTestCopyToDir(), tdTestResultFailure() ],
4981 # Only source given:
4982 [ tdTestCopyToFile(sSrc = sBigFileHst), tdTestResultFailure() ],
4983 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst), tdTestResultFailure() ],
4984 # Only destination given:
4985 [ tdTestCopyToFile(sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')), tdTestResultFailure() ],
4986 [ tdTestCopyToDir( sDst = sScratchGst), tdTestResultFailure() ],
4987 # Both given, but invalid flags.
4988 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst, afFlags = [ 0x40000000, ] ), tdTestResultFailure() ],
4989 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGst, afFlags = [ 0x40000000, ] ),
4990 tdTestResultFailure() ],
4991 ];
4992 atTests.extend([
4993 # Non-existing source, but no destination:
4994 [ tdTestCopyToFile(sSrc = sScratchHstNotExist), tdTestResultFailure() ],
4995 [ tdTestCopyToDir( sSrc = sScratchHstNotExist), tdTestResultFailure() ],
4996 # Valid sources, but destination path not found:
4997 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
4998 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
4999 # Valid destination, but source file/dir not found:
5000 [ tdTestCopyToFile(sSrc = sScratchHstNotExist, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
5001 tdTestResultFailure() ],
5002 [ tdTestCopyToDir( sSrc = sScratchHstNotExist, sDst = sScratchGst), tdTestResultFailure() ],
5003 # Wrong type:
5004 [ tdTestCopyToFile(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, 'dstfile')),
5005 tdTestResultFailure() ],
5006 [ tdTestCopyToDir( sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultFailure() ],
5007 ]);
5008 # Invalid characters in destination or source path:
5009 if sScratchGstInvalid is not None:
5010 atTests.extend([
5011 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
5012 tdTestResultFailure() ],
5013 [ tdTestCopyToDir( sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
5014 tdTestResultFailure() ],
5015 ]);
5016 if sScratchHstInvalid is not None:
5017 atTests.extend([
5018 [ tdTestCopyToFile(sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
5019 tdTestResultFailure() ],
5020 [ tdTestCopyToDir( sSrc = os.path.join(self.oTstDrv.sScratchPath, sScratchHstInvalid), sDst = sScratchGst),
5021 tdTestResultFailure() ],
5022 ]);
5023
5024 #
5025 # Single file handling.
5026 #
5027 atTests.extend([
5028 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')),
5029 tdTestResultSuccess() ],
5030 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
5031 tdTestResultSuccess() ],
5032 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
5033 tdTestResultSuccess() ],
5034 ]);
5035 if self.oTstDrv.fpApiVer > 5.2: # Copying files into directories via Main is supported only 6.0 and later.
5036 atTests.extend([
5037 # Should succeed, as the file isn't there yet on the destination.
5038 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst + oTestVm.pathSep()), tdTestResultSuccess() ],
5039 # Overwrite the existing file.
5040 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = sScratchGst + oTestVm.pathSep()), tdTestResultSuccess() ],
5041 # Same file, but with a different name on the destination.
5042 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, os.path.split(sBigFileHst)[1])),
5043 tdTestResultSuccess() ], # Overwrite
5044 ]);
5045
5046 if oTestVm.isWindows():
5047 # Copy to a Windows alternative data stream (ADS).
5048 atTests.extend([
5049 [ tdTestCopyToFile(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat:ADS-Test')),
5050 tdTestResultSuccess() ],
5051 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat:ADS-Test')),
5052 tdTestResultSuccess() ],
5053 ]);
5054
5055 #
5056 # Directory handling.
5057 #
5058 if self.oTstDrv.fpApiVer > 5.2: # Copying directories via Main is supported only in versions > 5.2.
5059 atTests.extend([
5060 # Without a trailing slash added to the destination this should fail,
5061 # as the destination directory already exists.
5062 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst), tdTestResultFailure() ],
5063 # Same existing host directory, but this time with DirectoryCopyFlag_CopyIntoExisting set.
5064 # This should copy the contents of oEmptyDirGst to sScratchDstDir1Gst (empty, but anyway).
5065 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
5066 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5067 # Try again.
5068 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir1Gst,
5069 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5070 # With a trailing slash added to the destination, copy the empty guest directory
5071 # (should end up as sScratchDstDir2Gst/empty):
5072 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
5073 tdTestResultSuccess() ],
5074 # Repeat -- this time it should fail, as the destination directory already exists (and
5075 # DirectoryCopyFlag_CopyIntoExisting is not specified):
5076 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep()),
5077 tdTestResultFailure() ],
5078 # Add the DirectoryCopyFlag_CopyIntoExisting flag being set and it should work (again).
5079 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = sScratchDstDir2Gst + oTestVm.pathSep(),
5080 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5081 # Copy with a different destination name just for the heck of it:
5082 [ tdTestCopyToDir(sSrc = sScratchEmptyDirHst, sDst = oTestVm.pathJoin(sScratchDstDir2Gst, 'empty2')),
5083 tdTestResultSuccess() ],
5084 ]);
5085 atTests.extend([
5086 # Now the same using a directory with files in it:
5087 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
5088 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5089 # Again.
5090 [ tdTestCopyToDir(sSrc = sScratchNonEmptyDirHst, sDst = sScratchDstDir3Gst,
5091 afFlags = [vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5092 ]);
5093 atTests.extend([
5094 # Copy the entire test tree:
5095 [ tdTestCopyToDir(sSrc = sScratchTreeDirHst, sDst = sScratchDstDir4Gst + oTestVm.pathSep()),
5096 tdTestResultSuccess() ],
5097 # Again, should fail this time.
5098 [ tdTestCopyToDir(sSrc = sScratchTreeDirHst, sDst = sScratchDstDir4Gst + oTestVm.pathSep()),
5099 tdTestResultFailure() ],
5100 # Works again, as DirectoryCopyFlag_CopyIntoExisting is specified.
5101 [ tdTestCopyToDir(sSrc = sScratchTreeDirHst, sDst = sScratchDstDir4Gst + oTestVm.pathSep(),
5102 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5103 ]);
5104 #
5105 # Dotdot path handling.
5106 #
5107 if self.oTstDrv.fpApiVer >= 6.1:
5108 atTests.extend([
5109 # Test if copying stuff from a host dotdot ".." directory works.
5110 [ tdTestCopyToFile(sSrc = sScratchDotDotFileHst, sDst = sScratchDstDir1Gst + oTestVm.pathSep()),
5111 tdTestResultSuccess() ],
5112 # Test if copying stuff from the host to a guest's dotdot ".." directory works.
5113 # That should fail on destinations.
5114 [ tdTestCopyToFile(sSrc = sEmptyFileHst, sDst = sScratchDotDotDirGst), tdTestResultFailure() ],
5115 ]);
5116
5117 fRc = True;
5118 for (i, tTest) in enumerate(atTests):
5119 oCurTest = tTest[0]; # tdTestCopyTo
5120 oCurRes = tTest[1]; # tdTestResult
5121 reporter.log('Testing #%d, sSrc=%s, sDst=%s, afFlags=%s ...'
5122 % (i, limitString(oCurTest.sSrc), limitString(oCurTest.sDst), oCurTest.afFlags));
5123
5124 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
5125 if not fRc:
5126 break;
5127 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyTo: Test #%d' % (i,));
5128 if fRc is not True:
5129 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
5130 break;
5131
5132 fRc2 = False;
5133 if isinstance(oCurTest, tdTestCopyToFile):
5134 fRc2 = self.gctrlCopyFileTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags, oCurRes.fRc);
5135 else:
5136 fRc2 = self.gctrlCopyDirTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.afFlags, oCurRes.fRc);
5137 if fRc2 is not oCurRes.fRc:
5138 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
5139
5140 fRc = oCurTest.closeSession() and fRc;
5141
5142 return (fRc, oTxsSession);
5143
5144 def testGuestCtrlCopyFrom(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
5145 """
5146 Tests copying files from guest to the host.
5147 """
5148
5149 reporter.log2('Entered');
5150
5151 #
5152 # Paths.
5153 #
5154 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom");
5155 sScratchDstDir1Hst = os.path.join(sScratchHst, "dstdir1");
5156 sScratchDstDir2Hst = os.path.join(sScratchHst, "dstdir2");
5157 sScratchDstDir3Hst = os.path.join(sScratchHst, "dstdir3");
5158 sScratchDstDir4Hst = os.path.join(sScratchHst, "dstdir4");
5159 # os.path.join() is too clever for "..", so we just build up the path here ourselves.
5160 sScratchDotDotDirHst = sScratchHst + os.path.sep + '..' + os.path.sep;
5161 oExistingFileGst = self.oTestFiles.chooseRandomFile();
5162 oNonEmptyDirGst = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True);
5163 oTreeDirGst = self.oTestFiles.oTreeDir;
5164 oEmptyDirGst = self.oTestFiles.oEmptyDir;
5165
5166 if oTestVm.isWindows() or oTestVm.isOS2():
5167 sScratchGstInvalid = "?*|<invalid-name>";
5168 else:
5169 sScratchGstInvalid = None;
5170 if utils.getHostOs() in ('win', 'os2'):
5171 sScratchHstInvalid = "?*|<invalid-name>";
5172 else:
5173 sScratchHstInvalid = None;
5174
5175 sScratchDotDotDirGst = oTestVm.pathJoin(oEmptyDirGst.sPath, '..');
5176
5177 if os.path.exists(sScratchHst):
5178 if base.wipeDirectory(sScratchHst) != 0:
5179 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
5180 else:
5181 try:
5182 os.mkdir(sScratchHst);
5183 except:
5184 return reporter.errorXcpt('os.mkdir(%s)' % (sScratchHst, ));
5185
5186 reporter.log2('Creating host sub dirs ...');
5187
5188 for sSubDir in (sScratchDstDir1Hst, sScratchDstDir2Hst, sScratchDstDir3Hst, sScratchDstDir4Hst):
5189 try:
5190 os.mkdir(sSubDir);
5191 except:
5192 return reporter.errorXcpt('os.mkdir(%s)' % (sSubDir, ));
5193
5194 reporter.log2('Defining tests ...');
5195
5196 #
5197 # Bad parameter tests.
5198 #
5199 atTests = [
5200 # Missing both source and destination:
5201 [ tdTestCopyFromFile(), tdTestResultFailure() ],
5202 [ tdTestCopyFromDir(), tdTestResultFailure() ],
5203 # Missing source.
5204 [ tdTestCopyFromFile(sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
5205 [ tdTestCopyFromDir( sDst = sScratchHst), tdTestResultFailure() ],
5206 # Missing destination.
5207 [ tdTestCopyFromFile(oSrc = oExistingFileGst), tdTestResultFailure() ],
5208 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath), tdTestResultFailure() ],
5209 # Invalid flags:
5210 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somefile'), afFlags = [0x40000000]),
5211 tdTestResultFailure() ],
5212 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'somedir'), afFlags = [ 0x40000000] ),
5213 tdTestResultFailure() ],
5214 # Non-existing sources:
5215 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
5216 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
5217 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
5218 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
5219 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-file'),
5220 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
5221 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-subdir'),
5222 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
5223 # Non-existing destinations:
5224 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
5225 sDst = os.path.join(sScratchHst, 'no-such-directory', 'somefile') ), tdTestResultFailure() ],
5226 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'no-such-directory', 'somedir') ),
5227 tdTestResultFailure() ],
5228 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
5229 sDst = os.path.join(sScratchHst, 'no-such-directory-slash' + os.path.sep)),
5230 tdTestResultFailure() ],
5231 # Wrong source type:
5232 [ tdTestCopyFromFile(oSrc = oNonEmptyDirGst, sDst = os.path.join(sScratchHst, 'somefile') ), tdTestResultFailure() ],
5233 [ tdTestCopyFromDir(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somedir') ), tdTestResultFailure() ],
5234 ];
5235 # Bogus names:
5236 if sScratchHstInvalid:
5237 atTests.extend([
5238 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
5239 tdTestResultFailure() ],
5240 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
5241 tdTestResultFailure() ],
5242 ]);
5243 if sScratchGstInvalid:
5244 atTests.extend([
5245 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
5246 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
5247 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
5248 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
5249 ]);
5250
5251 #
5252 # Single file copying.
5253 #
5254 atTests.extend([
5255 # Should succeed, as the file isn't there yet on the destination.
5256 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')), tdTestResultSuccess() ],
5257 # Overwrite the existing file.
5258 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')), tdTestResultSuccess() ],
5259 # Same file, but with a different name on the destination.
5260 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile2')), tdTestResultSuccess() ],
5261 ]);
5262
5263 if self.oTstDrv.fpApiVer > 5.2: # Copying files into directories via Main is supported only 6.0 and later.
5264 # Copy into a directory.
5265 atTests.extend([
5266 # This should fail, as sScratchHst exists and is a directory.
5267 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst), tdTestResultFailure() ],
5268 # Same existing host directory, but this time with a trailing slash.
5269 # This should succeed, as the file isn't there yet on the destination.
5270 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst + os.path.sep), tdTestResultSuccess() ],
5271 # Overwrite the existing file.
5272 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst + os.path.sep), tdTestResultSuccess() ],
5273 ]);
5274
5275 #
5276 # Directory handling.
5277 #
5278 if self.oTstDrv.fpApiVer > 5.2: # Copying directories via Main is supported only in versions > 5.2.
5279 atTests.extend([
5280 # Without a trailing slash added to the destination this should fail,
5281 # as the destination directory already exist.
5282 [ tdTestCopyFromDir(sSrc = oEmptyDirGst.sPath, sDst = sScratchDstDir1Hst), tdTestResultFailure() ],
5283 # Same existing host directory, but this time with DirectoryCopyFlag_CopyIntoExisting set.
5284 # This should copy the contents of oEmptyDirGst to sScratchDstDir1Hst (empty, but anyway).
5285 [ tdTestCopyFromDir(sSrc = oEmptyDirGst.sPath, sDst = sScratchDstDir1Hst,
5286 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5287 # Try again.
5288 [ tdTestCopyFromDir(sSrc = oEmptyDirGst.sPath, sDst = sScratchDstDir1Hst,
5289 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5290 # With a trailing slash added to the destination, copy the empty guest directory
5291 # (should end up as sScratchHst/empty):
5292 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir2Hst + os.path.sep), tdTestResultSuccess() ],
5293 # Repeat -- this time it should fail, as the destination directory already exists (and
5294 # DirectoryCopyFlag_CopyIntoExisting is not specified):
5295 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir2Hst + os.path.sep), tdTestResultFailure() ],
5296 # Add the DirectoryCopyFlag_CopyIntoExisting flag being set and it should work (again).
5297 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchDstDir2Hst + os.path.sep,
5298 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5299 # Copy with a different destination name just for the heck of it:
5300 [ tdTestCopyFromDir(sSrc = oEmptyDirGst.sPath, sDst = os.path.join(sScratchDstDir2Hst, 'empty2'),
5301 fIntoDst = True),
5302 tdTestResultSuccess() ],
5303 ]);
5304 atTests.extend([
5305 # Now the same using a directory with files in it:
5306 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir3Hst + os.path.sep), tdTestResultSuccess() ],
5307 # Again.
5308 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchDstDir3Hst, fIntoDst = True,
5309 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5310 ]);
5311 atTests.extend([
5312 # Copy the entire test tree:
5313 [ tdTestCopyFromDir(oSrc = oTreeDirGst, sDst = sScratchDstDir4Hst + os.path.sep), tdTestResultSuccess() ],
5314 # Again, should fail this time.
5315 [ tdTestCopyFromDir(oSrc = oTreeDirGst, sDst = sScratchDstDir4Hst + os.path.sep), tdTestResultFailure() ],
5316 # Works again, as DirectoryCopyFlag_CopyIntoExisting is specified.
5317 [ tdTestCopyFromDir(oSrc = oTreeDirGst, sDst = sScratchDstDir4Hst + os.path.sep,
5318 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
5319 ]);
5320 #
5321 # Dotdot path handling.
5322 #
5323 if self.oTstDrv.fpApiVer >= 6.1:
5324 atTests.extend([
5325 # Test if copying stuff from a guest dotdot ".." directory works.
5326 [ tdTestCopyFromDir(sSrc = sScratchDotDotDirGst, sDst = sScratchDstDir1Hst + os.path.sep,
5327 afFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]),
5328 tdTestResultFailure() ],
5329 # Test if copying stuff from the guest to a host's dotdot ".." directory works.
5330 # That should fail on destinations.
5331 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchDotDotDirHst), tdTestResultFailure() ],
5332 ]);
5333
5334 reporter.log2('Executing tests ...');
5335
5336 #
5337 # Execute the tests.
5338 #
5339 fRc = True;
5340 for (i, tTest) in enumerate(atTests):
5341 oCurTest = tTest[0]
5342 oCurRes = tTest[1] # type: tdTestResult
5343 if isinstance(oCurTest, tdTestCopyFrom):
5344 reporter.log('Testing #%d, %s: sSrc="%s", sDst="%s", afFlags="%s" ...'
5345 % (i, "directory" if isinstance(oCurTest, tdTestCopyFromDir) else "file",
5346 limitString(oCurTest.sSrc), limitString(oCurTest.sDst), oCurTest.afFlags,));
5347 else:
5348 reporter.log('Testing #%d, tdTestRemoveHostDir "%s" ...' % (i, oCurTest.sDir,));
5349 if isinstance(oCurTest, tdTestCopyFromDir) and self.oTstDrv.fpApiVer < 6.0:
5350 reporter.log('Skipping directoryCopyFromGuest test, not implemented in %s' % (self.oTstDrv.fpApiVer,));
5351 continue;
5352
5353 if isinstance(oCurTest, tdTestRemoveHostDir):
5354 fRc = oCurTest.execute(self.oTstDrv, oSession, oTxsSession, oTestVm, 'testing #%d' % (i,));
5355 else:
5356 fRc = oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
5357 if not fRc:
5358 break;
5359 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyFrom: Test #%d' % (i,));
5360 if fRc2 is not True:
5361 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
5362 break;
5363
5364 if isinstance(oCurTest, tdTestCopyFromFile):
5365 fRc2 = self.gctrlCopyFileFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
5366 else:
5367 fRc2 = self.gctrlCopyDirFrom(oCurGuestSession, oCurTest, oCurRes.fRc);
5368
5369 if fRc2 != oCurRes.fRc:
5370 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
5371
5372 fRc = oCurTest.closeSession() and fRc;
5373
5374 return (fRc, oTxsSession);
5375
5376 def testGuestCtrlUpdateAdditions(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
5377 """
5378 Tests updating the Guest Additions inside the guest.
5379
5380 """
5381
5382 ## @todo currently disabled everywhere.
5383 if self.oTstDrv.fpApiVer < 100.0:
5384 reporter.log("Skipping updating GAs everywhere for now...");
5385 return None;
5386
5387 # Skip test for updating Guest Additions if we run on a too old (Windows) guest.
5388 ##
5389 ## @todo make it work everywhere!
5390 ##
5391 if oTestVm.sKind in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
5392 reporter.log("Skipping updating GAs on old windows vm (sKind=%s)" % (oTestVm.sKind,));
5393 return (None, oTxsSession);
5394 if oTestVm.isOS2():
5395 reporter.log("Skipping updating GAs on OS/2 guest");
5396 return (None, oTxsSession);
5397
5398 sVBoxValidationKitIso = self.oTstDrv.sVBoxValidationKitIso;
5399 if not os.path.isfile(sVBoxValidationKitIso):
5400 return reporter.log('Validation Kit .ISO not found at "%s"' % (sVBoxValidationKitIso,));
5401
5402 sScratch = os.path.join(self.oTstDrv.sScratchPath, "testGctrlUpdateAdditions");
5403 try:
5404 os.makedirs(sScratch);
5405 except OSError as e:
5406 if e.errno != errno.EEXIST:
5407 return reporter.error('Failed: Unable to create scratch directory \"%s\"' % (sScratch,));
5408 reporter.log('Scratch path is: %s' % (sScratch,));
5409
5410 atTests = [];
5411 if oTestVm.isWindows():
5412 atTests.extend([
5413 # Source is missing.
5414 [ tdTestUpdateAdditions(sSrc = ''), tdTestResultFailure() ],
5415
5416 # Wrong flags.
5417 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
5418 afFlags = [ 1234 ]), tdTestResultFailure() ],
5419
5420 # Non-existing .ISO.
5421 [ tdTestUpdateAdditions(sSrc = "non-existing.iso"), tdTestResultFailure() ],
5422
5423 # Wrong .ISO.
5424 [ tdTestUpdateAdditions(sSrc = sVBoxValidationKitIso), tdTestResultFailure() ],
5425
5426 # The real thing.
5427 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso()),
5428 tdTestResultSuccess() ],
5429 # Test the (optional) installer arguments. This will extract the
5430 # installer into our guest's scratch directory.
5431 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
5432 asArgs = [ '/extract', '/D=' + sScratch ]),
5433 tdTestResultSuccess() ]
5434 # Some debg ISO. Only enable locally.
5435 #[ tdTestUpdateAdditions(
5436 # sSrc = "V:\\Downloads\\VBoxGuestAdditions-r80354.iso"),
5437 # tdTestResultSuccess() ]
5438 ]);
5439 else:
5440 reporter.log('No OS-specific tests for non-Windows yet!');
5441
5442 fRc = True;
5443 for (i, tTest) in enumerate(atTests):
5444 oCurTest = tTest[0] # type: tdTestUpdateAdditions
5445 oCurRes = tTest[1] # type: tdTestResult
5446 reporter.log('Testing #%d, sSrc="%s", afFlags="%s" ...' % (i, oCurTest.sSrc, oCurTest.afFlags,));
5447
5448 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
5449 if not fRc:
5450 break;
5451 fRc, _ = oCurTest.createSession('Test #%d' % (i,));
5452 if fRc is not True:
5453 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
5454 break;
5455
5456 try:
5457 oCurProgress = oCurTest.oGuest.updateGuestAdditions(oCurTest.sSrc, oCurTest.asArgs, oCurTest.afFlags);
5458 except:
5459 reporter.maybeErrXcpt(oCurRes.fRc, 'Updating Guest Additions exception for sSrc="%s", afFlags="%s":'
5460 % (oCurTest.sSrc, oCurTest.afFlags,));
5461 fRc = False;
5462 else:
5463 if oCurProgress is not None:
5464 oWrapperProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr,
5465 self.oTstDrv, "gctrlUpGA");
5466 oWrapperProgress.wait();
5467 if not oWrapperProgress.isSuccess():
5468 oWrapperProgress.logResult(fIgnoreErrors = not oCurRes.fRc);
5469 fRc = False;
5470 else:
5471 fRc = reporter.error('No progress object returned');
5472
5473 oCurTest.closeSession();
5474 if fRc is oCurRes.fRc:
5475 if fRc:
5476 ## @todo Verify if Guest Additions were really updated (build, revision, ...).
5477 ## @todo r=bird: Not possible since you're installing the same GAs as before...
5478 ## Maybe check creation dates on certain .sys/.dll/.exe files?
5479 pass;
5480 else:
5481 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
5482 break;
5483
5484 return (fRc, oTxsSession);
5485
5486 def checkScreenShot(self, iWidth, iHeight, aRGBData): # pylint: disable=unused-argument
5487 """
5488 TBD: Implement basic validation of the captured screenshot content.
5489 """
5490 cPixels = iHeight * iWidth
5491
5492 if cPixels == 0:
5493 reporter.logXcpt("Empty screenshot");
5494 return False
5495
5496 # The simple algoritm below assumes that Windows OS desktop consists of a pixels that
5497 # are not too dark or bright but usually of blue tint.
5498 cDesktopPixels = 0
5499 cDesktopPixelsBlue = 0
5500 iThreshold = 20
5501 for i in range(0, cPixels, 4) :
5502 if sys.version_info[0] >= 3:
5503 iRed = aRGBData[i];
5504 iGreen = aRGBData[i + 1];
5505 iBlue = aRGBData[i + 2];
5506 else: # Python 2.7 treats a pixel data returned by takeScreenShotToArray as a string
5507 iRed = ord(aRGBData[i])
5508 iGreen = ord(aRGBData[i + 1])
5509 iBlue = ord(aRGBData[i + 2])
5510
5511 iBright = (3 * iRed + 6 * iGreen + iBlue) / 10
5512 if iThreshold < iBright < 255 - iThreshold :
5513 cDesktopPixels += 1;
5514 cDesktopPixelsBlue += int(iBlue > iRed and iBlue > iGreen);
5515
5516 fpRatioDesktop = float(cDesktopPixels) / float(cPixels);
5517 reporter.log2('Ratio of not too dark or bright pixels %.2f' % (fpRatioDesktop));
5518
5519 if fpRatioDesktop > 0.1:
5520 fpRatioBlue = float(cDesktopPixelsBlue) / float(cDesktopPixels);
5521 reporter.log2('Ratio of blue pixels %.2f ' % (fpRatioBlue));
5522 if fpRatioBlue > 0.5:
5523 return True
5524
5525 return True # Always return True until the parameters will be calibrated.
5526
5527 def testGuestCtrl3D(self, oSession, oTxsSession, oTestVm): # pylint: disable=unused-argument
5528 """
5529 Tests for VMSVGA device.
5530 """
5531
5532 if oTestVm.sKind not in ('Windows8_64', 'Windows10', 'Windows10_64', 'Windows11_64'):
5533 return (True, oTxsSession);
5534
5535 iScreenId = 0 # TBD: Use a loop to iterate and check all virtual displays
5536 try:
5537 if self.oTstDrv.fpApiVer >= 5.0:
5538 iWidth, iHeight, _, _, _, _ = oSession.o.console.display.getScreenResolution(iScreenId);
5539 else:
5540 iWidth, iHeight, _, _, _ = oSession.o.console.display.getScreenResolution(iScreenId);
5541
5542 aRGBData = oSession.o.console.display.takeScreenShotToArray(iScreenId, iWidth, iHeight,
5543 vboxcon.BitmapFormat_RGBA);
5544 except:
5545 reporter.logXcpt("Unable to take screenshot");
5546 return False
5547
5548 reporter.log2('Got screenshot (%s x %s) having %s bytes' % (iWidth, iHeight, len(aRGBData)));
5549 fRc = self.checkScreenShot(iWidth, iHeight, aRGBData);
5550
5551 fRc = fRc and self.oTstDrv.txsRunTest(oTxsSession, 'Checking DX11 feature level', 30 * 1000,
5552 '${CDROM}/${OS/ARCH}/ntDisplay${EXESUFF}', ('ntDisplay', ));
5553
5554 return (fRc, oTxsSession);
5555
5556class tdAddGuestCtrl(vbox.TestDriver): # pylint: disable=too-many-instance-attributes,too-many-public-methods
5557 """
5558 Guest control using VBoxService on the guest.
5559 """
5560
5561 def __init__(self):
5562 vbox.TestDriver.__init__(self);
5563 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
5564 self.asRsrcs = None;
5565 self.fQuick = False; # Don't skip lengthly tests by default.
5566 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
5567
5568 #
5569 # Overridden methods.
5570 #
5571 def showUsage(self):
5572 """
5573 Shows the testdriver usage.
5574 """
5575 rc = vbox.TestDriver.showUsage(self);
5576 reporter.log('');
5577 reporter.log('tdAddGuestCtrl Options:');
5578 reporter.log(' --quick');
5579 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
5580 return rc;
5581
5582 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
5583 """
5584 Parses the testdriver arguments from the command line.
5585 """
5586 if asArgs[iArg] == '--quick':
5587 self.parseOption(['--virt-modes', 'hwvirt'], 0);
5588 self.parseOption(['--cpu-counts', '1'], 0);
5589 self.fQuick = True;
5590 else:
5591 return vbox.TestDriver.parseOption(self, asArgs, iArg);
5592 return iArg + 1;
5593
5594 def actionConfig(self):
5595 if not self.importVBoxApi(): # So we can use the constant below.
5596 return False;
5597
5598 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
5599 sGaIso = self.getGuestAdditionsIso();
5600 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
5601
5602 def actionExecute(self):
5603 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
5604
5605 #
5606 # Test execution helpers.
5607 #
5608 def testOneCfg(self, oVM, oTestVm): # pylint: disable=too-many-statements
5609 """
5610 Runs the specified VM thru the tests.
5611
5612 Returns a success indicator on the general test execution. This is not
5613 the actual test result.
5614 """
5615
5616 self.logVmInfo(oVM);
5617
5618 fRc = True;
5619 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False);
5620 reporter.log("TxsSession: %s" % (oTxsSession,));
5621 if oSession is not None:
5622 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
5623 self.terminateVmBySession(oSession);
5624 else:
5625 fRc = False;
5626 return fRc;
5627
5628 def onExit(self, iRc):
5629 return vbox.TestDriver.onExit(self, iRc);
5630
5631 def gctrlReportError(self, progress):
5632 """
5633 Helper function to report an error of a
5634 given progress object.
5635 """
5636 if progress is None:
5637 reporter.log('No progress object to print error for');
5638 else:
5639 errInfo = progress.errorInfo;
5640 if errInfo:
5641 reporter.log('%s' % (errInfo.text,));
5642 return False;
5643
5644 def gctrlGetRemainingTime(self, msTimeout, msStart):
5645 """
5646 Helper function to return the remaining time (in ms)
5647 based from a timeout value and the start time (both in ms).
5648 """
5649 if msTimeout == 0:
5650 return 0xFFFFFFFE; # Wait forever.
5651 msElapsed = base.timestampMilli() - msStart;
5652 if msElapsed > msTimeout:
5653 return 0; # No time left.
5654 return msTimeout - msElapsed;
5655
5656 def testGuestCtrlManual(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements,unused-argument,unused-variable
5657 """
5658 For manually testing certain bits.
5659 """
5660
5661 reporter.log('Manual testing ...');
5662 fRc = True;
5663
5664 sUser = 'Administrator';
5665 sPassword = 'password';
5666
5667 oGuest = oSession.o.console.guest;
5668 oGuestSession = oGuest.createSession(sUser,
5669 sPassword,
5670 "", "Manual Test");
5671
5672 aWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
5673 _ = oGuestSession.waitForArray(aWaitFor, 30 * 1000);
5674
5675 #sCmd = self.getGuestSystemShell(oTestVm);
5676 #asArgs = [ sCmd, '/C', 'dir', '/S', 'c:\\windows' ];
5677 #aEnv = [];
5678 #afFlags = [];
5679
5680 # Fix this once being used (again).
5681 #for _ in xrange(100):
5682 # oProc = self.processCreateWrapper(oGuestSession, sCmd, asArgs if self.fpApiVer >= 5.0 else asArgs[1:],
5683 # "", # Working directory.
5684 # aEnv, afFlags, 30 * 1000);
5685 #
5686 # aWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate ];
5687 # _ = oProc.waitForArray(aWaitFor, 30 * 1000);
5688
5689 oGuestSession.close();
5690 oGuestSession = None;
5691
5692 time.sleep(5);
5693
5694 oSession.o.console.PowerDown();
5695
5696 return (fRc, oTxsSession);
5697
5698if __name__ == '__main__':
5699 sys.exit(tdAddGuestCtrl().main(sys.argv));
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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