VirtualBox

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

Last change on this file since 93889 was 93889, checked in by vboxsync, 3 years ago

Guest Control/Validation Kit: Added another assertion to check if the host directory tree really is there before attempting to run any copy-to-guest tests.

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

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