VirtualBox

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

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

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

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