VirtualBox

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

Last change on this file since 79394 was 79394, checked in by vboxsync, 6 years ago

tdAddGuestCtrl.py: Adjustment of dir listing test. bugref:9320 bugref:9151

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