VirtualBox

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

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

Guest Control/Validation Kit: Enabled more tests (IGuestSession::directoryOpen() API + trying to open directories on Linux as files). bugref:9320

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