VirtualBox

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

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

tdAddGuestCtrl.py: testGuestCtrlCopyFrom related cleanups. Fixed python 2.x issue in vboxtestfileset.py. bugref:9151 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: 193.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# pylint: disable=too-many-lines
4
5"""
6VirtualBox Validation Kit - Guest Control Tests.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2019 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 79180 $"
31
32# Standard Python imports.
33from array import array
34import errno
35import os
36import random
37import struct
38import sys
39import threading
40import time
41
42# Only the main script needs to modify the path.
43try: __file__
44except: __file__ = sys.argv[0];
45g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
46sys.path.append(g_ksValidationKitDir);
47
48# Validation Kit imports.
49from testdriver import reporter;
50from testdriver import base;
51from testdriver import 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 def appendStream(self, stream, convertTo = '<b'):
68 """
69 Appends and converts a byte sequence to this object;
70 handy for displaying a guest stream.
71 """
72 self.extend(struct.pack(convertTo, stream));
73
74class tdCtxTest(object):
75 """
76 Provides the actual test environment.
77 Should be kept as generic as possible.
78 """
79 def __init__(self, oSession, oTxsSession, oTestVm): # pylint: disable=unused-argument
80 ## The desired Main API result.
81 self.fRc = False;
82 ## IGuest reference.
83 self.oGuest = oSession.o.console.guest; ## @todo may throw shit
84 self.oSesison = oSession;
85 self.oTxsSesison = oTxsSession;
86 self.oTestVm = oTestVm;
87
88class tdCtxCreds(object):
89 """
90 Provides credentials to pass to the guest.
91 """
92 def __init__(self, sUser = None, sPassword = None, sDomain = None):
93 self.oTestVm = None;
94 self.sUser = sUser;
95 self.sPassword = sPassword;
96 self.sDomain = sDomain;
97
98 def applyDefaultsIfNotSet(self, oTestVm):
99 """
100 Applies credential defaults, based on the test VM (guest OS), if
101 no credentials were set yet.
102 """
103 self.oTestVm = oTestVm;
104 assert self.oTestVm is not None;
105
106 if self.sUser is None:
107 self.sUser = self.oTestVm.getTestUser();
108
109 if self.sPassword is None:
110 self.sPassword = self.oTestVm.getTestUserPassword(self.sUser);
111
112 if self.sDomain is None:
113 self.sDomain = '';
114
115class tdTestGuestCtrlBase(object):
116 """
117 Base class for all guest control tests.
118
119 Note: This test ASSUMES that working Guest Additions
120 were installed and running on the guest to be tested.
121 """
122 def __init__(self):
123 self.oTest = None;
124 self.oCreds = None;
125 self.timeoutMS = 30 * 1000; # 30s timeout
126 ## IGuestSession reference or None.
127 self.oGuestSession = None;
128
129 def setEnvironment(self, oSession, oTxsSession, oTestVm):
130 """
131 Sets the test environment required for this test.
132 """
133 self.oTest = tdCtxTest(oSession, oTxsSession, oTestVm);
134 self.oCreds.applyDefaultsIfNotSet(oTestVm);
135 return self.oTest;
136
137 def uploadLogData(self, oTstDrv, aData, sFileName, sDesc):
138 """
139 Uploads (binary) data to a log file for manual (later) inspection.
140 """
141 reporter.log('Creating + uploading log data file "%s"' % sFileName);
142 sHstFileName = os.path.join(oTstDrv.sScratchPath, sFileName);
143 try:
144 oCurTestFile = open(sHstFileName, "wb");
145 oCurTestFile.write(aData);
146 oCurTestFile.close();
147 except:
148 return reporter.error('Unable to create temporary file for "%s"' % (sDesc,));
149 return reporter.addLogFile(sHstFileName, 'misc/other', sDesc);
150
151 def createSession(self, sName, fIsError = False):
152 """
153 Creates (opens) a guest session.
154 Returns (True, IGuestSession) on success or (False, None) on failure.
155 """
156 if self.oGuestSession is None:
157 if sName is None:
158 sName = "<untitled>";
159
160 reporter.log('Creating session "%s" ...' % (sName,));
161 try:
162 self.oGuestSession = self.oTest.oGuest.createSession(self.oCreds.sUser,
163 self.oCreds.sPassword,
164 self.oCreds.sDomain,
165 sName);
166 except:
167 # Just log, don't assume an error here (will be done in the main loop then).
168 reporter.maybeErrXcpt(fIsError, 'Creating a guest session "%s" failed; sUser="%s", pw="%s", sDomain="%s":'
169 % (sName, self.oCreds.sUser, self.oCreds.sPassword, self.oCreds.sDomain));
170 return (False, None);
171
172 reporter.log('Waiting for session "%s" to start within %dms...' % (sName, self.timeoutMS));
173 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
174 try:
175 waitResult = self.oGuestSession.waitForArray(aeWaitFor, self.timeoutMS);
176
177 #
178 # Be nice to Guest Additions < 4.3: They don't support session handling and
179 # therefore return WaitFlagNotSupported.
180 #
181 if waitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
182 # Just log, don't assume an error here (will be done in the main loop then).
183 reporter.maybeErr(fIsError, 'Session did not start successfully, returned wait result: %d' % (waitResult,));
184 return (False, None);
185 reporter.log('Session "%s" successfully started' % (sName,));
186 except:
187 # Just log, don't assume an error here (will be done in the main loop then).
188 reporter.maybeErrXcpt(fIsError, 'Waiting for guest session "%s" (usr=%s;pw=%s;dom=%s) to start failed:'
189 % (sName, self.oCreds.sUser, self.oCreds.sPassword, self.oCreds.sDomain,));
190 return (False, None);
191 else:
192 reporter.log('Warning: Session already set; this is probably not what you want');
193 return (True, self.oGuestSession);
194
195 def setSession(self, oGuestSession):
196 """
197 Sets the current guest session and closes
198 an old one if necessary.
199 """
200 if self.oGuestSession is not None:
201 self.closeSession();
202 self.oGuestSession = oGuestSession;
203 return self.oGuestSession;
204
205 def closeSession(self, fIsError = False):
206 """
207 Closes the guest session.
208 """
209 if self.oGuestSession is not None:
210 try:
211 sName = self.oGuestSession.name;
212 except:
213 return reporter.errorXcpt();
214
215 reporter.log('Closing session "%s" ...' % (sName,));
216 try:
217 self.oGuestSession.close();
218 self.oGuestSession = None;
219 except:
220 # Just log, don't assume an error here (will be done in the main loop then).
221 reporter.maybeErrXcpt(fIsError, 'Closing guest session "%s" failed:' % (sName,));
222 return False;
223 return True;
224
225class tdTestCopyFrom(tdTestGuestCtrlBase):
226 """
227 Test for copying files from the guest to the host.
228 """
229 def __init__(self, sSrc = "", sDst = "", sUser = None, sPassword = None, fFlags = None, oSrc = None):
230 tdTestGuestCtrlBase.__init__(self);
231 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
232 self.sSrc = sSrc;
233 self.sDst = sDst;
234 self.fFlags = fFlags;
235 self.oSrc = oSrc # type: vboxtestfileset.GstFsObj
236 if oSrc and not sSrc:
237 self.sSrc = oSrc.sPath;
238
239class tdTestCopyFromDir(tdTestCopyFrom):
240 pass;
241
242class tdTestCopyFromFile(tdTestCopyFrom):
243 pass;
244
245class tdTestRemoveHostDir(object):
246 """
247 Test step that removes a host directory tree.
248 """
249 def __init__(self, sDir):
250 self.sDir = sDir;
251
252 def execute(self, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
253 _ = oTstDrv; _ = oVmSession; _ = oTxsSession; _ = oTestVm; _ = sMsgPrefix;
254 if os.path.exists(self.sDir):
255 if base.wipeDirectory(self.sDir) != 0:
256 return False;
257 try:
258 os.rmdir(self.sDir);
259 except:
260 reporter.errorXcpt('%s: sDir=%s' % (sMsgPrefix, self.sDir,));
261 return True;
262
263
264
265class tdTestCopyTo(tdTestGuestCtrlBase):
266 """
267 Test for copying files from the host to the guest.
268 """
269 def __init__(self, sSrc = "", sDst = "", sUser = None, sPassword = None, fFlags = None):
270 tdTestGuestCtrlBase.__init__(self);
271 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
272 self.sSrc = sSrc;
273 self.sDst = sDst;
274 self.fFlags = fFlags;
275
276class tdTestDirCreate(tdTestGuestCtrlBase):
277 """
278 Test for directoryCreate call.
279 """
280 def __init__(self, sDirectory = "", sUser = None, sPassword = None, fMode = 0, fFlags = None):
281 tdTestGuestCtrlBase.__init__(self);
282 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
283 self.sDirectory = sDirectory;
284 self.fMode = fMode;
285 self.fFlags = fFlags;
286
287class tdTestDirCreateTemp(tdTestGuestCtrlBase):
288 """
289 Test for the directoryCreateTemp call.
290 """
291 def __init__(self, sDirectory = "", sTemplate = "", sUser = None, sPassword = None, fMode = 0, fSecure = False):
292 tdTestGuestCtrlBase.__init__(self);
293 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
294 self.sDirectory = sDirectory;
295 self.sTemplate = sTemplate;
296 self.fMode = fMode;
297 self.fSecure = fSecure;
298
299class tdTestDirOpen(tdTestGuestCtrlBase):
300 """
301 Test for the directoryOpen call.
302 """
303 def __init__(self, sDirectory = "", sUser = None, sPassword = None, sFilter = "", fFlags = None):
304 tdTestGuestCtrlBase.__init__(self);
305 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
306 self.sDirectory = sDirectory;
307 self.sFilter = sFilter;
308 self.fFlags = fFlags or [];
309
310class tdTestDirRead(tdTestDirOpen):
311 """
312 Test for the opening, reading and closing a certain directory.
313 """
314 def __init__(self, sDirectory = "", sUser = None, sPassword = None,
315 sFilter = "", fFlags = None):
316 tdTestDirOpen.__init__(self, sDirectory, sUser, sPassword, sFilter, fFlags);
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, fFlags = None, # pylint: disable=too-many-arguments
324 timeoutMS = 5 * 60 * 1000, sUser = None, sPassword = None, sDomain = None, fWaitForExit = True):
325 tdTestGuestCtrlBase.__init__(self);
326 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain);
327 self.sCmd = sCmd;
328 self.asArgs = asArgs if asArgs is not None else [sCmd,];
329 self.aEnv = aEnv;
330 self.fFlags = fFlags or [];
331 self.timeoutMS = timeoutMS;
332 self.fWaitForExit = fWaitForExit;
333 self.uExitStatus = 0;
334 self.iExitCode = 0;
335 self.cbStdOut = 0;
336 self.cbStdErr = 0;
337 self.sBuf = '';
338
339class tdTestFileExists(tdTestGuestCtrlBase):
340 """
341 Test for the file exists API call (fileExists).
342 """
343 def __init__(self, sFile = "", sUser = None, sPassword = None):
344 tdTestGuestCtrlBase.__init__(self);
345 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
346 self.sFile = sFile;
347
348class tdTestFileRemove(tdTestGuestCtrlBase):
349 """
350 Test querying guest file information.
351 """
352 def __init__(self, sFile = "", sUser = None, sPassword = None):
353 tdTestGuestCtrlBase.__init__(self);
354 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
355 self.sFile = sFile;
356
357class tdTestFileStat(tdTestGuestCtrlBase):
358 """
359 Test querying guest file information.
360 """
361 def __init__(self, sFile = "", sUser = None, sPassword = None, cbSize = 0, eFileType = 0):
362 tdTestGuestCtrlBase.__init__(self);
363 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
364 self.sFile = sFile;
365 self.cbSize = cbSize;
366 self.eFileType = eFileType;
367
368class tdTestFileIO(tdTestGuestCtrlBase):
369 """
370 Test for the IGuestFile object.
371 """
372 def __init__(self, sFile = "", sUser = None, sPassword = None):
373 tdTestGuestCtrlBase.__init__(self);
374 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
375 self.sFile = sFile;
376
377class tdTestFileQuerySize(tdTestGuestCtrlBase):
378 """
379 Test for the file size query API call (fileQuerySize).
380 """
381 def __init__(self, sFile = "", sUser = None, sPassword = None):
382 tdTestGuestCtrlBase.__init__(self);
383 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
384 self.sFile = sFile;
385
386class tdTestFileReadWrite(tdTestGuestCtrlBase):
387 """
388 Tests reading from guest files.
389 """
390 def __init__(self, sFile = "", sUser = None, sPassword = None, sOpenMode = "r", # pylint: disable=too-many-arguments
391 sDisposition = "", sSharingMode = "", fCreationMode = 0, offFile = 0, cbToReadWrite = 0, abBuf = None):
392 tdTestGuestCtrlBase.__init__(self);
393 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain = None);
394 self.sFile = sFile;
395 self.sOpenMode = sOpenMode;
396 self.sDisposition = sDisposition;
397 self.sSharingMode = sSharingMode;
398 self.fCreationMode = fCreationMode;
399 self.offFile = offFile;
400 self.cbToReadWrite = cbToReadWrite;
401 self.abBuf = abBuf;
402
403 def getOpenAction(self):
404 """ Converts string disposition to open action enum. """
405 if self.sDisposition == 'oe': return vboxcon.FileOpenAction_OpenExisting;
406 if self.sDisposition == 'oc': return vboxcon.FileOpenAction_OpenOrCreate;
407 if self.sDisposition == 'ce': return vboxcon.FileOpenAction_CreateNew;
408 if self.sDisposition == 'ca': return vboxcon.FileOpenAction_CreateOrReplace;
409 if self.sDisposition == 'ot': return vboxcon.FileOpenAction_OpenExistingTruncated;
410 if self.sDisposition == 'oa': return vboxcon.FileOpenAction_AppendOrCreate;
411 raise base.GenError(self.sDisposition);
412
413 def getAccessMode(self):
414 """ Converts open mode to access mode enum. """
415 if self.sOpenMode == 'r': return vboxcon.FileAccessMode_ReadOnly;
416 if self.sOpenMode == 'w': return vboxcon.FileAccessMode_WriteOnly;
417 if self.sOpenMode == 'w+': return vboxcon.FileAccessMode_ReadWrite;
418 if self.sOpenMode == 'r+': return vboxcon.FileAccessMode_ReadWrite;
419 raise base.GenError(self.sOpenMode);
420
421 def getSharingMode(self):
422 """ Converts the sharing mode. """
423 return vboxcon.FileSharingMode_All;
424
425class tdTestSession(tdTestGuestCtrlBase):
426 """
427 Test the guest session handling.
428 """
429 def __init__(self, sUser = None, sPassword = None, sDomain = None, sSessionName = ""):
430 tdTestGuestCtrlBase.__init__(self);
431 self.sSessionName = sSessionName;
432 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain);
433
434 def getSessionCount(self, oVBoxMgr):
435 """
436 Helper for returning the number of currently
437 opened guest sessions of a VM.
438 """
439 if self.oTest.oGuest is None:
440 return 0;
441 try:
442 aoSession = oVBoxMgr.getArray(self.oTest.oGuest, 'sessions')
443 except:
444 reporter.errorXcpt('sSessionName: %s' % (self.sSessionName,));
445 return 0;
446 return len(aoSession);
447
448class tdTestSessionEx(tdTestGuestCtrlBase):
449 """
450 Test the guest session.
451 """
452 def __init__(self, aoSteps = None, enmUser = None):
453 tdTestGuestCtrlBase.__init__(self);
454 assert enmUser is None; # For later.
455 self.enmUser = enmUser;
456 self.aoSteps = aoSteps if aoSteps is not None else [];
457
458 def execute(self, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
459 """
460 Executes the test.
461 """
462 #
463 # Create a session.
464 #
465 assert self.enmUser is None; # For later.
466 self.oCreds = tdCtxCreds();
467 self.setEnvironment(oVmSession, oTxsSession, oTestVm);
468 reporter.log2('%s: %s steps' % (sMsgPrefix, len(self.aoSteps),));
469 fRc, oCurSession = self.createSession(sMsgPrefix);
470 if fRc is True:
471 #
472 # Execute the tests.
473 #
474 try:
475 fRc = self.executeSteps(oTstDrv, oCurSession, sMsgPrefix);
476 except:
477 fRc = reporter.errorXcpt('%s: Unexpected exception executing test steps' % (sMsgPrefix,));
478
479 #
480 # Close the session.
481 #
482 fRc2 = self.closeSession(True);
483 if fRc2 is False:
484 fRc = reporter.error('%s: Session could not be closed' % (sMsgPrefix,));
485 else:
486 fRc = reporter.error('%s: Session creation failed' % (sMsgPrefix,));
487 return fRc;
488
489 def executeSteps(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
490 """
491 Executes just the steps.
492 Returns True on success, False on test failure.
493 """
494 fRc = True;
495 for (i, oStep) in enumerate(self.aoSteps):
496 fRc2 = oStep.execute(oTstDrv, oGstCtrlSession, sMsgPrefix + ', step #%d' % i);
497 if fRc2 is True:
498 pass;
499 elif fRc2 is None:
500 reporter.log('%s: skipping remaining %d steps' % (sMsgPrefix, len(self.aoSteps) - i - 1,));
501 break;
502 else:
503 fRc = False;
504 return fRc;
505
506 @staticmethod
507 def executeListTestSessions(aoTests, oTstDrv, oVmSession, oTxsSession, oTestVm, sMsgPrefix):
508 """
509 Works thru a list of tdTestSessionEx object.
510 """
511 fRc = True;
512 for (i, oCurTest) in enumerate(aoTests):
513 try:
514 fRc2 = oCurTest.execute(oTstDrv, oVmSession, oTxsSession, oTestVm, '%s / %#d' % (sMsgPrefix, i,));
515 if fRc2 is not True:
516 fRc = False;
517 except:
518 fRc = reporter.errorXcpt('%s: Unexpected exception executing test #%d' % (sMsgPrefix, i ,));
519
520 return (fRc, oTxsSession);
521
522
523class tdSessionStepBase(object):
524 """
525 Base class for the guest control session test steps.
526 """
527
528 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
529 """
530 Executes the test step.
531
532 Returns True on success.
533 Returns False on failure (must be reported as error).
534 Returns None if to skip the remaining steps.
535 """
536 _ = oTstDrv;
537 _ = oGstCtrlSession;
538 return reporter.error('%s: Missing execute implementation: %s' % (sMsgPrefix, self,));
539
540
541class tdStepRequireMinimumApiVer(tdSessionStepBase):
542 """
543 Special test step which will cause executeSteps to skip the remaining step
544 if the VBox API is too old:
545 """
546 def __init__(self, fpMinApiVer):
547 self.fpMinApiVer = fpMinApiVer;
548
549 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
550 """ Returns None if API version is too old, otherwise True. """
551 if oTstDrv.fpApiVer >= self.fpMinApiVer:
552 return True;
553 _ = oGstCtrlSession;
554 _ = sMsgPrefix;
555 return None; # Special return value. Don't use elsewhere.
556
557
558#
559# Scheduling Environment Changes with the Guest Control Session.
560#
561
562class tdStepSessionSetEnv(tdSessionStepBase):
563 """
564 Guest session environment: schedule putenv
565 """
566 def __init__(self, sVar, sValue, hrcExpected = 0):
567 self.sVar = sVar;
568 self.sValue = sValue;
569 self.hrcExpected = hrcExpected;
570
571 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
572 """
573 Executes the step.
574 Returns True on success, False on test failure.
575 """
576 reporter.log2('tdStepSessionSetEnv: sVar=%s sValue=%s hrcExpected=%#x' % (self.sVar, self.sValue, self.hrcExpected,));
577 try:
578 if oTstDrv.fpApiVer >= 5.0:
579 oGstCtrlSession.environmentScheduleSet(self.sVar, self.sValue);
580 else:
581 oGstCtrlSession.environmentSet(self.sVar, self.sValue);
582 except vbox.ComException as oXcpt:
583 # Is this an expected failure?
584 if vbox.ComError.equal(oXcpt, self.hrcExpected):
585 return True;
586 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (setenv %s=%s)'
587 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
588 vbox.ComError.getXcptResult(oXcpt),
589 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
590 self.sVar, self.sValue,));
591 except:
592 return reporter.errorXcpt('%s: Unexpected exception in tdStepSessionSetEnv::execute (%s=%s)'
593 % (sMsgPrefix, self.sVar, self.sValue,));
594
595 # Should we succeed?
596 if self.hrcExpected != 0:
597 return reporter.error('%s: Expected hrcExpected=%#x, got S_OK (putenv %s=%s)'
598 % (sMsgPrefix, self.hrcExpected, self.sVar, self.sValue,));
599 return True;
600
601class tdStepSessionUnsetEnv(tdSessionStepBase):
602 """
603 Guest session environment: schedule unset.
604 """
605 def __init__(self, sVar, hrcExpected = 0):
606 self.sVar = sVar;
607 self.hrcExpected = hrcExpected;
608
609 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
610 """
611 Executes the step.
612 Returns True on success, False on test failure.
613 """
614 reporter.log2('tdStepSessionUnsetEnv: sVar=%s hrcExpected=%#x' % (self.sVar, self.hrcExpected,));
615 try:
616 if oTstDrv.fpApiVer >= 5.0:
617 oGstCtrlSession.environmentScheduleUnset(self.sVar);
618 else:
619 oGstCtrlSession.environmentUnset(self.sVar);
620 except vbox.ComException as oXcpt:
621 # Is this an expected failure?
622 if vbox.ComError.equal(oXcpt, self.hrcExpected):
623 return True;
624 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (unsetenv %s)'
625 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
626 vbox.ComError.getXcptResult(oXcpt),
627 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
628 self.sVar,));
629 except:
630 return reporter.errorXcpt('%s: Unexpected exception in tdStepSessionUnsetEnv::execute (%s)'
631 % (sMsgPrefix, self.sVar,));
632
633 # Should we succeed?
634 if self.hrcExpected != 0:
635 return reporter.error('%s: Expected hrcExpected=%#x, got S_OK (unsetenv %s)'
636 % (sMsgPrefix, self.hrcExpected, self.sVar,));
637 return True;
638
639class tdStepSessionBulkEnv(tdSessionStepBase):
640 """
641 Guest session environment: Bulk environment changes.
642 """
643 def __init__(self, asEnv = None, hrcExpected = 0):
644 self.asEnv = asEnv if asEnv is not None else [];
645 self.hrcExpected = hrcExpected;
646
647 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
648 """
649 Executes the step.
650 Returns True on success, False on test failure.
651 """
652 reporter.log2('tdStepSessionBulkEnv: asEnv=%s hrcExpected=%#x' % (self.asEnv, self.hrcExpected,));
653 try:
654 if oTstDrv.fpApiVer >= 5.0:
655 oTstDrv.oVBoxMgr.setArray(oGstCtrlSession, 'environmentChanges', self.asEnv);
656 else:
657 oTstDrv.oVBoxMgr.setArray(oGstCtrlSession, 'environment', self.asEnv);
658 except vbox.ComException as oXcpt:
659 # Is this an expected failure?
660 if vbox.ComError.equal(oXcpt, self.hrcExpected):
661 return True;
662 return reporter.errorXcpt('%s: Expected hrc=%#x (%s) got %#x (%s) instead (asEnv=%s)'
663 % (sMsgPrefix, self.hrcExpected, vbox.ComError.toString(self.hrcExpected),
664 vbox.ComError.getXcptResult(oXcpt),
665 vbox.ComError.toString(vbox.ComError.getXcptResult(oXcpt)),
666 self.asEnv,));
667 except:
668 return reporter.errorXcpt('%s: Unexpected exception writing the environmentChanges property (asEnv=%s).'
669 % (sMsgPrefix, self.asEnv));
670 return True;
671
672class tdStepSessionClearEnv(tdStepSessionBulkEnv):
673 """
674 Guest session environment: clears the scheduled environment changes.
675 """
676 def __init__(self):
677 tdStepSessionBulkEnv.__init__(self);
678
679
680class tdStepSessionCheckEnv(tdSessionStepBase):
681 """
682 Check the currently scheduled environment changes of a guest control session.
683 """
684 def __init__(self, asEnv = None):
685 self.asEnv = asEnv if asEnv is not None else [];
686
687 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
688 """
689 Executes the step.
690 Returns True on success, False on test failure.
691 """
692 reporter.log2('tdStepSessionCheckEnv: asEnv=%s' % (self.asEnv,));
693
694 #
695 # Get the environment change list.
696 #
697 try:
698 if oTstDrv.fpApiVer >= 5.0:
699 asCurEnv = oTstDrv.oVBoxMgr.getArray(oGstCtrlSession, 'environmentChanges');
700 else:
701 asCurEnv = oTstDrv.oVBoxMgr.getArray(oGstCtrlSession, 'environment');
702 except:
703 return reporter.errorXcpt('%s: Unexpected exception reading the environmentChanges property.' % (sMsgPrefix,));
704
705 #
706 # Compare it with the expected one by trying to remove each expected value
707 # and the list anything unexpected.
708 #
709 fRc = True;
710 asCopy = list(asCurEnv); # just in case asCurEnv is immutable
711 for sExpected in self.asEnv:
712 try:
713 asCopy.remove(sExpected);
714 except:
715 fRc = reporter.error('%s: Expected "%s" to be in the resulting environment' % (sMsgPrefix, sExpected,));
716 for sUnexpected in asCopy:
717 fRc = reporter.error('%s: Unexpected "%s" in the resulting environment' % (sMsgPrefix, sUnexpected,));
718
719 if fRc is not True:
720 reporter.log2('%s: Current environment: %s' % (sMsgPrefix, asCurEnv));
721 return fRc;
722
723
724#
725# File system object statistics (i.e. stat()).
726#
727
728class tdStepStat(tdSessionStepBase):
729 """
730 Stats a file system object.
731 """
732 def __init__(self, sPath, hrcExpected = 0, fFound = True, fFollowLinks = True, enmType = None):
733 self.sPath = sPath;
734 self.hrcExpected = hrcExpected;
735 self.fFound = fFound;
736 self.fFollowLinks = fFollowLinks;
737 self.enmType = enmType if enmType is not None else vboxcon.FsObjType_File;
738 self.cbExactSize = None;
739 self.cbMinSize = None;
740
741 def execute(self, oTstDrv, oGstCtrlSession, sMsgPrefix):
742 """
743 Execute the test step.
744 """
745 reporter.log2('tdStepStat: sPath=%s enmType=%s hrcExpected=%s fFound=%s fFollowLinks=%s'
746 % (self.sPath, self.enmType, self.hrcExpected, self.fFound, self.fFollowLinks,));
747
748 # Don't execute non-file tests on older VBox version.
749 if oTstDrv.fpApiVer >= 5.0 or self.enmType == vboxcon.FsObjType_File or not self.fFound:
750 #
751 # Call the API.
752 #
753 try:
754 if oTstDrv.fpApiVer >= 5.0:
755 oFsInfo = oGstCtrlSession.fsObjQueryInfo(self.sPath, self.fFollowLinks);
756 else:
757 oFsInfo = oGstCtrlSession.fileQueryInfo(self.sPath);
758 except vbox.ComException as oXcpt:
759 ## @todo: The error reporting in the API just plain sucks! Most of the errors are
760 ## VBOX_E_IPRT_ERROR and there seems to be no way to distinguish between
761 ## non-existing files/path and a lot of other errors. Fix API and test!
762 if not self.fFound:
763 return True;
764 if vbox.ComError.equal(oXcpt, self.hrcExpected): # Is this an expected failure?
765 return True;
766 return reporter.errorXcpt('%s: Unexpected exception for exiting path "%s" (enmType=%s, hrcExpected=%s):'
767 % (sMsgPrefix, self.sPath, self.enmType, self.hrcExpected,));
768 except:
769 return reporter.errorXcpt('%s: Unexpected exception in tdStepStat::execute (%s)'
770 % (sMsgPrefix, self.sPath,));
771 if oFsInfo is None:
772 return reporter.error('%s: "%s" got None instead of IFsObjInfo instance!' % (sMsgPrefix, self.sPath,));
773
774 #
775 # Check type expectations.
776 #
777 try:
778 enmType = oFsInfo.type;
779 except:
780 return reporter.errorXcpt('%s: Unexpected exception in reading "IFsObjInfo::type"' % (sMsgPrefix,));
781 if enmType != self.enmType:
782 return reporter.error('%s: "%s" has type %s, expected %s'
783 % (sMsgPrefix, self.sPath, enmType, self.enmType));
784
785 #
786 # Check size expectations.
787 # Note! This is unicode string here on windows, for some reason.
788 # long long mapping perhaps?
789 #
790 try:
791 cbObject = long(oFsInfo.objectSize);
792 except:
793 return reporter.errorXcpt('%s: Unexpected exception in reading "IFsObjInfo::objectSize"'
794 % (sMsgPrefix,));
795 if self.cbExactSize is not None \
796 and cbObject != self.cbExactSize:
797 return reporter.error('%s: "%s" has size %s bytes, expected %s bytes'
798 % (sMsgPrefix, self.sPath, cbObject, self.cbExactSize));
799 if self.cbMinSize is not None \
800 and cbObject < self.cbMinSize:
801 return reporter.error('%s: "%s" has size %s bytes, expected as least %s bytes'
802 % (sMsgPrefix, self.sPath, cbObject, self.cbMinSize));
803 return True;
804
805class tdStepStatDir(tdStepStat):
806 """ Checks for an existing directory. """
807 def __init__(self, sDirPath):
808 tdStepStat.__init__(self, sPath = sDirPath, enmType = vboxcon.FsObjType_Directory);
809
810class tdStepStatFile(tdStepStat):
811 """ Checks for an existing file """
812 def __init__(self, sFilePath):
813 tdStepStat.__init__(self, sPath = sFilePath, enmType = vboxcon.FsObjType_File);
814
815class tdStepStatFileSize(tdStepStat):
816 """ Checks for an existing file of a given expected size.. """
817 def __init__(self, sFilePath, cbExactSize = 0):
818 tdStepStat.__init__(self, sPath = sFilePath, enmType = vboxcon.FsObjType_File);
819 self.cbExactSize = cbExactSize;
820
821class tdStepStatFileNotFound(tdStepStat):
822 """ Checks for an existing directory. """
823 def __init__(self, sPath):
824 tdStepStat.__init__(self, sPath = sPath, fFound = False);
825
826class tdStepStatPathNotFound(tdStepStat):
827 """ Checks for an existing directory. """
828 def __init__(self, sPath):
829 tdStepStat.__init__(self, sPath = sPath, fFound = False);
830
831
832#
833#
834#
835
836class tdTestSessionFileRefs(tdTestGuestCtrlBase):
837 """
838 Tests session file (IGuestFile) reference counting.
839 """
840 def __init__(self, cRefs = 0):
841 tdTestGuestCtrlBase.__init__(self);
842 self.cRefs = cRefs;
843
844class tdTestSessionDirRefs(tdTestGuestCtrlBase):
845 """
846 Tests session directory (IGuestDirectory) reference counting.
847 """
848 def __init__(self, cRefs = 0):
849 tdTestGuestCtrlBase.__init__(self);
850 self.cRefs = cRefs;
851
852class tdTestSessionProcRefs(tdTestGuestCtrlBase):
853 """
854 Tests session process (IGuestProcess) reference counting.
855 """
856 def __init__(self, cRefs = 0):
857 tdTestGuestCtrlBase.__init__(self);
858 self.cRefs = cRefs;
859
860class tdTestUpdateAdditions(tdTestGuestCtrlBase):
861 """
862 Test updating the Guest Additions inside the guest.
863 """
864 def __init__(self, sSrc = "", asArgs = None, fFlags = None,
865 sUser = None, sPassword = None, sDomain = None):
866 tdTestGuestCtrlBase.__init__(self);
867 self.oCreds = tdCtxCreds(sUser, sPassword, sDomain);
868 self.sSrc = sSrc;
869 self.asArgs = asArgs;
870 self.fFlags = fFlags;
871
872class tdTestResult(object):
873 """
874 Base class for test results.
875 """
876 def __init__(self, fRc = False):
877 ## The overall test result.
878 self.fRc = fRc;
879
880class tdTestResultFailure(tdTestResult):
881 """
882 Base class for test results.
883 """
884 def __init__(self):
885 tdTestResult.__init__(self, fRc = False);
886
887class tdTestResultSuccess(tdTestResult):
888 """
889 Base class for test results.
890 """
891 def __init__(self):
892 tdTestResult.__init__(self, fRc = True);
893
894class tdTestResultDirRead(tdTestResult):
895 """
896 Test result for reading guest directories.
897 """
898 def __init__(self, fRc = False, cFiles = 0, cDirs = 0, cOthers = None):
899 tdTestResult.__init__(self, fRc = fRc);
900 self.cFiles = cFiles;
901 self.cDirs = cDirs;
902 self.cOthers = cOthers;
903
904class tdTestResultExec(tdTestResult):
905 """
906 Holds a guest process execution test result,
907 including the exit code, status + fFlags.
908 """
909 def __init__(self, fRc = False, uExitStatus = 500, iExitCode = 0, sBuf = None, cbBuf = 0, cbStdOut = None, cbStdErr = None):
910 tdTestResult.__init__(self);
911 ## The overall test result.
912 self.fRc = fRc;
913 ## Process exit stuff.
914 self.uExitStatus = uExitStatus;
915 self.iExitCode = iExitCode;
916 ## Desired buffer length returned back from stdout/stderr.
917 self.cbBuf = cbBuf;
918 ## Desired buffer result from stdout/stderr. Use with caution!
919 self.sBuf = sBuf;
920 self.cbStdOut = cbStdOut;
921 self.cbStdErr = cbStdErr;
922
923class tdTestResultFileStat(tdTestResult):
924 """
925 Test result for stat'ing guest files.
926 """
927 def __init__(self, fRc = False,
928 cbSize = 0, eFileType = 0):
929 tdTestResult.__init__(self, fRc = fRc);
930 self.cbSize = cbSize;
931 self.eFileType = eFileType;
932 ## @todo Add more information.
933
934class tdTestResultFileReadWrite(tdTestResult):
935 """
936 Test result for reading + writing guest directories.
937 """
938 def __init__(self, fRc = False,
939 cbProcessed = 0, offFile = 0, abBuf = None):
940 tdTestResult.__init__(self, fRc = fRc);
941 self.cbProcessed = cbProcessed;
942 self.offFile = offFile;
943 self.abBuf = abBuf;
944
945class tdTestResultSession(tdTestResult):
946 """
947 Test result for guest session counts.
948 """
949 def __init__(self, fRc = False, cNumSessions = 0):
950 tdTestResult.__init__(self, fRc = fRc);
951 self.cNumSessions = cNumSessions;
952
953
954class SubTstDrvAddGuestCtrl(base.SubTestDriverBase):
955 """
956 Sub-test driver for executing guest control (VBoxService, IGuest) tests.
957 """
958
959 def __init__(self, oTstDrv):
960 base.SubTestDriverBase.__init__(self, oTstDrv, 'add-guest-ctrl', 'Guest Control');
961
962 ## @todo base.TestBase.
963 self.asTestsDef = [
964 'session_basic', 'session_env', 'session_file_ref', 'session_dir_ref', 'session_proc_ref', 'session_reboot',
965 'exec_basic', 'exec_timeout',
966 'dir_create', 'dir_create_temp', 'dir_read',
967 'file_remove', 'file_stat', 'file_read', 'file_write',
968 'copy_to', 'copy_from',
969 'update_additions'
970 ];
971 self.asTests = self.asTestsDef;
972 self.asRsrcs = ['5.3/guestctrl/50mb_rnd.dat', ];
973 self.oTestFiles = None # type: vboxtestfileset.TestFileSet
974
975 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
976 if asArgs[iArg] == '--add-guest-ctrl-tests':
977 iArg += 1;
978 iNext = self.oTstDrv.requireMoreArgs(1, asArgs, iArg);
979 if asArgs[iArg] == 'all': # Nice for debugging scripts.
980 self.asTests = self.asTestsDef;
981 else:
982 self.asTests = asArgs[iArg].split(':');
983 for s in self.asTests:
984 if s not in self.asTestsDef:
985 raise base.InvalidOption('The "--add-guest-ctrl-tests" value "%s" is not valid; valid values are: %s'
986 % (s, ' '.join(self.asTestsDef)));
987 return iNext;
988 return iArg;
989
990 def showUsage(self):
991 base.SubTestDriverBase.showUsage(self);
992 reporter.log(' --add-guest-ctrl-tests <s1[:s2[:]]>');
993 reporter.log(' Default: %s (all)' % (':'.join(self.asTestsDef)));
994 return True;
995
996 def testIt(self, oTestVm, oSession, oTxsSession):
997 """
998 Executes the test.
999
1000 Returns fRc, oTxsSession. The latter may have changed.
1001 """
1002 reporter.log("Active tests: %s" % (self.asTests,));
1003
1004 # The tests. Must-succeed tests should be first.
1005 atTests = [
1006 ( True, self.prepareGuestForTesting, None, 'Preparations',),
1007 ( True, self.testGuestCtrlSession, 'session_basic', 'Session Basics',),
1008 ( True, self.testGuestCtrlExec, 'exec_basic', 'Execution',),
1009 ( False, self.testGuestCtrlExecTimeout, 'exec_timeout', 'Execution Timeouts',),
1010 ( False, self.testGuestCtrlSessionEnvironment, 'session_env', 'Session Environment',),
1011 ( False, self.testGuestCtrlSessionFileRefs, 'session_file_ref', 'Session File References',),
1012 #( False, self.testGuestCtrlSessionDirRefs, 'session_dir_ref', 'Session Directory References',),
1013 ( False, self.testGuestCtrlSessionProcRefs, 'session_proc_ref', 'Session Process References',),
1014 ( False, self.testGuestCtrlDirCreate, 'dir_create', 'Creating directories',),
1015 ( False, self.testGuestCtrlDirCreateTemp, 'dir_create_temp', 'Creating temporary directories',),
1016 ( False, self.testGuestCtrlDirRead, 'dir_read', 'Reading directories',),
1017 ( False, self.testGuestCtrlCopyTo, 'copy_to', 'Copy to guest',),
1018 ( False, self.testGuestCtrlCopyFrom, 'copy_from', 'Copy from guest',),
1019 ( False, self.testGuestCtrlFileStat, 'file_stat', 'Querying file information (stat)',),
1020 ( False, self.testGuestCtrlFileRead, 'file_read', 'File read',),
1021 ( False, self.testGuestCtrlFileWrite, 'file_write', 'File write',),
1022 ( False, self.testGuestCtrlFileRemove, 'file_remove', 'Removing files',), # Destroys prepped files.
1023 ( False, self.testGuestCtrlSessionReboot, 'session_reboot', 'Session w/ Guest Reboot',), # May zap /tmp.
1024 ( False, self.testGuestCtrlUpdateAdditions, 'update_additions', 'Updating Guest Additions',),
1025 ];
1026
1027 fRc = True;
1028 for fMustSucceed, fnHandler, sShortNm, sTestNm in atTests:
1029 reporter.testStart(sTestNm);
1030
1031 if sShortNm is None or sShortNm in self.asTests:
1032 # Returns (fRc, oTxsSession, oSession) - but only the first one is mandatory.
1033 aoResult = fnHandler(oSession, oTxsSession, oTestVm);
1034 if aoResult is None or isinstance(aoResult, bool):
1035 fRcTest = aoResult;
1036 else:
1037 fRcTest = aoResult[0];
1038 if len(aoResult) > 1:
1039 oTxsSession = aoResult[1];
1040 if len(aoResult) > 2:
1041 oSession = aoResult[2];
1042 assert len(aoResult) == 3;
1043 else:
1044 fRcTest = None;
1045
1046 if fRcTest is False and reporter.testErrorCount() == 0:
1047 fRcTest = reporter.error('Buggy test! Returned False w/o logging the error!');
1048 if reporter.testDone(fRcTest is None)[1] != 0:
1049 fRcTest = False;
1050 fRc = False;
1051
1052 # Stop execution if this is a must-succeed test and it failed.
1053 if fRcTest is False and fMustSucceed is True:
1054 reporter.log('Skipping any remaining tests since the previous one failed.');
1055 break;
1056
1057 return (fRc, oTxsSession);
1058
1059 #
1060 # Guest locations.
1061 #
1062
1063 @staticmethod
1064 def getGuestTempDir(oTestVm):
1065 """
1066 Helper for finding a temporary directory in the test VM.
1067
1068 Note! It may be necessary to create it!
1069 """
1070 if oTestVm.isWindows():
1071 return "C:\\Temp";
1072 if oTestVm.isOS2():
1073 return "C:\\Temp";
1074 return '/var/tmp';
1075
1076 @staticmethod
1077 def getGuestSystemDir(oTestVm):
1078 """
1079 Helper for finding a system directory in the test VM that we can play around with.
1080
1081 On Windows this is always the System32 directory, so this function can be used as
1082 basis for locating other files in or under that directory.
1083 """
1084 if oTestVm.isWindows():
1085 if oTestVm.sKind in ['WindowsNT4', 'WindowsNT3x',]:
1086 return 'C:\\Winnt\\System32';
1087 return 'C:\\Windows\\System32';
1088 if oTestVm.isOS2():
1089 return 'C:\\OS2\\DLL';
1090 return "/bin";
1091
1092 @staticmethod
1093 def getGuestSystemShell(oTestVm):
1094 """
1095 Helper for finding the default system shell in the test VM.
1096 """
1097 if oTestVm.isWindows():
1098 return SubTstDrvAddGuestCtrl.getGuestSystemDir(oTestVm) + '\\cmd.exe';
1099 if oTestVm.isOS2():
1100 return SubTstDrvAddGuestCtrl.getGuestSystemDir(oTestVm) + '\\..\\CMD.EXE';
1101 return "/bin/sh";
1102
1103 @staticmethod
1104 def getGuestSystemFileForReading(oTestVm):
1105 """
1106 Helper for finding a file in the test VM that we can read.
1107 """
1108 if oTestVm.isWindows():
1109 return SubTstDrvAddGuestCtrl.getGuestSystemDir(oTestVm) + '\\ntdll.dll';
1110 if oTestVm.isOS2():
1111 return SubTstDrvAddGuestCtrl.getGuestSystemDir(oTestVm) + '\\DOSCALL1.DLL';
1112 return "/bin/sh";
1113
1114 #
1115 # Guest test files.
1116 #
1117
1118 def prepareGuestForTesting(self, oSession, oTxsSession, oTestVm):
1119 """
1120 Prepares the VM for testing, uploading a bunch of files and stuff via TXS.
1121 Returns success indicator.
1122 """
1123 _ = oSession;
1124
1125 #reporter.log('Take snapshot now!');
1126 #self.oTstDrv.sleep(22);
1127 #return False;
1128
1129 # Make sure the temporary directory exists.
1130 for sDir in [self.getGuestTempDir(oTestVm), ]:
1131 if oTxsSession.syncMkDirPath(sDir, 0o777) is not True:
1132 return reporter.error('Failed to create directory "%s"!' % (sDir,));
1133
1134 # Generate and upload some random files and dirs to the guest:
1135 self.oTestFiles = vboxtestfileset.TestFileSet(oTestVm, self.getGuestTempDir(oTestVm), 'addgst-1');
1136 return self.oTestFiles.upload(oTxsSession, self.oTstDrv);
1137
1138
1139 #
1140 # gctrlXxxx stuff.
1141 #
1142
1143 def gctrlCopyFileFrom(self, oGuestSession, sSrc, sDst, fFlags, fExpected):
1144 """
1145 Helper function to copy a single file from the guest to the host.
1146 """
1147 reporter.log2('Copying guest file "%s" to host "%s"' % (sSrc, sDst));
1148 try:
1149 if self.oTstDrv.fpApiVer >= 5.0:
1150 oCurProgress = oGuestSession.fileCopyFromGuest(sSrc, sDst, fFlags);
1151 else:
1152 oCurProgress = oGuestSession.copyFrom(sSrc, sDst, fFlags);
1153 except:
1154 reporter.maybeErrXcpt(fExpected, 'Copy from exception for sSrc="%s", sDst="%s":' % (sSrc, sDst,));
1155 return False;
1156 if oCurProgress is None:
1157 return reporter.error('No progress object returned');
1158 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlFileCopyFrom");
1159 oProgress.wait();
1160 if not oProgress.isSuccess():
1161 oProgress.logResult(fIgnoreErrors = not fExpected);
1162 return False;
1163 return True;
1164
1165 def gctrlCopyDirFrom(self, oGuestSession, sSrc, sDst, fFlags, fExpected):
1166 """
1167 Helper function to copy a directory from the guest to the host.
1168 """
1169 reporter.log2('Copying guest dir "%s" to host "%s"' % (sSrc, sDst));
1170 try:
1171 oCurProgress = oGuestSession.directoryCopyFromGuest(sSrc, sDst, fFlags);
1172 except:
1173 reporter.maybeErrXcpt(fExpected, 'Copy dir from exception for sSrc="%s", sDst="%s":' % (sSrc, sDst,));
1174 return False;
1175 if oCurProgress is None:
1176 return reporter.error('No progress object returned');
1177
1178 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlDirCopyFrom");
1179 oProgress.wait();
1180 if not oProgress.isSuccess():
1181 oProgress.logResult(fIgnoreErrors = not fExpected);
1182 return False;
1183 return True;
1184
1185 def gctrlCopyFileTo(self, oGuestSession, sSrc, sDst, fFlags, fIsError):
1186 """
1187 Helper function to copy a single file from the host to the guest.
1188 """
1189 reporter.log2('Copying host file "%s" to guest "%s" (flags %s)' % (sSrc, sDst, fFlags));
1190 try:
1191 if self.oTstDrv.fpApiVer >= 5.0:
1192 oCurProgress = oGuestSession.fileCopyToGuest(sSrc, sDst, fFlags);
1193 else:
1194 oCurProgress = oGuestSession.copyTo(sSrc, sDst, fFlags);
1195 except:
1196 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1197 return False;
1198
1199 if oCurProgress is None:
1200 return reporter.error('No progress object returned');
1201 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1202
1203 try:
1204 oProgress.wait();
1205 if not oProgress.isSuccess():
1206 oProgress.logResult(fIgnoreErrors = not fIsError);
1207 return False;
1208 except:
1209 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1210 return False;
1211 return True;
1212
1213 def gctrlCopyDirTo(self, oGuestSession, sSrc, sDst, fFlags, fIsError):
1214 """
1215 Helper function to copy a directory tree from the host to the guest.
1216 """
1217 reporter.log2('Copying host directory "%s" to guest "%s" (flags %s)' % (sSrc, sDst, fFlags));
1218 try:
1219 oCurProgress = oGuestSession.directoryCopyToGuest(sSrc, sDst, fFlags);
1220 except:
1221 reporter.maybeErrXcpt(fIsError, 'sSrc=%s sDst=%s' % (sSrc, sDst,));
1222 return False;
1223
1224 if oCurProgress is None:
1225 return reporter.error('No progress object returned');
1226 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlCopyFileTo");
1227
1228 try:
1229 oProgress.wait();
1230 if not oProgress.isSuccess():
1231 oProgress.logResult(fIgnoreErrors = not fIsError);
1232 return False;
1233 except:
1234 reporter.maybeErrXcpt(fIsError, 'Wait exception for sSrc="%s", sDst="%s":' % (sSrc, sDst));
1235 return False;
1236 return True;
1237
1238 def gctrlCreateDir(self, oTest, oRes, oGuestSession):
1239 """
1240 Helper function to create a guest directory specified in the current test.
1241 """
1242 reporter.log2('Creating directory "%s"' % (oTest.sDirectory,));
1243 try:
1244 oGuestSession.directoryCreate(oTest.sDirectory, oTest.fMode, oTest.fFlags);
1245 except:
1246 reporter.maybeErrXcpt(oRes.fRc, 'Failed to create "%s" fMode=%o fFlags=%s'
1247 % (oTest.sDirectory, oTest.fMode, oTest.fFlags,));
1248 return not oRes.fRc;
1249 if oRes.fRc is not True:
1250 return reporter.error('Did not expect to create directory "%s"!' % (oTest.sDirectory,));
1251
1252 # Check if the directory now exists.
1253 try:
1254 if self.oTstDrv.fpApiVer >= 5.0:
1255 fDirExists = oGuestSession.directoryExists(oTest.sDirectory, False);
1256 else:
1257 fDirExists = oGuestSession.directoryExists(oTest.sDirectory);
1258 except:
1259 return reporter.errorXcpt('directoryExists failed on "%s"!' % (oTest.sDirectory,));
1260 if not fDirExists:
1261 return reporter.errorXcpt('directoryExists returned False on "%s" after directoryCreate succeeded!'
1262 % (oTest.sDirectory,));
1263 return True;
1264
1265 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, sSubDir = None):
1266 """
1267 Helper function to recursively read a guest directory tree specified in the current test.
1268 """
1269 sDir = oTest.sDirectory;
1270 sFilter = oTest.sFilter;
1271 fFlags = oTest.fFlags;
1272 oTestVm = oTest.oCreds.oTestVm;
1273 sCurDir = oTestVm.pathJoin(sDir, sSubDir) if sSubDir else sDir;
1274
1275 fRc = True; # Be optimistic.
1276 cDirs = 0; # Number of directories read.
1277 cFiles = 0; # Number of files read.
1278 cOthers = 0; # Other files.
1279
1280 ##
1281 ## @todo r=bird: Unlike fileOpen, directoryOpen will not fail if the directory does not exist.
1282 ## This is of course a bug in the implementation, as it is documented to return
1283 ## VBOX_E_OBJECT_NOT_FOUND or VBOX_E_IPRT_ERROR!
1284 ##
1285
1286 # Open the directory:
1287 #reporter.log2('Directory="%s", filter="%s", fFlags="%s"' % (sCurDir, sFilter, fFlags));
1288 try:
1289 oCurDir = oGuestSession.directoryOpen(sCurDir, sFilter, fFlags);
1290 except:
1291 reporter.maybeErrXcpt(fIsError, 'sCurDir=%s sFilter=%s fFlags=%s' % (sCurDir, sFilter, fFlags,))
1292 return (False, 0, 0, 0);
1293
1294 # Read the directory.
1295 while fRc is True:
1296 try:
1297 oFsObjInfo = oCurDir.read();
1298 except Exception as oXcpt:
1299 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1300 ##
1301 ## @todo r=bird: Change this to reporter.errorXcpt() once directoryOpen() starts
1302 ## working the way it is documented.
1303 ##
1304 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,)); # See above why 'maybe'.
1305 fRc = False;
1306 #else: reporter.log2('\tNo more directory entries for "%s"' % (sCurDir,));
1307 break;
1308
1309 try:
1310 sName = oFsObjInfo.name;
1311 eType = oFsObjInfo.type;
1312 except:
1313 fRc = reporter.errorXcpt();
1314 break;
1315
1316 if sName in ('.', '..', ):
1317 if eType != vboxcon.FsObjType_Directory:
1318 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1319 % (sName, eType, vboxcon.FsObjType_Directory));
1320 elif eType == vboxcon.FsObjType_Directory:
1321 #reporter.log2(' Directory "%s"' % oFsObjInfo.name);
1322 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError,
1323 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName);
1324 fRc = aSubResult[0];
1325 cDirs += aSubResult[1] + 1;
1326 cFiles += aSubResult[2];
1327 cOthers += aSubResult[3];
1328 elif eType is vboxcon.FsObjType_File:
1329 #reporter.log2(' File "%s"' % oFsObjInfo.name);
1330 cFiles += 1;
1331 elif eType is vboxcon.FsObjType_Symlink:
1332 #reporter.log2(' Symlink "%s" -- not tested yet' % oFsObjInfo.name);
1333 cOthers += 1;
1334 elif oTestVm.isWindows() \
1335 or oTestVm.isOS2() \
1336 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock,
1337 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut):
1338 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' %
1339 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,));
1340 else:
1341 cOthers += 1;
1342
1343 # Close the directory
1344 try:
1345 oCurDir.close();
1346 except:
1347 fRc = reporter.errorXcpt('sCurDir=%s' % (sCurDir));
1348
1349 return (fRc, cDirs, cFiles, cOthers);
1350
1351 def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (vboxtestfileset.GstDir) -> bool
1352 """
1353 Helper function to recursively read a guest directory tree specified in the current test.
1354 """
1355
1356 #
1357 # Process the directory.
1358 #
1359
1360 # Open the directory:
1361 try:
1362 oCurDir = oGuestSession.directoryOpen(oDir.sPath, '', None);
1363 except:
1364 return reporter.errorXcpt('sPath=%s' % (oDir.sPath,));
1365
1366 # Read the directory.
1367 dLeftUpper = dict(oDir.dChildrenUpper);
1368 cDot = 0;
1369 cDotDot = 0;
1370 fRc = True;
1371 while True:
1372 try:
1373 oFsObjInfo = oCurDir.read();
1374 except Exception as oXcpt:
1375 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
1376 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath,));
1377 break;
1378
1379 try:
1380 sName = oFsObjInfo.name;
1381 eType = oFsObjInfo.type;
1382 cbFile = oFsObjInfo.objectSize;
1383 ## @todo check further attributes.
1384 except:
1385 fRc = reporter.errorXcpt();
1386 break;
1387
1388 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment:
1389 if sName in ('.', '..', ):
1390 if eType != vboxcon.FsObjType_Directory:
1391 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
1392 % (sName, eType, vboxcon.FsObjType_Directory));
1393 if sName == '.': cDot += 1;
1394 else: cDotDot += 1;
1395 else:
1396 # Find the child and remove it from the dictionary.
1397 sNameUpper = sName.upper();
1398 oFsObj = dLeftUpper.get(sNameUpper);
1399 if oFsObj is None:
1400 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!'
1401 % (sName, oDir.sPath, eType, cbFile,));
1402 else:
1403 del dLeftUpper[sNameUpper];
1404
1405 # Check type
1406 if isinstance(oFsObj, vboxtestfileset.GstDir):
1407 if eType != vboxcon.FsObjType_Directory:
1408 fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
1409 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
1410 elif isinstance(oFsObj, vboxtestfileset.GstFile):
1411 if eType != vboxcon.FsObjType_File:
1412 fRc = reporter.error('%s: expected file (%d), got eType=%d!'
1413 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,));
1414 else:
1415 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),));
1416
1417 # Check the name.
1418 if oFsObj.sName != sName:
1419 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,));
1420
1421 # Check the size if a file.
1422 if isinstance(oFsObj, vboxtestfileset.GstFile) and cbFile != oFsObj.cbContent:
1423 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,));
1424
1425 ## @todo check timestamps and attributes.
1426
1427 # Close the directory
1428 try:
1429 oCurDir.close();
1430 except:
1431 fRc = reporter.errorXcpt('oDir.sPath=%s' % (oDir.sPath,));
1432
1433 # Any files left over?
1434 for sKey in dLeftUpper:
1435 oFsObj = dLeftUpper[sKey];
1436 fRc = reporter.error('%s: Was not returned! (%s)' % (oFsObj.sPath, type(oFsObj),));
1437
1438 # Check the dot and dot-dot counts.
1439 if cDot != 1:
1440 fRc = reporter.error('%s: Found %s "." entries, expected exactly 1!' % (oDir.sPath, cDot,));
1441 if cDotDot != 1:
1442 fRc = reporter.error('%s: Found %s ".." entries, expected exactly 1!' % (oDir.sPath, cDotDot,));
1443
1444 #
1445 # Recurse into subdirectories using info from oDir.
1446 #
1447 for oFsObj in oDir.aoChildren:
1448 if isinstance(oFsObj, vboxtestfileset.GstDir):
1449 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc;
1450
1451 return fRc;
1452
1453 def gctrlExecDoTest(self, i, oTest, oRes, oGuestSession):
1454 """
1455 Wrapper function around gctrlExecute to provide more sanity checking
1456 when needed in actual execution tests.
1457 """
1458 reporter.log('Testing #%d, cmd="%s" ...' % (i, oTest.sCmd));
1459 fRcExec = self.gctrlExecute(oTest, oGuestSession, oRes.fRc);
1460 if fRcExec == oRes.fRc:
1461 fRc = True;
1462 if fRcExec is True:
1463 # Compare exit status / code on successful process execution.
1464 if oTest.uExitStatus != oRes.uExitStatus \
1465 or oTest.iExitCode != oRes.iExitCode:
1466 fRc = reporter.error('Test #%d (%s) failed: Got exit status + code %d,%d, expected %d,%d'
1467 % (i, oTest.asArgs, oTest.uExitStatus, oTest.iExitCode,
1468 oRes.uExitStatus, oRes.iExitCode));
1469
1470 # Compare test / result buffers on successful process execution.
1471 if oTest.sBuf is not None and oRes.sBuf is not None:
1472 if not utils.areBytesEqual(oTest.sBuf, oRes.sBuf):
1473 fRc = reporter.error('Test #%d (%s) failed: Got buffer\n%s (%d bytes), expected\n%s (%d bytes)'
1474 % (i, oTest.asArgs,
1475 map(hex, map(ord, oTest.sBuf)), len(oTest.sBuf),
1476 map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf)));
1477 reporter.log2('Test #%d passed: Buffers match (%d bytes)' % (i, len(oRes.sBuf)));
1478 elif oRes.sBuf and not oTest.sBuf:
1479 fRc = reporter.error('Test #%d (%s) failed: Got no buffer data, expected\n%s (%dbytes)' %
1480 (i, oTest.asArgs, map(hex, map(ord, oRes.sBuf)), len(oRes.sBuf),));
1481
1482 if oRes.cbStdOut is not None and oRes.cbStdOut != oTest.cbStdOut:
1483 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stdout data, expected %d'
1484 % (i, oTest.asArgs, oTest.cbStdOut, oRes.cbStdOut));
1485 if oRes.cbStdErr is not None and oRes.cbStdErr != oTest.cbStdErr:
1486 fRc = reporter.error('Test #%d (%s) failed: Got %d bytes of stderr data, expected %d'
1487 % (i, oTest.asArgs, oTest.cbStdErr, oRes.cbStdErr));
1488 else:
1489 fRc = reporter.error('Test #%d (%s) failed: Got %s, expected %s' % (i, oTest.asArgs, fRcExec, oRes.fRc));
1490 return fRc;
1491
1492 def gctrlExecute(self, oTest, oGuestSession, fIsError):
1493 """
1494 Helper function to execute a program on a guest, specified in the current test.
1495
1496 Note! This weirdo returns results (process exitcode and status) in oTest.
1497 """
1498 fRc = True; # Be optimistic.
1499
1500 # Reset the weird result stuff:
1501 oTest.cbStdOut = 0;
1502 oTest.cbStdErr = 0;
1503 oTest.sBuf = '';
1504 oTest.uExitStatus = 0;
1505 oTest.iExitCode = 0;
1506
1507 ## @todo Compare execution timeouts!
1508 #tsStart = base.timestampMilli();
1509
1510 try:
1511 reporter.log2('Using session user=%s, sDomain=%s, name=%s, timeout=%d'
1512 % (oGuestSession.user, oGuestSession.domain, oGuestSession.name, oGuestSession.timeout,));
1513 except:
1514 return reporter.errorXcpt();
1515
1516 #
1517 # Start the process:
1518 #
1519 reporter.log2('Executing sCmd=%s, fFlags=%s, timeoutMS=%d, asArgs=%s, asEnv=%s'
1520 % (oTest.sCmd, oTest.fFlags, oTest.timeoutMS, oTest.asArgs, oTest.aEnv,));
1521 try:
1522 oProcess = oGuestSession.processCreate(oTest.sCmd,
1523 oTest.asArgs if self.oTstDrv.fpApiVer >= 5.0 else oTest.asArgs[1:],
1524 oTest.aEnv, oTest.fFlags, oTest.timeoutMS);
1525 except:
1526 reporter.maybeErrXcpt(fIsError, 'asArgs=%s' % (oTest.asArgs,));
1527 return False;
1528 if oProcess is None:
1529 return reporter.error('oProcess is None! (%s)' % (oTest.asArgs,));
1530
1531 #time.sleep(5); # try this if you want to see races here.
1532
1533 # Wait for the process to start properly:
1534 reporter.log2('Process start requested, waiting for start (%dms) ...' % (oTest.timeoutMS,));
1535 iPid = -1;
1536 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Start, ];
1537 try:
1538 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
1539 except:
1540 reporter.maybeErrXcpt(fIsError, 'waitforArray failed for asArgs=%s' % (oTest.asArgs,));
1541 fRc = False;
1542 else:
1543 try:
1544 eStatus = oProcess.status;
1545 iPid = oProcess.PID;
1546 except:
1547 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1548 else:
1549 reporter.log2('Wait result returned: %d, current process status is: %d' % (eWaitResult, eStatus,));
1550
1551 #
1552 # Wait for the process to run to completion if necessary.
1553 #
1554 # Note! The above eWaitResult return value can be ignored as it will
1555 # (mostly) reflect the process status anyway.
1556 #
1557 if eStatus == vboxcon.ProcessStatus_Started:
1558
1559 # What to wait for:
1560 aeWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate, ];
1561 if vboxcon.ProcessCreateFlag_WaitForStdOut in oTest.fFlags:
1562 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdOut);
1563 if vboxcon.ProcessCreateFlag_WaitForStdErr in oTest.fFlags:
1564 aeWaitFor.append(vboxcon.ProcessWaitForFlag_StdErr);
1565 ## @todo Add vboxcon.ProcessWaitForFlag_StdIn.
1566
1567 reporter.log2('Process (PID %d) started, waiting for termination (%dms), aeWaitFor=%s ...'
1568 % (iPid, oTest.timeoutMS, aeWaitFor));
1569 acbFdOut = [0,0,0];
1570 while True:
1571 try:
1572 eWaitResult = oProcess.waitForArray(aeWaitFor, oTest.timeoutMS);
1573 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
1574 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
1575 try: oProcess.close();
1576 except: pass;
1577 break;
1578 except:
1579 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1580 break;
1581 reporter.log2('Wait returned: %d' % (eWaitResult,));
1582
1583 # Process output:
1584 for eFdResult, iFd, sFdNm in [ (vboxcon.ProcessWaitResult_StdOut, 1, 'stdout'),
1585 (vboxcon.ProcessWaitResult_StdErr, 2, 'stderr'), ]:
1586 if eWaitResult in (eFdResult, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
1587 reporter.log2('Reading %s ...' % (sFdNm,));
1588 try:
1589 abBuf = oProcess.Read(1, 64 * 1024, oTest.timeoutMS);
1590 except KeyboardInterrupt: # Not sure how helpful this is, but whatever.
1591 reporter.error('Process (PID %d) execution interrupted' % (iPid,));
1592 try: oProcess.close();
1593 except: pass;
1594 except:
1595 pass; ## @todo test for timeouts and fail on anything else!
1596 else:
1597 if abBuf:
1598 reporter.log2('Process (PID %d) got %d bytes of %s data' % (iPid, len(abBuf), sFdNm,));
1599 acbFdOut[iFd] += len(abBuf);
1600 oTest.sBuf = abBuf; ## @todo Figure out how to uniform + append!
1601
1602 ## Process input (todo):
1603 #if eWaitResult in (vboxcon.ProcessWaitResult_StdIn, vboxcon.ProcessWaitResult_WaitFlagNotSupported):
1604 # reporter.log2('Process (PID %d) needs stdin data' % (iPid,));
1605
1606 # Termination or error?
1607 if eWaitResult in (vboxcon.ProcessWaitResult_Terminate,
1608 vboxcon.ProcessWaitResult_Error,
1609 vboxcon.ProcessWaitResult_Timeout,):
1610 try: eStatus = oProcess.status;
1611 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1612 reporter.log2('Process (PID %d) reported terminate/error/timeout: %d, status: %d'
1613 % (iPid, eWaitResult, eStatus,));
1614 break;
1615
1616 # End of the wait loop.
1617 _, oTest.cbStdOut, oTest.cbStdErr = acbFdOut;
1618
1619 try: eStatus = oProcess.status;
1620 except: fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1621 reporter.log2('Final process status (PID %d) is: %d' % (iPid, eStatus));
1622 reporter.log2('Process (PID %d) %d stdout, %d stderr' % (iPid, oTest.cbStdOut, oTest.cbStdErr));
1623
1624 #
1625 # Get the final status and exit code of the process.
1626 #
1627 try:
1628 oTest.uExitStatus = oProcess.status;
1629 oTest.iExitCode = oProcess.exitCode;
1630 except:
1631 fRc = reporter.errorXcpt('asArgs=%s' % (oTest.asArgs,));
1632 reporter.log2('Process (PID %d) has exit code: %d; status: %d ' % (iPid, oTest.iExitCode, oTest.uExitStatus));
1633 return fRc;
1634
1635 def testGuestCtrlSessionEnvironment(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
1636 """
1637 Tests the guest session environment changes.
1638 """
1639 aoTests = [
1640 # Check basic operations.
1641 tdTestSessionEx([ # Initial environment is empty.
1642 tdStepSessionCheckEnv(),
1643 # Check clearing empty env.
1644 tdStepSessionClearEnv(),
1645 tdStepSessionCheckEnv(),
1646 # Check set.
1647 tdStepSessionSetEnv('FOO', 'BAR'),
1648 tdStepSessionCheckEnv(['FOO=BAR',]),
1649 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
1650 tdStepSessionClearEnv(),
1651 tdStepSessionCheckEnv(),
1652 # Check unset.
1653 tdStepSessionUnsetEnv('BAR'),
1654 tdStepSessionCheckEnv(['BAR']),
1655 tdStepSessionClearEnv(),
1656 tdStepSessionCheckEnv(),
1657 # Set + unset.
1658 tdStepSessionSetEnv('FOO', 'BAR'),
1659 tdStepSessionCheckEnv(['FOO=BAR',]),
1660 tdStepSessionUnsetEnv('FOO'),
1661 tdStepSessionCheckEnv(['FOO']),
1662 # Bulk environment changes (via attrib) (shall replace existing 'FOO').
1663 tdStepSessionBulkEnv( ['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
1664 tdStepSessionCheckEnv(['PATH=/bin:/usr/bin', 'TMPDIR=/var/tmp', 'USER=root']),
1665 ]),
1666 tdTestSessionEx([ # Check that setting the same value several times works.
1667 tdStepSessionSetEnv('FOO','BAR'),
1668 tdStepSessionCheckEnv([ 'FOO=BAR',]),
1669 tdStepSessionSetEnv('FOO','BAR2'),
1670 tdStepSessionCheckEnv([ 'FOO=BAR2',]),
1671 tdStepSessionSetEnv('FOO','BAR3'),
1672 tdStepSessionCheckEnv([ 'FOO=BAR3',]),
1673 tdStepRequireMinimumApiVer(5.0), # 4.3 can't cope with the remainder.
1674 # Add a little unsetting to the mix.
1675 tdStepSessionSetEnv('BAR', 'BEAR'),
1676 tdStepSessionCheckEnv([ 'FOO=BAR3', 'BAR=BEAR',]),
1677 tdStepSessionUnsetEnv('FOO'),
1678 tdStepSessionCheckEnv([ 'FOO', 'BAR=BEAR',]),
1679 tdStepSessionSetEnv('FOO','BAR4'),
1680 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR',]),
1681 # The environment is case sensitive.
1682 tdStepSessionSetEnv('foo','BAR5'),
1683 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo=BAR5']),
1684 tdStepSessionUnsetEnv('foo'),
1685 tdStepSessionCheckEnv([ 'FOO=BAR4', 'BAR=BEAR', 'foo']),
1686 ]),
1687 tdTestSessionEx([ # Bulk settings merges stuff, last entry standing.
1688 tdStepSessionBulkEnv(['FOO=bar', 'foo=bar', 'FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
1689 tdStepSessionCheckEnv(['FOO=doofus', 'TMPDIR=/tmp', 'foo=bar2']),
1690 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
1691 tdStepSessionBulkEnv(['2=1+1', 'FOO=doofus2', ]),
1692 tdStepSessionCheckEnv(['2=1+1', 'FOO=doofus2' ]),
1693 ]),
1694 # Invalid variable names.
1695 tdTestSessionEx([
1696 tdStepSessionSetEnv('', 'FOO', vbox.ComError.E_INVALIDARG),
1697 tdStepSessionCheckEnv(),
1698 tdStepRequireMinimumApiVer(5.0), # 4.3 is too relaxed checking input!
1699 tdStepSessionSetEnv('=', '===', vbox.ComError.E_INVALIDARG),
1700 tdStepSessionCheckEnv(),
1701 tdStepSessionSetEnv('FOO=', 'BAR', vbox.ComError.E_INVALIDARG),
1702 tdStepSessionCheckEnv(),
1703 tdStepSessionSetEnv('=FOO', 'BAR', vbox.ComError.E_INVALIDARG),
1704 tdStepSessionCheckEnv(),
1705 tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy and too relaxed!
1706 tdStepSessionBulkEnv(['', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1707 tdStepSessionCheckEnv(),
1708 tdStepSessionBulkEnv(['=', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1709 tdStepSessionCheckEnv(),
1710 tdStepSessionBulkEnv(['=FOO', 'foo=bar'], vbox.ComError.E_INVALIDARG),
1711 tdStepSessionCheckEnv(),
1712 ]),
1713 # A bit more weird keys/values.
1714 tdTestSessionEx([ tdStepSessionSetEnv('$$$', ''),
1715 tdStepSessionCheckEnv([ '$$$=',]), ]),
1716 tdTestSessionEx([ tdStepSessionSetEnv('$$$', '%%%'),
1717 tdStepSessionCheckEnv([ '$$$=%%%',]),
1718 ]),
1719 tdTestSessionEx([ tdStepRequireMinimumApiVer(5.0), # 4.3 is buggy!
1720 tdStepSessionSetEnv(u'ß$%ß&', ''),
1721 tdStepSessionCheckEnv([ u'ß$%ß&=',]),
1722 ]),
1723 # Misc stuff.
1724 tdTestSessionEx([ tdStepSessionSetEnv('FOO', ''),
1725 tdStepSessionCheckEnv(['FOO=',]),
1726 ]),
1727 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
1728 tdStepSessionCheckEnv(['FOO=BAR',])
1729 ],),
1730 tdTestSessionEx([ tdStepSessionSetEnv('FOO', 'BAR'),
1731 tdStepSessionSetEnv('BAR', 'BAZ'),
1732 tdStepSessionCheckEnv([ 'FOO=BAR', 'BAR=BAZ',]),
1733 ]),
1734 ];
1735 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'SessionEnv');
1736
1737 def testGuestCtrlSession(self, oSession, oTxsSession, oTestVm):
1738 """
1739 Tests the guest session handling.
1740 """
1741
1742 #
1743 # Parameters.
1744 #
1745 atTests = [
1746 # Invalid parameters.
1747 [ tdTestSession(sUser = ''), tdTestResultSession() ],
1748 [ tdTestSession(sPassword = 'bar'), tdTestResultSession() ],
1749 [ tdTestSession(sDomain = 'boo'),tdTestResultSession() ],
1750 [ tdTestSession(sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
1751 # User account without a passwort - forbidden.
1752 [ tdTestSession(sPassword = "" ), tdTestResultSession() ],
1753 # Wrong credentials.
1754 # Note: On Guest Additions < 4.3 this always succeeds because these don't
1755 # support creating dedicated sessions. Instead, guest process creation
1756 # then will fail. See note below.
1757 [ tdTestSession(sUser = 'foo', sPassword = 'bar', sDomain = 'boo'), tdTestResultSession() ],
1758 # Correct credentials.
1759 [ tdTestSession(), tdTestResultSession(fRc = True, cNumSessions = 1) ]
1760 ];
1761
1762 fRc = True;
1763 for (i, tTest) in enumerate(atTests):
1764 oCurTest = tTest[0] # type: tdTestSession
1765 oCurRes = tTest[1] # type: tdTestResult
1766
1767 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
1768 reporter.log('Testing #%d, user="%s", sPassword="%s", sDomain="%s" ...'
1769 % (i, oCurTest.oCreds.sUser, oCurTest.oCreds.sPassword, oCurTest.oCreds.sDomain));
1770 sCurGuestSessionName = 'testGuestCtrlSession: Test #%d' % (i,);
1771 fRc2, oCurGuestSession = oCurTest.createSession(sCurGuestSessionName, fIsError = oCurRes.fRc);
1772
1773 # See note about < 4.3 Guest Additions above.
1774 uProtocolVersion = 2;
1775 if oCurGuestSession is not None:
1776 try:
1777 uProtocolVersion = oCurGuestSession.protocolVersion;
1778 except:
1779 fRc = reporter.errorXcpt('Test #%d' % (i,));
1780
1781 if uProtocolVersion >= 2 and fRc2 is not oCurRes.fRc:
1782 fRc = reporter.error('Test #%d failed: Session creation failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc,));
1783
1784 if fRc2 and oCurGuestSession is None:
1785 fRc = reporter.error('Test #%d failed: no session object' % (i,));
1786 fRc2 = False;
1787
1788 if fRc2:
1789 if uProtocolVersion >= 2: # For Guest Additions < 4.3 getSessionCount() always will return 1.
1790 cCurSessions = oCurTest.getSessionCount(self.oTstDrv.oVBoxMgr);
1791 if cCurSessions != oCurRes.cNumSessions:
1792 fRc = reporter.error('Test #%d failed: Session count does not match: Got %d, expected %d'
1793 % (i, cCurSessions, oCurRes.cNumSessions));
1794 try:
1795 sObjName = oCurGuestSession.name;
1796 except:
1797 fRc = reporter.errorXcpt('Test #%d' % (i,));
1798 else:
1799 if sObjName != sCurGuestSessionName:
1800 fRc = reporter.error('Test #%d failed: Session name does not match: Got "%s", expected "%s"'
1801 % (i, sObjName, sCurGuestSessionName));
1802 fRc2 = oCurTest.closeSession(True);
1803 if fRc2 is False:
1804 fRc = reporter.error('Test #%d failed: Session could not be closed' % (i,));
1805
1806 if fRc is False:
1807 return (False, oTxsSession);
1808
1809 #
1810 # Multiple sessions.
1811 #
1812 cMaxGuestSessions = 31; # Maximum number of concurrent guest session allowed.
1813 # Actually, this is 32, but we don't test session 0.
1814 aoMultiSessions = {};
1815 reporter.log2('Opening multiple guest tsessions at once ...');
1816 for i in xrange(cMaxGuestSessions + 1):
1817 aoMultiSessions[i] = tdTestSession(sSessionName = 'MultiSession #%d' % (i,));
1818 aoMultiSessions[i].setEnvironment(oSession, oTxsSession, oTestVm);
1819
1820 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
1821 reporter.log2('MultiSession test #%d count is %d' % (i, cCurSessions));
1822 if cCurSessions != i:
1823 return (reporter.error('MultiSession count is %d, expected %d' % (cCurSessions, i)), oTxsSession);
1824 fRc2, _ = aoMultiSessions[i].createSession('MultiSession #%d' % (i,), i < cMaxGuestSessions);
1825 if fRc2 is not True:
1826 if i < cMaxGuestSessions:
1827 return (reporter.error('MultiSession #%d test failed' % (i,)), oTxsSession);
1828 reporter.log('MultiSession #%d exceeded concurrent guest session count, good' % (i,));
1829 break;
1830
1831 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr);
1832 if cCurSessions is not cMaxGuestSessions:
1833 return (reporter.error('Final session count %d, expected %d ' % (cCurSessions, cMaxGuestSessions,)), oTxsSession);
1834
1835 reporter.log2('Closing MultiSessions ...');
1836 for i in xrange(cMaxGuestSessions):
1837 # Close this session:
1838 oClosedGuestSession = aoMultiSessions[i].oGuestSession;
1839 fRc2 = aoMultiSessions[i].closeSession(True);
1840 cCurSessions = aoMultiSessions[i].getSessionCount(self.oTstDrv.oVBoxMgr)
1841 reporter.log2('MultiSession #%d count is %d' % (i, cCurSessions,));
1842 if fRc2 is False:
1843 fRc = reporter.error('Closing MultiSession #%d failed' % (i,));
1844 elif cCurSessions != cMaxGuestSessions - (i + 1):
1845 fRc = reporter.error('Expected %d session after closing #%d, got %d instead'
1846 % (cMaxGuestSessions - (i + 1), cCurSessions, i,));
1847 assert aoMultiSessions[i].oGuestSession is None or not fRc2;
1848 ## @todo any way to check that the session is closed other than the 'sessions' attribute?
1849
1850 # Try check that none of the remaining sessions got closed.
1851 try:
1852 aoGuestSessions = self.oTstDrv.oVBoxMgr.getArray(atTests[0][0].oTest.oGuest, 'sessions');
1853 except:
1854 return (reporter.errorXcpt('i=%d/%d' % (i, cMaxGuestSessions,)), oTxsSession);
1855 if oClosedGuestSession in aoGuestSessions:
1856 fRc = reporter.error('i=%d/%d: %s should not be in %s'
1857 % (i, cMaxGuestSessions, oClosedGuestSession, aoGuestSessions));
1858 if i + 1 < cMaxGuestSessions: # Not sure what xrange(2,2) does...
1859 for j in xrange(i + 1, cMaxGuestSessions):
1860 if aoMultiSessions[j].oGuestSession not in aoGuestSessions:
1861 fRc = reporter.error('i=%d/j=%d/%d: %s should be in %s'
1862 % (i, j, cMaxGuestSessions, aoMultiSessions[j].oGuestSession, aoGuestSessions));
1863 ## @todo any way to check that they work?
1864
1865 ## @todo Test session timeouts.
1866
1867 return (fRc, oTxsSession);
1868
1869 def testGuestCtrlSessionFileRefs(self, oSession, oTxsSession, oTestVm):
1870 """
1871 Tests the guest session file reference handling.
1872 """
1873
1874 # Find a file to play around with:
1875 sFile = self.getGuestSystemFileForReading(oTestVm);
1876
1877 # Use credential defaults.
1878 oCreds = tdCtxCreds();
1879 oCreds.applyDefaultsIfNotSet(oTestVm);
1880
1881 # Number of stale guest files to create.
1882 cStaleFiles = 10;
1883
1884 #
1885 # Start a session.
1886 #
1887 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
1888 try:
1889 oGuest = oSession.o.console.guest;
1890 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionFileRefs");
1891 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
1892 except:
1893 return (reporter.errorXcpt(), oTxsSession);
1894
1895 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
1896 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
1897 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
1898 reporter.log('Session successfully started');
1899
1900 #
1901 # Open guest files and "forget" them (stale entries).
1902 # For them we don't have any references anymore intentionally.
1903 #
1904 reporter.log2('Opening stale files');
1905 fRc = True;
1906 for i in xrange(0, cStaleFiles):
1907 try:
1908 if self.oTstDrv.fpApiVer >= 5.0:
1909 oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly, vboxcon.FileOpenAction_OpenExisting, 0);
1910 else:
1911 oGuestSession.fileOpen(sFile, "r", "oe", 0);
1912 # Note: Use a timeout in the call above for not letting the stale processes
1913 # hanging around forever. This can happen if the installed Guest Additions
1914 # do not support terminating guest processes.
1915 except:
1916 fRc = reporter.errorXcpt('Opening stale file #%d failed:' % (i,));
1917 break;
1918
1919 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
1920 except: fRc = reporter.errorXcpt();
1921 else:
1922 if cFiles != cStaleFiles:
1923 fRc = reporter.error('Got %d stale files, expected %d' % (cFiles, cStaleFiles));
1924
1925 if fRc is True:
1926 #
1927 # Open non-stale files and close them again.
1928 #
1929 reporter.log2('Opening non-stale files');
1930 aoFiles = [];
1931 for i in xrange(0, cStaleFiles):
1932 try:
1933 if self.oTstDrv.fpApiVer >= 5.0:
1934 oCurFile = oGuestSession.fileOpen(sFile, vboxcon.FileAccessMode_ReadOnly,
1935 vboxcon.FileOpenAction_OpenExisting, 0);
1936 else:
1937 oCurFile = oGuestSession.fileOpen(sFile, "r", "oe", 0);
1938 aoFiles.append(oCurFile);
1939 except:
1940 fRc = reporter.errorXcpt('Opening non-stale file #%d failed:' % (i,));
1941 break;
1942
1943 # Check the count.
1944 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
1945 except: fRc = reporter.errorXcpt();
1946 else:
1947 if cFiles != cStaleFiles * 2:
1948 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles * 2));
1949
1950 # Close them.
1951 reporter.log2('Closing all non-stale files again ...');
1952 for i, oFile in enumerate(aoFiles):
1953 try:
1954 oFile.close();
1955 except:
1956 fRc = reporter.errorXcpt('Closing non-stale file #%d failed:' % (i,));
1957
1958 # Check the count again.
1959 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
1960 except: fRc = reporter.errorXcpt();
1961 # Here we count the stale files (that is, files we don't have a reference
1962 # anymore for) and the opened and then closed non-stale files (that we still keep
1963 # a reference in aoFiles[] for).
1964 if cFiles != cStaleFiles:
1965 fRc = reporter.error('Got %d total files, expected %d' % (cFiles, cStaleFiles));
1966
1967 #
1968 # Check that all (referenced) non-stale files are now in the "closed" state.
1969 #
1970 reporter.log2('Checking statuses of all non-stale files ...');
1971 for i, oFile in enumerate(aoFiles):
1972 try:
1973 eFileStatus = aoFiles[i].status;
1974 except:
1975 fRc = reporter.errorXcpt('Checking status of file #%d failed:' % (i,));
1976 else:
1977 if eFileStatus != vboxcon.FileStatus_Closed:
1978 fRc = reporter.error('Non-stale file #%d has status %d, expected %d'
1979 % (i, eFileStatus, vboxcon.FileStatus_Closed));
1980
1981 if fRc is True:
1982 reporter.log2('All non-stale files closed');
1983
1984 try: cFiles = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'files'));
1985 except: fRc = reporter.errorXcpt();
1986 else: reporter.log2('Final guest session file count: %d' % (cFiles,));
1987
1988 #
1989 # Now try to close the session and see what happens.
1990 # Note! Session closing is why we've been doing all the 'if fRc is True' stuff above rather than returning.
1991 #
1992 reporter.log2('Closing guest session ...');
1993 try:
1994 oGuestSession.close();
1995 except:
1996 fRc = reporter.errorXcpt('Testing for stale processes failed:');
1997
1998 return (fRc, oTxsSession);
1999
2000 #def testGuestCtrlSessionDirRefs(self, oSession, oTxsSession, oTestVm):
2001 # """
2002 # Tests the guest session directory reference handling.
2003 # """
2004
2005 # fRc = True;
2006 # return (fRc, oTxsSession);
2007
2008 def testGuestCtrlSessionProcRefs(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2009 """
2010 Tests the guest session process reference handling.
2011 """
2012
2013 sCmd = self.getGuestSystemShell(oTestVm);
2014 asArgs = [sCmd,];
2015
2016 # Use credential defaults.
2017 oCreds = tdCtxCreds();
2018 oCreds.applyDefaultsIfNotSet(oTestVm);
2019
2020 # Number of stale guest processes to create.
2021 cStaleProcs = 10;
2022
2023 #
2024 # Start a session.
2025 #
2026 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2027 try:
2028 oGuest = oSession.o.console.guest;
2029 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionProcRefs");
2030 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2031 except:
2032 return (reporter.errorXcpt(), oTxsSession);
2033
2034 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2035 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2036 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2037 reporter.log('Session successfully started');
2038
2039 #
2040 # Fire off forever-running processes and "forget" them (stale entries).
2041 # For them we don't have any references anymore intentionally.
2042 #
2043 reporter.log2('Starting stale processes...');
2044 fRc = True;
2045 for i in xrange(0, cStaleProcs):
2046 try:
2047 oGuestSession.processCreate(sCmd,
2048 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], [],
2049 [ vboxcon.ProcessCreateFlag_WaitForStdOut ], \
2050 30 * 1000);
2051 # Note: Use a timeout in the call above for not letting the stale processes
2052 # hanging around forever. This can happen if the installed Guest Additions
2053 # do not support terminating guest processes.
2054 except:
2055 fRc = reporter.errorXcpt('Creating stale process #%d failed:' % (i,));
2056 break;
2057
2058 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2059 except: fRc = reporter.errorXcpt();
2060 else:
2061 if cProcesses != cStaleProcs:
2062 fRc = reporter.error('Got %d stale processes, expected %d' % (cProcesses, cStaleProcs));
2063
2064 if fRc is True:
2065 #
2066 # Fire off non-stale processes and wait for termination.
2067 #
2068 if oTestVm.isWindows() or oTestVm.isOS2():
2069 asArgs = [ sCmd, '/C', 'dir', '/S', self.getGuestSystemDir(oTestVm), ];
2070 else:
2071 asArgs = [ sCmd, '-c', 'ls -la ' + self.getGuestSystemDir(oTestVm), ];
2072 reporter.log2('Starting non-stale processes...');
2073 aoProcesses = [];
2074 for i in xrange(0, cStaleProcs):
2075 try:
2076 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2077 [], [], 0); # Infinite timeout.
2078 aoProcesses.append(oCurProc);
2079 except:
2080 fRc = reporter.errorXcpt('Creating non-stale process #%d failed:' % (i,));
2081 break;
2082
2083 reporter.log2('Waiting for non-stale processes to terminate...');
2084 for i, oProcess in enumerate(aoProcesses):
2085 try:
2086 oProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 30 * 1000);
2087 eProcessStatus = oProcess.status;
2088 except:
2089 fRc = reporter.errorXcpt('Waiting for non-stale process #%d failed:' % (i,));
2090 else:
2091 if eProcessStatus != vboxcon.ProcessStatus_TerminatedNormally:
2092 fRc = reporter.error('Waiting for non-stale processes #%d resulted in status %d, expected %d'
2093 % (i, eProcessStatus, vboxcon.ProcessStatus_TerminatedNormally));
2094
2095 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2096 except: fRc = reporter.errorXcpt();
2097 else:
2098 # Here we count the stale processes (that is, processes we don't have a reference
2099 # anymore for) and the started + terminated non-stale processes (that we still keep
2100 # a reference in aoProcesses[] for).
2101 if cProcesses != (cStaleProcs * 2):
2102 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2103
2104 if fRc is True:
2105 reporter.log2('All non-stale processes terminated');
2106
2107 #
2108 # Fire off non-stale blocking processes which are terminated via terminate().
2109 #
2110 if oTestVm.isWindows() or oTestVm.isOS2():
2111 asArgs = [ sCmd, '/C', 'pause'];
2112 else:
2113 asArgs = [ sCmd ];
2114 reporter.log2('Starting blocking processes...');
2115 aoProcesses = [];
2116 for i in xrange(0, cStaleProcs):
2117 try:
2118 oCurProc = oGuestSession.processCreate(sCmd, asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:],
2119 [], [], 30 * 1000);
2120 # Note: Use a timeout in the call above for not letting the stale processes
2121 # hanging around forever. This can happen if the installed Guest Additions
2122 # do not support terminating guest processes.
2123 aoProcesses.append(oCurProc);
2124 except:
2125 fRc = reporter.errorXcpt('Creating non-stale blocking process #%d failed:' % (i,));
2126 break;
2127
2128 reporter.log2('Terminating blocking processes...');
2129 for i, oProcess in enumerate(aoProcesses):
2130 try:
2131 oProcess.terminate();
2132 except: # Termination might not be supported, just skip and log it.
2133 reporter.logXcpt('Termination of blocking process #%d failed, skipped:' % (i,));
2134
2135 # There still should be 20 processes because we terminated the 10 newest ones.
2136 try: cProcesses = len(self.oTstDrv.oVBoxMgr.getArray(oGuestSession, 'processes'));
2137 except: fRc = reporter.errorXcpt();
2138 else:
2139 if cProcesses != (cStaleProcs * 2):
2140 fRc = reporter.error('Got %d total processes, expected %d' % (cProcesses, cStaleProcs));
2141 reporter.log2('Final guest session processes count: %d' % (cProcesses,));
2142
2143 #
2144 # Now try to close the session and see what happens.
2145 #
2146 reporter.log2('Closing guest session ...');
2147 try:
2148 oGuestSession.close();
2149 except:
2150 fRc = reporter.errorXcpt('Testing for stale processes failed:');
2151
2152 return (fRc, oTxsSession);
2153
2154 def testGuestCtrlExec(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements
2155 """
2156 Tests the basic execution feature.
2157 """
2158
2159 # Paths:
2160 sVBoxControl = None; ## @todo Get path of installed Guest Additions. Later.
2161 sShell = self.getGuestSystemShell(oTestVm);
2162 sShellOpt = '/C' if oTestVm.isWindows() or oTestVm.isOS2() else '-c';
2163 sSystemDir = self.getGuestSystemDir(oTestVm);
2164 sFileForReading = self.getGuestSystemFileForReading(oTestVm);
2165 if oTestVm.isWindows() or oTestVm.isOS2():
2166 sImageOut = self.getGuestSystemShell(oTestVm);
2167 if oTestVm.isWindows():
2168 sVBoxControl = "C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\VBoxControl.exe";
2169 else:
2170 sImageOut = "/bin/ls";
2171 if oTestVm.isLinux(): ## @todo check solaris and darwin.
2172 sVBoxControl = "/usr/bin/VBoxControl"; # Symlink
2173
2174 # Use credential defaults.
2175 oCreds = tdCtxCreds();
2176 oCreds.applyDefaultsIfNotSet(oTestVm);
2177
2178 atInvalid = [
2179 # Invalid parameters.
2180 [ tdTestExec(), tdTestResultExec() ],
2181 # Non-existent / invalid image.
2182 [ tdTestExec(sCmd = "non-existent"), tdTestResultExec() ],
2183 [ tdTestExec(sCmd = "non-existent2"), tdTestResultExec() ],
2184 # Use an invalid format string.
2185 [ tdTestExec(sCmd = "%$%%%&"), tdTestResultExec() ],
2186 # More stuff.
2187 [ tdTestExec(sCmd = u"ƒ‰‹ˆ÷‹¸"), tdTestResultExec() ],
2188 [ tdTestExec(sCmd = "???://!!!"), tdTestResultExec() ],
2189 [ tdTestExec(sCmd = "<>!\\"), tdTestResultExec() ],
2190 # Enable as soon as ERROR_BAD_DEVICE is implemented.
2191 #[ tdTestExec(sCmd = "CON", tdTestResultExec() ],
2192 ];
2193
2194 atExec = [];
2195 if oTestVm.isWindows() or oTestVm.isOS2():
2196 atExec += [
2197 # Basic execution.
2198 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2199 tdTestResultExec(fRc = True) ],
2200 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sFileForReading ]),
2201 tdTestResultExec(fRc = True) ],
2202 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir + '\\nonexist.dll' ]),
2203 tdTestResultExec(fRc = True, iExitCode = 1) ],
2204 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', '/wrongparam' ]),
2205 tdTestResultExec(fRc = True, iExitCode = 1) ],
2206 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2207 tdTestResultExec(fRc = True, iExitCode = 1) ],
2208 # StdOut.
2209 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2210 tdTestResultExec(fRc = True) ],
2211 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdout-non-existing' ]),
2212 tdTestResultExec(fRc = True, iExitCode = 1) ],
2213 # StdErr.
2214 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2215 tdTestResultExec(fRc = True) ],
2216 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stderr-non-existing' ]),
2217 tdTestResultExec(fRc = True, iExitCode = 1) ],
2218 # StdOut + StdErr.
2219 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', sSystemDir ]),
2220 tdTestResultExec(fRc = True) ],
2221 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'dir', '/S', 'stdouterr-non-existing' ]),
2222 tdTestResultExec(fRc = True, iExitCode = 1) ],
2223 ];
2224 # atExec.extend([
2225 # FIXME: Failing tests.
2226 # Environment variables.
2227 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2228 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2229 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2230 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2231 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2232 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2233 # aEnv = [ 'TEST_FOO=BAR' ],
2234 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2235 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2236 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2237 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2238 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2239 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2240
2241 ## @todo Create some files (or get files) we know the output size of to validate output length!
2242 ## @todo Add task which gets killed at some random time while letting the guest output something.
2243 #];
2244 else:
2245 atExec += [
2246 # Basic execution.
2247 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '-R', sSystemDir ]),
2248 tdTestResultExec(fRc = True, iExitCode = 1) ],
2249 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sFileForReading ]),
2250 tdTestResultExec(fRc = True) ],
2251 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '--wrong-parameter' ]),
2252 tdTestResultExec(fRc = True, iExitCode = 2) ],
2253 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/non/existent' ]),
2254 tdTestResultExec(fRc = True, iExitCode = 2) ],
2255 [ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'wrongcommand' ]),
2256 tdTestResultExec(fRc = True, iExitCode = 127) ],
2257 # StdOut.
2258 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2259 tdTestResultExec(fRc = True) ],
2260 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdout-non-existing' ]),
2261 tdTestResultExec(fRc = True, iExitCode = 2) ],
2262 # StdErr.
2263 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2264 tdTestResultExec(fRc = True) ],
2265 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stderr-non-existing' ]),
2266 tdTestResultExec(fRc = True, iExitCode = 2) ],
2267 # StdOut + StdErr.
2268 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, sSystemDir ]),
2269 tdTestResultExec(fRc = True) ],
2270 [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, 'stdouterr-non-existing' ]),
2271 tdTestResultExec(fRc = True, iExitCode = 2) ],
2272 ];
2273 # atExec.extend([
2274 # FIXME: Failing tests.
2275 # Environment variables.
2276 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_NONEXIST' ],
2277 # tdTestResultExec(fRc = True, iExitCode = 1) ]
2278 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'windir' ],
2279 #
2280 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2281 # tdTestResultExec(fRc = True, sBuf = 'windir=C:\\WINDOWS\r\n') ],
2282 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2283 # aEnv = [ 'TEST_FOO=BAR' ],
2284 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2285 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ],
2286 # [ tdTestExec(sCmd = sImageOut, asArgs = [ sImageOut, '/C', 'set', 'TEST_FOO' ],
2287 # aEnv = [ 'TEST_FOO=BAR', 'TEST_BAZ=BAR' ],
2288 # fFlags = [ vboxcon.ProcessCreateFlag_WaitForStdOut, vboxcon.ProcessCreateFlag_WaitForStdErr ]),
2289 # tdTestResultExec(fRc = True, sBuf = 'TEST_FOO=BAR\r\n') ]
2290
2291 ## @todo Create some files (or get files) we know the output size of to validate output length!
2292 ## @todo Add task which gets killed at some random time while letting the guest output something.
2293 #];
2294
2295 #
2296 for iExitCode in xrange(0, 127):
2297 atExec.append([ tdTestExec(sCmd = sShell, asArgs = [ sShell, sShellOpt, 'exit %s' % iExitCode ]),
2298 tdTestResultExec(fRc = True, iExitCode = iExitCode) ]);
2299
2300 if sVBoxControl:
2301 # Paths with spaces on windows.
2302 atExec.append([ tdTestExec(sCmd = sVBoxControl, asArgs = [ sVBoxControl, 'version' ]),
2303 tdTestResultExec(fRc = True) ]);
2304
2305 # Build up the final test array for the first batch.
2306 atTests = atInvalid + atExec;
2307
2308 #
2309 # First batch: One session per guest process.
2310 #
2311 reporter.log('One session per guest process ...');
2312 fRc = True;
2313 for (i, tTest) in enumerate(atTests):
2314 oCurTest = tTest[0] # type: tdTestExec
2315 oCurRes = tTest[1] # type: tdTestResultExec
2316 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2317 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlExec: Test #%d' % (i,), True);
2318 if fRc is not True:
2319 reporter.error('Test #%d failed: Could not create session' % (i,));
2320 break;
2321 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
2322 if fRc is not True:
2323 break;
2324 fRc = oCurTest.closeSession(True);
2325 if fRc is not True:
2326 break;
2327
2328 reporter.log('Execution of all tests done, checking for stale sessions');
2329
2330 # No sessions left?
2331 try:
2332 aSessions = self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions');
2333 except:
2334 fRc = reporter.errorXcpt();
2335 else:
2336 cSessions = len(aSessions);
2337 if cSessions != 0:
2338 fRc = reporter.error('Found %d stale session(s), expected 0:' % (cSessions,));
2339 for (i, aSession) in enumerate(aSessions):
2340 try: reporter.log(' Stale session #%d ("%s")' % (aSession.id, aSession.name));
2341 except: reporter.errorXcpt();
2342
2343 if fRc is not True:
2344 return (fRc, oTxsSession);
2345
2346 reporter.log('Now using one guest session for all tests ...');
2347
2348 #
2349 # Second batch: One session for *all* guest processes.
2350 #
2351
2352 # Create session.
2353 reporter.log('Creating session for all tests ...');
2354 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start, ];
2355 try:
2356 oGuest = oSession.o.console.guest;
2357 oCurGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain,
2358 'testGuestCtrlExec: One session for all tests');
2359 except:
2360 return (reporter.errorXcpt(), oTxsSession);
2361
2362 try:
2363 eWaitResult = oCurGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2364 except:
2365 fRc = reporter.errorXcpt('Waiting for guest session to start failed:');
2366 else:
2367 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2368 fRc = reporter.error('Session did not start successfully, returned wait result: %d' % (eWaitResult,));
2369 else:
2370 reporter.log('Session successfully started');
2371
2372 # Do the tests within this session.
2373 for (i, tTest) in enumerate(atTests):
2374 oCurTest = tTest[0] # type: tdTestExec
2375 oCurRes = tTest[1] # type: tdTestResultExec
2376
2377 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2378 fRc = self.gctrlExecDoTest(i, oCurTest, oCurRes, oCurGuestSession);
2379 if fRc is False:
2380 break;
2381
2382 # Close the session.
2383 reporter.log2('Closing guest session ...');
2384 try:
2385 oCurGuestSession.close();
2386 oCurGuestSession = None;
2387 except:
2388 fRc = reporter.errorXcpt('Closing guest session failed:');
2389
2390 # No sessions left?
2391 reporter.log('Execution of all tests done, checking for stale sessions again');
2392 try: cSessions = len(self.oTstDrv.oVBoxMgr.getArray(oSession.o.console.guest, 'sessions'));
2393 except: fRc = reporter.errorXcpt();
2394 else:
2395 if cSessions != 0:
2396 fRc = reporter.error('Found %d stale session(s), expected 0' % (cSessions,));
2397 return (fRc, oTxsSession);
2398
2399 def threadForTestGuestCtrlSessionReboot(self, oGuestProcess):
2400 """
2401 Thread routine which waits for the stale guest process getting terminated (or some error)
2402 while the main test routine reboots the guest. It then compares the expected guest process result
2403 and logs an error if appropriate.
2404 """
2405 reporter.log('Waiting for process to get terminated at reboot ...');
2406 try:
2407 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate ], 5 * 60 * 1000);
2408 except:
2409 return reporter.errorXcpt('waitForArray failed');
2410 try:
2411 eStatus = oGuestProcess.status
2412 except:
2413 return reporter.errorXcpt('failed to get status (wait result %d)' % (eWaitResult,));
2414
2415 if eWaitResult == vboxcon.ProcessWaitResult_Terminate and eStatus == vboxcon.ProcessStatus_Down:
2416 reporter.log('Stale process was correctly terminated (status: down)');
2417 return True;
2418
2419 return reporter.error('Process wait across reboot failed: eWaitResult=%d, expected %d; eStatus=%d, expected %d'
2420 % (eWaitResult, vboxcon.ProcessWaitResult_Terminate, eStatus, vboxcon.ProcessStatus_Down,));
2421
2422 def testGuestCtrlSessionReboot(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2423 """
2424 Tests guest object notifications when a guest gets rebooted / shutdown.
2425
2426 These notifications gets sent from the guest sessions in order to make API clients
2427 aware of guest session changes.
2428
2429 To test that we create a stale guest process and trigger a reboot of the guest.
2430 """
2431
2432 ## @todo backport fixes to 6.0 and maybe 5.2
2433 if self.oTstDrv.fpApiVer <= 6.0:
2434 reporter.log('Skipping: Required fixes not yet backported!');
2435 return None;
2436
2437 # Use credential defaults.
2438 oCreds = tdCtxCreds();
2439 oCreds.applyDefaultsIfNotSet(oTestVm);
2440
2441 fRc = True;
2442
2443 #
2444 # Start a session.
2445 #
2446 aeWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
2447 try:
2448 oGuest = oSession.o.console.guest;
2449 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlSessionReboot");
2450 eWaitResult = oGuestSession.waitForArray(aeWaitFor, 30 * 1000);
2451 except:
2452 return (reporter.errorXcpt(), oTxsSession);
2453
2454 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2455 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2456 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2457 reporter.log('Session successfully started');
2458
2459 #
2460 # Create a process.
2461 #
2462 sImage = self.getGuestSystemShell(oTestVm);
2463 asArgs = [ sImage, ];
2464 aEnv = [];
2465 fFlags = [];
2466 try:
2467 oGuestProcess = oGuestSession.processCreate(sImage,
2468 asArgs if self.oTstDrv.fpApiVer >= 5.0 else asArgs[1:], aEnv, fFlags,
2469 30 * 1000);
2470 except:
2471 fRc = reporter.error('Failed to start shell process (%s)' % (sImage,));
2472 else:
2473 try:
2474 eWaitResult = oGuestProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2475 except:
2476 fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
2477 else:
2478 # Check the result and state:
2479 try: eStatus = oGuestProcess.status;
2480 except: fRc = reporter.errorXcpt('Waiting for shell process (%s) to start failed' % (sImage,));
2481 else:
2482 reporter.log2('Starting process wait result returned: %d; Process status is: %d' % (eWaitResult, eStatus,));
2483 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2484 fRc = reporter.error('wait for ProcessWaitForFlag_Start failed: %d, expected %d (Start)'
2485 % (eWaitResult, vboxcon.ProcessWaitResult_Start,));
2486 elif eStatus != vboxcon.ProcessStatus_Started:
2487 fRc = reporter.error('Unexpected process status after startup: %d, wanted %d (Started)'
2488 % (eStatus, vboxcon.ProcessStatus_Started,));
2489 else:
2490 # Create a thread that waits on the process to terminate
2491 reporter.log('Creating reboot thread ...');
2492 oThreadReboot = threading.Thread(target = self.threadForTestGuestCtrlSessionReboot,
2493 args = (oGuestProcess,),
2494 name = ('threadForTestGuestCtrlSessionReboot'));
2495 oThreadReboot.setDaemon(True);
2496 oThreadReboot.start();
2497
2498 # Not sure why this fudge is needed...
2499 reporter.log('5 second wait fudge before triggering reboot ...');
2500 self.oTstDrv.sleep(5);
2501
2502 # Do the reboot.
2503 reporter.log('Rebooting guest and reconnecting TXS ...');
2504 (oSession, oTxsSession) = self.oTstDrv.txsRebootAndReconnectViaTcp(oSession, oTxsSession,
2505 cMsTimeout = 3 * 60000);
2506 if not oSession or not oTxsSession:
2507 try: oGuestProcess.terminate();
2508 except: reporter.logXcpt();
2509 fRc = False;
2510
2511 reporter.log('Waiting for thread to finish ...');
2512 oThreadReboot.join();
2513
2514 #
2515 # Try make sure we don't leave with a stale process on failure.
2516 #
2517 try: oGuestProcess.terminate();
2518 except: reporter.logXcpt();
2519
2520 #
2521 # Close the session.
2522 #
2523 reporter.log2('Closing guest session ...');
2524 try:
2525 oGuestSession.close();
2526 except:
2527 fRc = reporter.errorXcpt();
2528
2529 return (fRc, oTxsSession);
2530
2531 def testGuestCtrlExecTimeout(self, oSession, oTxsSession, oTestVm):
2532 """
2533 Tests handling of timeouts of started guest processes.
2534 """
2535
2536 sShell = self.getGuestSystemShell(oTestVm);
2537
2538 # Use credential defaults.
2539 oCreds = tdCtxCreds();
2540 oCreds.applyDefaultsIfNotSet(oTestVm);
2541
2542 #
2543 # Create a session.
2544 #
2545 try:
2546 oGuest = oSession.o.console.guest;
2547 oGuestSession = oGuest.createSession(oCreds.sUser, oCreds.sPassword, oCreds.sDomain, "testGuestCtrlExecTimeout");
2548 eWaitResult = oGuestSession.waitForArray([ vboxcon.GuestSessionWaitForFlag_Start, ], 30 * 1000);
2549 except:
2550 return (reporter.errorXcpt(), oTxsSession);
2551
2552 # Be nice to Guest Additions < 4.3: They don't support session handling and therefore return WaitFlagNotSupported.
2553 if eWaitResult not in (vboxcon.GuestSessionWaitResult_Start, vboxcon.GuestSessionWaitResult_WaitFlagNotSupported):
2554 return (reporter.error('Session did not start successfully - wait error: %d' % (eWaitResult,)), oTxsSession);
2555 reporter.log('Session successfully started');
2556
2557 #
2558 # Create a process which never terminates and should timeout when
2559 # waiting for termination.
2560 #
2561 fRc = True;
2562 try:
2563 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
2564 [], [], 30 * 1000);
2565 except:
2566 fRc = reporter.errorXcpt();
2567 else:
2568 reporter.log('Waiting for process 1 being started ...');
2569 try:
2570 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2571 except:
2572 fRc = reporter.errorXcpt();
2573 else:
2574 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2575 fRc = reporter.error('Waiting for process 1 to start failed, got status %d' % (eWaitResult,));
2576 else:
2577 for msWait in (1, 32, 2000,):
2578 reporter.log('Waiting for process 1 to time out within %sms ...' % (msWait,));
2579 try:
2580 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], msWait);
2581 except:
2582 fRc = reporter.errorXcpt();
2583 break;
2584 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
2585 fRc = reporter.error('Waiting for process 1 did not time out in %sms as expected: %d'
2586 % (msWait, eWaitResult,));
2587 break;
2588 reporter.log('Waiting for process 1 timed out in %u ms, good' % (msWait,));
2589
2590 try:
2591 oCurProcess.terminate();
2592 except:
2593 reporter.errorXcpt();
2594 oCurProcess = None;
2595
2596 #
2597 # Create another process that doesn't terminate, but which will be killed by VBoxService
2598 # because it ran out of execution time (3 seconds).
2599 #
2600 try:
2601 oCurProcess = oGuestSession.processCreate(sShell, [sShell,] if self.oTstDrv.fpApiVer >= 5.0 else [],
2602 [], [], 3 * 1000);
2603 except:
2604 fRc = reporter.errorXcpt();
2605 else:
2606 reporter.log('Waiting for process 2 being started ...');
2607 try:
2608 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Start ], 30 * 1000);
2609 except:
2610 fRc = reporter.errorXcpt();
2611 else:
2612 if eWaitResult != vboxcon.ProcessWaitResult_Start:
2613 fRc = reporter.error('Waiting for process 2 to start failed, got status %d' % (eWaitResult,));
2614 else:
2615 reporter.log('Waiting for process 2 to get killed for running out of execution time ...');
2616 try:
2617 eWaitResult = oCurProcess.waitForArray([ vboxcon.ProcessWaitForFlag_Terminate, ], 15 * 1000);
2618 except:
2619 fRc = reporter.errorXcpt();
2620 else:
2621 if eWaitResult != vboxcon.ProcessWaitResult_Timeout:
2622 fRc = reporter.error('Waiting for process 2 did not time out when it should, got wait result %d'
2623 % (eWaitResult,));
2624 else:
2625 reporter.log('Waiting for process 2 did not time out, good: %s' % (eWaitResult,));
2626 try:
2627 eStatus = oCurProcess.status;
2628 except:
2629 fRc = reporter.errorXcpt();
2630 else:
2631 if eStatus != vboxcon.ProcessStatus_TimedOutKilled:
2632 fRc = reporter.error('Status of process 2 wrong; excepted %d, got %d'
2633 % (vboxcon.ProcessStatus_TimedOutKilled, eStatus));
2634 else:
2635 reporter.log('Status of process 2 is TimedOutKilled (%d) is it should be.'
2636 % (vboxcon.ProcessStatus_TimedOutKilled,));
2637 try:
2638 oCurProcess.terminate();
2639 except:
2640 reporter.logXcpt();
2641 oCurProcess = None;
2642
2643 #
2644 # Clean up the session.
2645 #
2646 try:
2647 oGuestSession.close();
2648 except:
2649 fRc = reporter.errorXcpt();
2650
2651 return (fRc, oTxsSession);
2652
2653 def testGuestCtrlDirCreate(self, oSession, oTxsSession, oTestVm):
2654 """
2655 Tests creation of guest directories.
2656 """
2657
2658 sScratch = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'testGuestCtrlDirCreate');
2659
2660 atTests = [
2661 # Invalid stuff.
2662 [ tdTestDirCreate(sDirectory = '' ), tdTestResultFailure() ],
2663 # More unusual stuff.
2664 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '..') ), tdTestResultFailure() ],
2665 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin('..', '.') ), tdTestResultFailure() ],
2666 ];
2667 if oTestVm.isWindows() or oTestVm.isOS2():
2668 atTests.extend([
2669 [ tdTestDirCreate(sDirectory = '..' ), tdTestResultFailure() ],
2670 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
2671 [ tdTestDirCreate(sDirectory = '../..' ), tdTestResultFailure() ],
2672 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
2673 [ tdTestDirCreate(sDirectory = 'C:\\' ), tdTestResultFailure() ],
2674 [ tdTestDirCreate(sDirectory = 'C:\\..' ), tdTestResultFailure() ],
2675 [ tdTestDirCreate(sDirectory = 'C:\\..\\' ), tdTestResultFailure() ],
2676 [ tdTestDirCreate(sDirectory = 'C:/' ), tdTestResultFailure() ],
2677 [ tdTestDirCreate(sDirectory = 'C:/.' ), tdTestResultFailure() ],
2678 [ tdTestDirCreate(sDirectory = 'C:/./' ), tdTestResultFailure() ],
2679 [ tdTestDirCreate(sDirectory = 'C:/..' ), tdTestResultFailure() ],
2680 [ tdTestDirCreate(sDirectory = 'C:/../' ), tdTestResultFailure() ],
2681 [ tdTestDirCreate(sDirectory = '\\\\uncrulez\\foo' ), tdTestResultFailure() ],
2682 ]);
2683 else:
2684 atTests.extend([
2685 [ tdTestDirCreate(sDirectory = '../' ), tdTestResultFailure() ],
2686 [ tdTestDirCreate(sDirectory = '../../' ), tdTestResultFailure() ],
2687 [ tdTestDirCreate(sDirectory = '/' ), tdTestResultFailure() ],
2688 [ tdTestDirCreate(sDirectory = '/..' ), tdTestResultFailure() ],
2689 [ tdTestDirCreate(sDirectory = '/../' ), tdTestResultFailure() ],
2690 ]);
2691 atTests.extend([
2692 # Existing directories and files.
2693 [ tdTestDirCreate(sDirectory = self.getGuestSystemDir(oTestVm) ), tdTestResultFailure() ],
2694 [ tdTestDirCreate(sDirectory = self.getGuestSystemShell(oTestVm) ), tdTestResultFailure() ],
2695 [ tdTestDirCreate(sDirectory = self.getGuestSystemFileForReading(oTestVm) ), tdTestResultFailure() ],
2696 ]);
2697
2698 atTests.extend([
2699 # Creating directories.
2700 [ tdTestDirCreate(sDirectory = sScratch ), tdTestResultSuccess() ],
2701 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
2702 fFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
2703 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo', 'bar', 'baz'),
2704 fFlags = (vboxcon.DirectoryCreateFlag_Parents,) ), tdTestResultSuccess() ],
2705 # Long random names.
2706 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(36, 28))),
2707 tdTestResultSuccess() ],
2708 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(140, 116))),
2709 tdTestResultSuccess() ],
2710 # Too long names. ASSUMES a guests has a 255 filename length limitation.
2711 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
2712 tdTestResultFailure() ],
2713 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, self.oTestFiles.generateFilenameEx(2048, 256))),
2714 tdTestResultFailure() ],
2715 # Missing directory in path.
2716 [ tdTestDirCreate(sDirectory = oTestVm.pathJoin(sScratch, 'foo1', 'bar') ), tdTestResultFailure() ],
2717 ]);
2718
2719 fRc = True;
2720 for (i, tTest) in enumerate(atTests):
2721 oCurTest = tTest[0] # type: tdTestDirCreate
2722 oCurRes = tTest[1] # type: tdTestResult
2723 reporter.log('Testing #%d, sDirectory="%s" ...' % (i, oCurTest.sDirectory));
2724
2725 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2726 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreate: Test #%d' % (i,), fIsError = True);
2727 if fRc is False:
2728 return reporter.error('Test #%d failed: Could not create session' % (i,));
2729
2730 fRc = self.gctrlCreateDir(oCurTest, oCurRes, oCurGuestSession);
2731
2732 fRc = oCurTest.closeSession(fIsError = True) and fRc;
2733 if fRc is False:
2734 reporter.error('Test #%d failed' % (i,));
2735 break;
2736
2737 return (fRc, oTxsSession);
2738
2739 def testGuestCtrlDirCreateTemp(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
2740 """
2741 Tests creation of temporary directories.
2742 """
2743
2744 sSystemDir = self.getGuestSystemDir(oTestVm);
2745 atTests = [
2746 # Invalid stuff (template must have one or more trailin 'X'es (upper case only), or a cluster of three or more).
2747 [ tdTestDirCreateTemp(sDirectory = ''), tdTestResultFailure() ],
2748 [ tdTestDirCreateTemp(sDirectory = sSystemDir, fMode = 1234), tdTestResultFailure() ],
2749 [ tdTestDirCreateTemp(sTemplate = 'xXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2750 [ tdTestDirCreateTemp(sTemplate = 'xxx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2751 [ tdTestDirCreateTemp(sTemplate = 'XXx', sDirectory = sSystemDir, fMode = 0o700), tdTestResultFailure() ],
2752 [ tdTestDirCreateTemp(sTemplate = 'bar', sDirectory = 'whatever', fMode = 0o700), tdTestResultFailure() ],
2753 [ tdTestDirCreateTemp(sTemplate = 'foo', sDirectory = 'it is not used', fMode = 0o700), tdTestResultFailure() ],
2754 [ tdTestDirCreateTemp(sTemplate = 'X,so', sDirectory = 'pointless test', fMode = 0o700), tdTestResultFailure() ],
2755 # Non-existing stuff.
2756 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX',
2757 sDirectory = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'non', 'existing')),
2758 tdTestResultFailure() ],
2759 # Working stuff:
2760 [ tdTestDirCreateTemp(sTemplate = 'X', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2761 [ tdTestDirCreateTemp(sTemplate = 'XX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2762 [ tdTestDirCreateTemp(sTemplate = 'XXX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2763 [ tdTestDirCreateTemp(sTemplate = 'XXXXXXX', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2764 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2765 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2766 [ tdTestDirCreateTemp(sTemplate = 'tmpXXXtst', sDirectory = self.getGuestTempDir(oTestVm)), tdTestResultFailure() ],
2767 ## @todo test fSecure and pass weird fMode values once these parameters are implemented in the API.
2768 ];
2769
2770 fRc = True;
2771 for (i, tTest) in enumerate(atTests):
2772 oCurTest = tTest[0] # type: tdTestDirCreateTemp
2773 oCurRes = tTest[1] # type: tdTestResult
2774 reporter.log('Testing #%d, sTemplate="%s", fMode=%#o, path="%s", secure="%s" ...' %
2775 (i, oCurTest.sTemplate, oCurTest.fMode, oCurTest.sDirectory, oCurTest.fSecure));
2776
2777 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2778 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirCreateTemp: Test #%d' % (i,), fIsError = True);
2779 if fRc is False:
2780 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
2781 break;
2782
2783 sDirTemp = '';
2784 try:
2785 sDirTemp = oCurGuestSession.directoryCreateTemp(oCurTest.sTemplate, oCurTest.fMode,
2786 oCurTest.sDirectory, oCurTest.fSecure);
2787 except:
2788 if oCurRes.fRc is True:
2789 fRc = reporter.errorXcpt('Creating temp directory "%s" failed:' % (oCurTest.sDirectory,));
2790 else:
2791 reporter.logXcpt('Creating temp directory "%s" failed expectedly, skipping:' % (oCurTest.sDirectory,));
2792 else:
2793 reporter.log2('Temporary directory is: "%s"' % (sDirTemp,));
2794 if not sDirTemp:
2795 fRc = reporter.error('Resulting directory is empty!');
2796 else:
2797 ## @todo This does not work for some unknown reason.
2798 #try:
2799 # if self.oTstDrv.fpApiVer >= 5.0:
2800 # fExists = oCurGuestSession.directoryExists(sDirTemp, False);
2801 # else:
2802 # fExists = oCurGuestSession.directoryExists(sDirTemp);
2803 #except:
2804 # fRc = reporter.errorXcpt('sDirTemp=%s' % (sDirTemp,));
2805 #else:
2806 # if fExists is not True:
2807 # fRc = reporter.error('Test #%d failed: Temporary directory "%s" does not exists (%s)'
2808 # % (i, sDirTemp, fExists));
2809 try:
2810 oFsObjInfo = oCurGuestSession.fsObjQueryInfo(sDirTemp, False);
2811 eType = oFsObjInfo.type;
2812 except:
2813 fRc = reporter.errorXcpt('sDirTemp="%s"' % (sDirTemp,));
2814 else:
2815 reporter.log2('%s: eType=%s (dir=%d)' % (sDirTemp, eType, vboxcon.FsObjType_Directory,));
2816 if eType != vboxcon.FsObjType_Directory:
2817 fRc = reporter.error('Temporary directory "%s" not created as a directory: eType=%d'
2818 % (sDirTemp, eType));
2819 fRc = oCurTest.closeSession(True) and fRc;
2820 return (fRc, oTxsSession);
2821
2822 def testGuestCtrlDirRead(self, oSession, oTxsSession, oTestVm):
2823 """
2824 Tests opening and reading (enumerating) guest directories.
2825 """
2826
2827 sSystemDir = self.getGuestSystemDir(oTestVm);
2828 atTests = [
2829 # Invalid stuff.
2830 [ tdTestDirRead(sDirectory = ''), tdTestResultDirRead() ],
2831 [ tdTestDirRead(sDirectory = sSystemDir, fFlags = [ 1234 ]), tdTestResultDirRead() ],
2832 [ tdTestDirRead(sDirectory = sSystemDir, sFilter = '*.foo'), tdTestResultDirRead() ],
2833 # Non-existing stuff.
2834 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'really-no-such-subdir')), tdTestResultDirRead() ],
2835 [ tdTestDirRead(sDirectory = oTestVm.pathJoin(sSystemDir, 'non', 'existing')), tdTestResultDirRead() ],
2836 ];
2837
2838 if oTestVm.isWindows() or oTestVm.isOS2():
2839 atTests.extend([
2840 # More unusual stuff.
2841 [ tdTestDirRead(sDirectory = 'z:\\'), tdTestResultDirRead() ],
2842 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
2843 ]);
2844 else:
2845 atTests.extend([
2846 # More unusual stuff.
2847 [ tdTestDirRead(sDirectory = 'z:/'), tdTestResultDirRead() ],
2848 [ tdTestDirRead(sDirectory = '\\\\uncrulez\\foo'), tdTestResultDirRead() ],
2849 ]);
2850 # Read the system directory (ASSUMES at least 5 files in it):
2851 atTests.append([ tdTestDirRead(sDirectory = sSystemDir), tdTestResultDirRead(fRc = True, cFiles = -5, cDirs = None) ]);
2852 ## @todo trailing slash
2853
2854 # Read from the test file set.
2855 atTests.extend([
2856 [ tdTestDirRead(sDirectory = self.oTestFiles.oEmptyDir.sPath),
2857 tdTestResultDirRead(fRc = True, cFiles = 0, cDirs = 0, cOthers = 0) ],
2858 [ tdTestDirRead(sDirectory = self.oTestFiles.oManyDir.sPath),
2859 tdTestResultDirRead(fRc = True, cFiles = len(self.oTestFiles.oManyDir.aoChildren), cDirs = 0, cOthers = 0) ],
2860 [ tdTestDirRead(sDirectory = self.oTestFiles.oTreeDir.sPath),
2861 tdTestResultDirRead(fRc = True, cFiles = self.oTestFiles.cTreeFiles, cDirs = self.oTestFiles.cTreeDirs,
2862 cOthers = self.oTestFiles.cTreeOthers) ],
2863 ]);
2864
2865
2866 fRc = True;
2867 for (i, tTest) in enumerate(atTests):
2868 oCurTest = tTest[0] # type: tdTestExec
2869 oCurRes = tTest[1] # type: tdTestResultDirRead
2870
2871 reporter.log('Testing #%d, dir="%s" ...' % (i, oCurTest.sDirectory));
2872 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2873 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: Test #%d' % (i,), True);
2874 if fRc is not True:
2875 break;
2876 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc);
2877 fRc = oCurTest.closeSession(True) and fRc;
2878
2879 reporter.log2('Test #%d: Returned %d directories, %d files total' % (i, cDirs, cFiles));
2880 if fRc2 is oCurRes.fRc:
2881 if fRc2 is True:
2882 if oCurRes.cFiles is None:
2883 pass; # ignore
2884 elif oCurRes.cFiles >= 0 and cFiles != oCurRes.cFiles:
2885 fRc = reporter.error('Test #%d failed: Got %d files, expected %d' % (i, cFiles, oCurRes.cFiles));
2886 elif oCurRes.cFiles < 0 and cFiles < -oCurRes.cFiles:
2887 fRc = reporter.error('Test #%d failed: Got %d files, expected at least %d'
2888 % (i, cFiles, -oCurRes.cFiles));
2889 if oCurRes.cDirs is None:
2890 pass; # ignore
2891 elif oCurRes.cDirs >= 0 and cDirs != oCurRes.cDirs:
2892 fRc = reporter.error('Test #%d failed: Got %d directories, expected %d' % (i, cDirs, oCurRes.cDirs));
2893 elif oCurRes.cDirs < 0 and cDirs < -oCurRes.cDirs:
2894 fRc = reporter.error('Test #%d failed: Got %d directories, expected at least %d'
2895 % (i, cDirs, -oCurRes.cDirs));
2896 if oCurRes.cOthers is None:
2897 pass; # ignore
2898 elif oCurRes.cOthers >= 0 and cOthers != oCurRes.cOthers:
2899 fRc = reporter.error('Test #%d failed: Got %d other types, expected %d' % (i, cOthers, oCurRes.cOthers));
2900 elif oCurRes.cOthers < 0 and cOthers < -oCurRes.cOthers:
2901 fRc = reporter.error('Test #%d failed: Got %d other types, expected at least %d'
2902 % (i, cOthers, -oCurRes.cOthers));
2903
2904 else:
2905 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
2906
2907
2908 #
2909 # Go over a few directories in the test file set and compare names,
2910 # types and sizes rather than just the counts like we did above.
2911 #
2912 if fRc is True:
2913 oCurTest = tdTestDirRead();
2914 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2915 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: gctrlReadDirTree2', True);
2916 if fRc is True:
2917 for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir):
2918 reporter.log('Checking "%s" ...' % (oDir.sPath,));
2919 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir) and fRc;
2920 fRc = oCurTest.closeSession(True) and fRc;
2921
2922 return (fRc, oTxsSession);
2923
2924 def testGuestCtrlFileRemove(self, oSession, oTxsSession, oTestVm):
2925 """
2926 Tests removing guest files.
2927 """
2928
2929 ## @todo r=bird: This fails on windows 7 RTM. Just create a stupid file and delete it again,
2930 # this chord.wav stuff is utter nonsense.
2931 if oTestVm.isWindows():
2932 sFileToDelete = "c:\\Windows\\Media\\chord.wav";
2933 else:
2934 sFileToDelete = "/home/vbox/.profile";
2935
2936 atTests = [];
2937 if oTestVm.isWindows():
2938 atTests.extend([
2939 # Invalid stuff.
2940 [ tdTestFileRemove(sFile = ''), tdTestResultFailure() ],
2941 [ tdTestFileRemove(sFile = 'C:\\Windows'), tdTestResultFailure() ],
2942 # More unusual stuff.
2943 [ tdTestFileRemove(sFile = 'z:\\'), tdTestResultFailure() ],
2944 [ tdTestFileRemove(sFile = '\\\\uncrulez\\foo'), tdTestResultFailure() ],
2945 # Non-existing stuff.
2946 [ tdTestFileRemove(sFile = 'c:\\Apps\\nonexisting'), tdTestResultFailure() ],
2947 # Try to delete system files.
2948 [ tdTestFileRemove(sFile = 'c:\\pagefile.sys'), tdTestResultFailure() ],
2949 [ tdTestFileRemove(sFile = 'c:\\Windows\\kernel32.sys'), tdTestResultFailure() ] ## r=bird: it's in \system32\ ...
2950 ]);
2951
2952 if oTestVm.sKind == "WindowsXP":
2953 atTests.extend([
2954 # Try delete some unimportant media stuff.
2955 [ tdTestFileRemove(sFile = 'c:\\Windows\\Media\\chimes.wav'), tdTestResultSuccess() ],
2956 # Second attempt should fail.
2957 [ tdTestFileRemove(sFile = 'c:\\Windows\\Media\\chimes.wav'), tdTestResultFailure() ]
2958 ]);
2959 elif oTestVm.isLinux():
2960 atTests.extend([
2961 # Invalid stuff.
2962 [ tdTestFileRemove(sFile = ''), tdTestResultFailure() ],
2963 [ tdTestFileRemove(sFile = 'C:\\Windows'), tdTestResultFailure() ],
2964 # More unusual stuff.
2965 [ tdTestFileRemove(sFile = 'z:/'), tdTestResultFailure() ],
2966 [ tdTestFileRemove(sFile = '//uncrulez/foo'), tdTestResultFailure() ],
2967 # Non-existing stuff.
2968 [ tdTestFileRemove(sFile = '/non/existing'), tdTestResultFailure() ],
2969 # Try to delete system files.
2970 [ tdTestFileRemove(sFile = '/etc'), tdTestResultFailure() ],
2971 [ tdTestFileRemove(sFile = '/bin/sh'), tdTestResultFailure() ]
2972 ]);
2973
2974 atTests.extend([
2975 # Try delete some unimportant stuff.
2976 [ tdTestFileRemove(sFile = sFileToDelete), tdTestResultSuccess() ],
2977 # Second attempt should fail.
2978 [ tdTestFileRemove(sFile = sFileToDelete), tdTestResultFailure() ]
2979 ]);
2980
2981 fRc = True;
2982 for (i, aTest) in enumerate(atTests):
2983 oCurTest = aTest[0]; # tdTestExec, use an index, later.
2984 oCurRes = aTest[1]; # tdTestResult
2985 reporter.log('Testing #%d, file="%s" ...' % (i, oCurTest.sFile));
2986 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
2987 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileRemove: Test #%d' % (i,));
2988 if fRc is False:
2989 reporter.error('Test #%d failed: Could not create session' % (i,));
2990 break;
2991 try:
2992 if self.oTstDrv.fpApiVer >= 5.0:
2993 oCurGuestSession.fsObjRemove(oCurTest.sFile);
2994 else:
2995 oCurGuestSession.fileRemove(oCurTest.sFile);
2996 except:
2997 if oCurRes.fRc is True:
2998 reporter.errorXcpt('Removing file "%s" failed:' % (oCurTest.sFile,));
2999 fRc = False;
3000 break;
3001 else:
3002 reporter.logXcpt('Removing file "%s" failed expectedly, skipping:' % (oCurTest.sFile,));
3003 oCurTest.closeSession();
3004 return (fRc, oTxsSession);
3005
3006 def testGuestCtrlFileStat(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3007 """
3008 Tests querying file information through stat.
3009 """
3010
3011 # Basic stuff, existing stuff.
3012 aoTests = [
3013 tdTestSessionEx([ tdStepStatDir('.'),
3014 tdStepStatDir('..'),
3015 ]),
3016 ];
3017 if oTestVm.isWindows():
3018 aoTests += [ tdTestSessionEx([ tdStepStatDir('C:\\Windows'),
3019 tdStepStatDir('C:\\Windows\\System32'),
3020 tdStepStatDir('C:\\Windows\\System32\\'),
3021 tdStepStatDir('C:\\Windows\\System32\\.'),
3022 tdStepStatDir('C:\\Windows\\System32\\.\\'),
3023 tdStepStatDir('C:\\Windows\\System32\\..'),
3024 tdStepStatDir('C:\\Windows\\System32\\..\\'),
3025 tdStepStatDir('C:\\Windows\\System32\\..\\\\'),
3026 tdStepStatDir('C:\\Windows\\System32\\\\..\\\\'),
3027 tdStepStatDir('C:/Windows/System32'),
3028 tdStepStatDir('C:/Windows/System32/'),
3029 tdStepStatDir('c:/winDowS/sYsTeM32/'),
3030 tdStepStatDir('C:/Windows/System32/.'),
3031 tdStepStatDir('C:/Windows/System32/./'),
3032 tdStepStatDir('C:/Windows/System32/..'),
3033 tdStepStatDir('C:/Windows/System32/../'),
3034 tdStepStatDir('C:/Windows/System32/..//'),
3035 tdStepStatDir('C:/Windows/System32//..//'),
3036 tdStepStatFile('C:\\Windows\\System32\\kernel32.dll'),
3037 tdStepStatFile('C:/Windows/System32/kernel32.dll')
3038 ]) ];
3039 elif oTestVm.isOS2():
3040 aoTests += [ tdTestSessionEx([ tdStepStatDir('C:\\OS2'),
3041 tdStepStatDir('C:\\OS2\\DLL'),
3042 tdStepStatDir('C:\\OS2\\DLL\\'),
3043 tdStepStatDir('C:/OS2/DLL'),
3044 tdStepStatDir('c:/OS2/DLL'),
3045 tdStepStatDir('c:/OS2/DLL/'),
3046 tdStepStatFile('C:\\CONFIG.SYS'),
3047 tdStepStatFile('C:\\OS2\\DLL\\DOSCALL1.DLL'),
3048 ]) ];
3049 else: # generic unix.
3050 aoTests += [ tdTestSessionEx([ tdStepStatDir('/'),
3051 tdStepStatDir('///'),
3052 tdStepStatDir('/usr/bin/.'),
3053 tdStepStatDir('/usr/bin/./'),
3054 tdStepStatDir('/usr/bin/..'),
3055 tdStepStatDir('/usr/bin/../'),
3056 tdStepStatFile('/bin/ls'),
3057 tdStepStatFile('/bin/cp'),
3058 tdStepStatFile('/bin/date'),
3059 ]) ];
3060 # None existing stuff.
3061 if oTestVm.isWindows() or oTestVm.isOS2():
3062 aoTests += [ tdTestSessionEx([ tdStepStatFileNotFound('C:\\NoSuchFileOrDirectory', ),
3063 tdStepStatPathNotFound('C:\\NoSuchDirectory\\'),
3064 tdStepStatPathNotFound('C:/NoSuchDirectory/'),
3065 tdStepStatPathNotFound('C:\\NoSuchDirectory\\.'),
3066 tdStepStatPathNotFound('C:/NoSuchDirectory/.'),
3067 tdStepStatPathNotFound('C:\\NoSuchDirectory\\NoSuchFileOrDirectory'),
3068 tdStepStatPathNotFound('C:/NoSuchDirectory/NoSuchFileOrDirectory'),
3069 tdStepStatPathNotFound('C:/NoSuchDirectory/NoSuchFileOrDirectory/'),
3070 tdStepStatPathNotFound('N:\\'), # ASSUMES nothing mounted on N:!
3071 tdStepStatPathNotFound('\\\\NoSuchUncServerName\\NoSuchShare'),
3072 ]) ];
3073 else: # generic unix.
3074 aoTests += [ tdTestSessionEx([ tdStepStatFileNotFound('/NoSuchFileOrDirectory', ),
3075 tdStepStatFileNotFound('/bin/NoSuchFileOrDirectory'),
3076 tdStepStatPathNotFound('/NoSuchDirectory/'),
3077 tdStepStatPathNotFound('/NoSuchDirectory/.'),
3078 ]) ];
3079 # Invalid parameter check.
3080 aoTests += [ tdTestSessionEx([ tdStepStat('', vbox.ComError.E_INVALIDARG), ]), ];
3081
3082 # Some test VM specific tests.
3083 if oTestVm.sVmName.startswith('tst-xpsp2'):
3084 aoTests += [ tdTestSessionEx([ tdStepStatFileSize('c:\\Windows\\system32\\kernel32.dll', 983552), ]) ];
3085
3086 #
3087 # Execute the tests.
3088 #
3089 return tdTestSessionEx.executeListTestSessions(aoTests, self.oTstDrv, oSession, oTxsSession, oTestVm, 'FsStat');
3090
3091 def testGuestCtrlFileRead(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3092 """
3093 Tests reading from guest files.
3094 """
3095
3096 if oTxsSession.syncMkDir('${SCRATCH}/testGuestCtrlFileRead') is False:
3097 reporter.error('Could not create scratch directory on guest');
3098 return (False, oTxsSession);
3099
3100 atTests = [];
3101 atTests.extend([
3102 # Invalid stuff.
3103 [ tdTestFileReadWrite(cbToReadWrite = 0), tdTestResultFileReadWrite() ],
3104 [ tdTestFileReadWrite(sFile = ''), tdTestResultFileReadWrite() ],
3105 [ tdTestFileReadWrite(sFile = 'non-existing.file'), tdTestResultFileReadWrite() ],
3106 # Wrong open mode.
3107 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'rt', sDisposition = 'oe'),
3108 tdTestResultFileReadWrite() ],
3109 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'tr', sDisposition = 'oe'),
3110 tdTestResultFileReadWrite() ],
3111 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'wr', sDisposition = 'oe'),
3112 tdTestResultFileReadWrite() ],
3113 # Wrong disposition.
3114 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'r', sDisposition = 'e'),
3115 tdTestResultFileReadWrite() ],
3116 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'r', sDisposition = 'o'),
3117 tdTestResultFileReadWrite() ],
3118 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'r', sDisposition = 'c'),
3119 tdTestResultFileReadWrite() ],
3120 # Opening non-existing file when it should exist.
3121 [ tdTestFileReadWrite(sFile = 'non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3122 tdTestResultFileReadWrite() ],
3123 [ tdTestFileReadWrite(sFile = '\\\\uncrulez\\non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3124 tdTestResultFileReadWrite() ],
3125 [ tdTestFileReadWrite(sFile = '../../non-existing.file', sOpenMode = 'r', sDisposition = 'oe'),
3126 tdTestResultFileReadWrite() ]
3127 ]);
3128
3129 if oTestVm.isWindows():
3130 atTests.extend([
3131 # Create a file which must not exist (but it hopefully does).
3132 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\calc.exe', sOpenMode = 'w', sDisposition = 'ce'),
3133 tdTestResultFileReadWrite() ],
3134 # Open a file which must exist.
3135 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\kernel32.dll', sOpenMode = 'r', sDisposition = 'oe'),
3136 tdTestResultFileReadWrite(fRc = True) ],
3137 # Try truncating a file which already is opened with a different sharing mode (and thus should fail).
3138 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\kernel32.dll', sOpenMode = 'w', sDisposition = 'ot'),
3139 tdTestResultFileReadWrite() ]
3140 ]);
3141
3142 # Note: tst-xppro has other contents in eula.txt.
3143 if oTestVm.sVmName.startswith('tst-xpsp2'):
3144 atTests.extend([
3145 # Reading from beginning.
3146 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\eula.txt',
3147 sOpenMode = 'r', sDisposition = 'oe', cbToReadWrite = 33),
3148 tdTestResultFileReadWrite(fRc = True, abBuf = 'Microsoft(r) Windows(r) XP Profes',
3149 cbProcessed = 33, offFile = 33) ],
3150 # Reading from offset.
3151 [ tdTestFileReadWrite(sFile = 'C:\\Windows\\System32\\eula.txt',
3152 sOpenMode = 'r', sDisposition = 'oe', offFile = 17769, cbToReadWrite = 31),
3153 tdTestResultFileReadWrite(fRc = True, abBuf = 'only with the HARDWARE. If\x0d\x0a ',
3154 cbProcessed = 31, offFile = 17769 + 31) ]
3155 ]);
3156 elif oTestVm.isLinux():
3157 atTests.extend([
3158 # Create a file which must not exist (but it hopefully does).
3159 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'w', sDisposition = 'ce'),
3160 tdTestResultFileReadWrite() ],
3161 # Open a file which must exist.
3162 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'r', sDisposition = 'oe'),
3163 tdTestResultFileReadWrite(fRc = True) ],
3164 # Try truncating a file which already is opened with a different sharing mode (and thus should fail).
3165 [ tdTestFileReadWrite(sFile = '/etc/issue', sOpenMode = 'w', sDisposition = 'ot'),
3166 tdTestResultFileReadWrite() ]
3167 ]);
3168
3169 fRc = True;
3170 for (i, aTest) in enumerate(atTests):
3171 oCurTest = aTest[0]; # tdTestFileReadWrite, use an index, later.
3172 oCurRes = aTest[1]; # tdTestResult
3173 reporter.log('Testing #%d, sFile="%s", cbToReadWrite=%d, sOpenMode="%s", sDisposition="%s", offFile=%d ...'
3174 % (i, oCurTest.sFile, oCurTest.cbToReadWrite, oCurTest.sOpenMode,
3175 oCurTest.sDisposition, oCurTest.offFile));
3176 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3177 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileRead: Test #%d' % (i,));
3178 if fRc is False:
3179 reporter.error('Test #%d failed: Could not create session' % (i,));
3180 break;
3181 try:
3182 fRc2 = True;
3183 if oCurTest.offFile > 0: # The offset parameter is gone.
3184 if self.oTstDrv.fpApiVer >= 5.0:
3185 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3186 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3187 curFile.seek(oCurTest.offFile, vboxcon.FileSeekOrigin_Begin);
3188 else:
3189 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3190 oCurTest.sSharingMode, oCurTest.fCreationMode, oCurTest.offFile);
3191 curOffset = long(curFile.offset);
3192 resOffset = long(oCurTest.offFile);
3193 if curOffset != resOffset:
3194 reporter.error('Test #%d failed: Initial offset on open does not match: Got %d, expected %d'
3195 % (i, curOffset, resOffset));
3196 fRc2 = False;
3197 else:
3198 if self.oTstDrv.fpApiVer >= 5.0:
3199 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3200 oCurTest.fCreationMode);
3201 else:
3202 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3203 oCurTest.fCreationMode);
3204 if fRc2 and oCurTest.cbToReadWrite > 0:
3205 ## @todo Split this up in 64K reads. Later.
3206 ## @todo Test timeouts.
3207 aBufRead = curFile.read(oCurTest.cbToReadWrite, 30 * 1000);
3208 if oCurRes.cbProcessed > 0 \
3209 and oCurRes.cbProcessed != len(aBufRead):
3210 reporter.error('Test #%d failed: Read buffer length does not match: Got %d, expected %d'
3211 % (i, len(aBufRead), oCurRes.cbProcessed));
3212 fRc2 = False;
3213 if fRc2:
3214 if oCurRes.abBuf is not None \
3215 and not utils.areBytesEqual(oCurRes.abBuf, aBufRead):
3216 reporter.error('Test #%d failed: Got buffer:\n"%s" (%d bytes, type %s)\n'
3217 'Expected buffer:\n"%s" (%d bytes, type %s)'
3218 % (i, map(hex, map(ord, aBufRead)), len(aBufRead), type(aBufRead),
3219 map(hex, map(ord, oCurRes.abBuf)), len(oCurRes.abBuf), type(oCurRes.abBuf),));
3220 reporter.error('Test #%d failed: Got buffer:\n"%s"\nExpected buffer:\n"%s"'
3221 % (i, aBufRead, oCurRes.abBuf));
3222 fRc2 = False;
3223 # Test final offset.
3224 curOffset = long(curFile.offset);
3225 resOffset = long(oCurRes.offFile);
3226 if curOffset != resOffset:
3227 reporter.error('Test #%d failed: Final offset does not match: Got %d, expected %d' \
3228 % (i, curOffset, resOffset));
3229 fRc2 = False;
3230 curFile.close();
3231
3232 if fRc2 != oCurRes.fRc:
3233 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3234 fRc = False;
3235
3236 except:
3237 reporter.logXcpt('Opening "%s" failed:' % (oCurTest.sFile,));
3238 fRc = False;
3239
3240 oCurTest.closeSession();
3241
3242 return (fRc, oTxsSession);
3243
3244 def testGuestCtrlFileWrite(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3245 """
3246 Tests writing to guest files.
3247 """
3248
3249 if oTestVm.isWindows():
3250 sScratch = "C:\\Temp\\vboxtest\\testGuestCtrlFileWrite\\";
3251 else:
3252 sScratch = "/tmp/";
3253
3254 if oTxsSession.syncMkDir('${SCRATCH}/testGuestCtrlFileWrite') is False:
3255 reporter.error('Could not create scratch directory on guest');
3256 return (False, oTxsSession);
3257
3258 atTests = [];
3259
3260 cbScratchBuf = random.randint(1, 4096);
3261 abScratchBuf = os.urandom(cbScratchBuf);
3262 atTests.extend([
3263 # Write to a non-existing file.
3264 [ tdTestFileReadWrite(sFile = sScratch + 'testGuestCtrlFileWrite.txt',
3265 sOpenMode = 'w+', sDisposition = 'ce', cbToReadWrite = cbScratchBuf, abBuf = abScratchBuf),
3266 tdTestResultFileReadWrite(fRc = True, abBuf = abScratchBuf, cbProcessed = cbScratchBuf, offFile = cbScratchBuf) ],
3267 ]);
3268
3269 aScratchBuf2 = os.urandom(cbScratchBuf);
3270 atTests.extend([
3271 # Append the same amount of data to the just created file.
3272 [ tdTestFileReadWrite(sFile = sScratch + 'testGuestCtrlFileWrite.txt',
3273 sOpenMode = 'w+', sDisposition = 'oa', cbToReadWrite = cbScratchBuf,
3274 offFile = cbScratchBuf, abBuf = aScratchBuf2),
3275 tdTestResultFileReadWrite(fRc = True, abBuf = aScratchBuf2, cbProcessed = cbScratchBuf,
3276 offFile = cbScratchBuf * 2) ],
3277 ]);
3278
3279 fRc = True;
3280 for (i, aTest) in enumerate(atTests):
3281 oCurTest = aTest[0]; # tdTestFileReadWrite, use an index, later.
3282 oCurRes = aTest[1]; # tdTestResult
3283 reporter.log('Testing #%d, sFile="%s", cbToReadWrite=%d, sOpenMode="%s", sDisposition="%s", offFile=%d ...'
3284 % (i, oCurTest.sFile, oCurTest.cbToReadWrite, oCurTest.sOpenMode,
3285 oCurTest.sDisposition, oCurTest.offFile,));
3286 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3287 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlFileWrite: Test #%d' % (i,));
3288 if fRc is False:
3289 reporter.error('Test #%d failed: Could not create session' % (i,));
3290 break;
3291
3292 try:
3293 if oCurTest.offFile > 0: # The offset parameter is gone.
3294 if self.oTstDrv.fpApiVer >= 5.0:
3295 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3296 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3297 curFile.seek(oCurTest.offFile, vboxcon.FileSeekOrigin_Begin);
3298 else:
3299 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3300 oCurTest.sSharingMode, oCurTest.fCreationMode, oCurTest.offFile);
3301 curOffset = long(curFile.offset);
3302 resOffset = long(oCurTest.offFile);
3303 if curOffset != resOffset:
3304 reporter.error('Test #%d failed: Initial offset on open does not match: Got %d, expected %d' \
3305 % (i, curOffset, resOffset));
3306 fRc = False;
3307 else:
3308 if self.oTstDrv.fpApiVer >= 5.0:
3309 curFile = oCurGuestSession.fileOpenEx(oCurTest.sFile, oCurTest.getAccessMode(), oCurTest.getOpenAction(),
3310 oCurTest.getSharingMode(), oCurTest.fCreationMode, []);
3311 else:
3312 curFile = oCurGuestSession.fileOpen(oCurTest.sFile, oCurTest.sOpenMode, oCurTest.sDisposition,
3313 oCurTest.fCreationMode);
3314 if fRc and oCurTest.cbToReadWrite > 0:
3315 reporter.log("File '%s' opened" % oCurTest.sFile);
3316 ## @todo Split this up in 64K writes. Later.
3317 ## @todo Test timeouts.
3318 cBytesWritten = curFile.write(array('b', oCurTest.abBuf), 30 * 1000);
3319 if oCurRes.cbProcessed > 0 \
3320 and oCurRes.cbProcessed != cBytesWritten:
3321 reporter.error('Test #%d failed: Written buffer length does not match: Got %d, expected %d' \
3322 % (i, cBytesWritten, oCurRes.cbProcessed));
3323 fRc = False;
3324 if fRc:
3325 # Verify written content by seeking back to the initial offset and
3326 # re-read & compare the written data.
3327 try:
3328 if self.oTstDrv.fpApiVer >= 5.0:
3329 curFile.seek(-(oCurTest.cbToReadWrite), vboxcon.FileSeekOrigin_Current);
3330 else:
3331 curFile.seek(-(oCurTest.cbToReadWrite), vboxcon.FileSeekType_Current);
3332 except:
3333 reporter.logXcpt('Seeking back to initial write position failed:');
3334 fRc = False;
3335 if fRc and long(curFile.offset) != oCurTest.offFile:
3336 reporter.error('Test #%d failed: Initial write position does not match current position, ' \
3337 'got %d, expected %d' % (i, long(curFile.offset), oCurTest.offFile));
3338 fRc = False;
3339 if fRc:
3340 aBufRead = curFile.read(oCurTest.cbToReadWrite, 30 * 1000);
3341 if len(aBufRead) != oCurTest.cbToReadWrite:
3342 reporter.error('Test #%d failed: Got buffer length %d, expected %d' \
3343 % (i, len(aBufRead), oCurTest.cbToReadWrite));
3344 fRc = False;
3345 if fRc \
3346 and oCurRes.abBuf is not None \
3347 and bytes(oCurRes.abBuf) != bytes(aBufRead):
3348 reporter.error('Test #%d failed: Read back buffer (%d bytes) does not match ' \
3349 'written content (%d bytes)' % (i, len(aBufRead), len(aBufRead)));
3350
3351 curFile.close();
3352
3353 # Download written file from guest.
3354 aGstFiles = [];
3355 aGstFiles.append(oCurTest.sFile.replace('\\', '/'));
3356 self.oTstDrv.txsDownloadFiles(oSession, oTxsSession, aGstFiles, fIgnoreErrors = True);
3357
3358 # Create files with buffer contents and upload those for later (manual) inspection.
3359 oCurTest.uploadLogData(self.oTstDrv, oCurRes.abBuf, ('testGuestCtrlWriteTest%d-BufExcepted' % i),
3360 ('Test #%d: Expected buffer' % i));
3361 oCurTest.uploadLogData(self.oTstDrv, aBufRead, ('testGuestCtrlWriteTest%d-BufGot' % i),
3362 ('Test #%d: Got buffer' % i));
3363 fRc = False;
3364 # Test final offset.
3365 curOffset = long(curFile.offset);
3366 resOffset = long(oCurRes.offFile);
3367 if curOffset != resOffset:
3368 reporter.error('Test #%d failed: Final offset does not match: Got %d, expected %d' \
3369 % (i, curOffset, resOffset));
3370 fRc = False;
3371 if curFile.status == vboxcon.FileStatus_Open:
3372 curFile.close();
3373 reporter.log("File '%s' closed" % oCurTest.sFile);
3374 except:
3375 reporter.logXcpt('Opening "%s" failed:' % (oCurTest.sFile,));
3376 fRc = False;
3377
3378 oCurTest.closeSession();
3379
3380 if fRc != oCurRes.fRc:
3381 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
3382 fRc = False;
3383 break;
3384
3385 return (fRc, oTxsSession);
3386
3387 @staticmethod
3388 def __generateFile(sName, cbFile):
3389 """ Helper for generating a file with a given size. """
3390 oFile = open(sName, 'wb');
3391 while cbFile > 0:
3392 cb = cbFile if cbFile < 256*1024 else 256*1024;
3393 oFile.write(bytearray(random.getrandbits(8) for _ in xrange(cb)));
3394 cbFile -= cb;
3395 oFile.close();
3396
3397 def testGuestCtrlCopyTo(self, oSession, oTxsSession, oTestVm):
3398 """
3399 Tests copying files from host to the guest.
3400 """
3401
3402 # Paths.
3403 sScratchGst = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'testGuestCtrlCopyTo');
3404 #sScratchGstNotExist = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'no-such-file-or-directory');
3405 sScratchHstNotExist = os.path.join(self.oTstDrv.sScratchPath, 'no-such-file-or-directory');
3406 sScratchGstPathNotFound = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'no-such-directory', 'or-file');
3407 #sScratchHstPathNotFound = os.path.join(self.oTstDrv.sScratchPath, 'no-such-directory', 'or-file');
3408 sSomeDirHst = self.oTstDrv.sScriptPath;
3409
3410 if oTestVm.isWindows() or oTestVm.isOS2():
3411 sScratchGstInvalid = "?*|<invalid-name>";
3412 else:
3413 sScratchGstInvalid = None;
3414
3415 if oTxsSession.syncMkDir(sScratchGst) is not True:
3416 return reporter.error('TXS failed to create directory "%s"!' % (sScratchGst,));
3417
3418 # Generate a test file in 32MB to 50 MB range.
3419 sBigFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-random.data');
3420 cbBigFileHst = random.randrange(32*1024*1024, 50*1024*1024);
3421 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
3422 cbLeft = cbBigFileHst;
3423 try:
3424 self.__generateFile(sBigFileHst, cbBigFileHst);
3425 except:
3426 return reporter.errorXcpt('sBigFileHst=%s cbBigFileHst=%s cbLeft=%s' % (sBigFileHst, cbBigFileHst, cbLeft,));
3427 reporter.log('cbBigFileHst=%s' % (cbBigFileHst,));
3428
3429 # Generate an empty file on the host that we can use to save space in the guest.
3430 sEmptyFileHst = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-empty.data');
3431 try:
3432 oFile = open(sEmptyFileHst, "wb");
3433 oFile.close();
3434 except:
3435 return reporter.errorXcpt('sEmptyFileHst=%s' % (sEmptyFileHst,));
3436
3437 #
3438 # Tests.
3439 #
3440 atTests = [
3441 ## @todo because of the way the test stats the source to figure out which API to use,
3442 ## not all of this necessarily testing both file and directory API variants like
3443 ## was intended. This needs to be addressed by specializing tdTestCopyTo so it
3444 ## would be possible to test feeding directories to the file API and vice versa.
3445
3446 # Nothing given
3447 [ tdTestCopyTo(), tdTestResultFailure() ],
3448 # Only one given.
3449 [ tdTestCopyTo(sSrc = sBigFileHst), tdTestResultFailure() ],
3450 [ tdTestCopyTo(sDst = sScratchGst), tdTestResultFailure() ],
3451 # Only one given, invalid flag.
3452 [ tdTestCopyTo(sSrc = sBigFileHst, fFlags = [ 0x40000000, ]), tdTestResultFailure() ],
3453 [ tdTestCopyTo(sDst = sScratchGst, fFlags = [ 0x40000000, ]), tdTestResultFailure() ],
3454 ## Apparently Main doesn't check the flags, so the first test succeeds.
3455 ## Both given, but invalid flags.
3456 #[ tdTestCopyTo(sSrc = sBigFileHst, sDst = sScratchGst, fFlags = [ 0x40000000] ), tdTestResultFailure() ],
3457 #[ tdTestCopyTo(sSrc = sSomeDirHst, sDst = sScratchGst, fFlags = [ 0x40000000] ), tdTestResultFailure() ],
3458 # Bogus source, but no destination.
3459 [ tdTestCopyTo(sSrc = sScratchHstNotExist), tdTestResultFailure() ],
3460 # Valid sources, but bogus destination (path not found).
3461 [ tdTestCopyTo(sSrc = sBigFileHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
3462 [ tdTestCopyTo(sSrc = sSomeDirHst, sDst = sScratchGstPathNotFound), tdTestResultFailure() ],
3463 ];
3464 if sScratchGstInvalid is not None:
3465 # Invalid characters in destination path:
3466 atTests.extend([
3467 [ tdTestCopyTo(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
3468 tdTestResultFailure() ],
3469 [ tdTestCopyTo(sSrc = sSomeDirHst, sDst = oTestVm.pathJoin(sScratchGst, sScratchGstInvalid)),
3470 tdTestResultFailure() ],
3471 ]);
3472
3473 #
3474 # Single file handling.
3475 #
3476 atTests.extend([
3477 [ tdTestCopyTo(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')),
3478 tdTestResultSuccess() ],
3479 [ tdTestCopyTo(sSrc = sBigFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
3480 tdTestResultSuccess() ],
3481 [ tdTestCopyTo(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, 'HostGABig.dat')), # Overwrite
3482 tdTestResultSuccess() ],
3483 ]);
3484 if self.oTstDrv.fpApiVer > 5.2: # Copying files into directories via Main is supported only 6.0 and later.
3485 atTests.extend([
3486 [ tdTestCopyTo(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ],
3487 [ tdTestCopyTo(sSrc = sBigFileHst, sDst = sScratchGst), tdTestResultSuccess() ], # Overwrite
3488 [ tdTestCopyTo(sSrc = sEmptyFileHst, sDst = oTestVm.pathJoin(sScratchGst, os.path.split(sBigFileHst)[1])),
3489 tdTestResultSuccess() ], # Overwrite
3490 ]);
3491
3492 if oTestVm.isWindows():
3493 # Copy to a Windows alternative data stream (ADS).
3494 atTests.extend([
3495 [ tdTestCopyTo(sSrc = sBigFileHst, sDst = os.path.join(sScratchGst, 'HostGABig.dat:ADS-Test')),
3496 tdTestResultSuccess() ],
3497 [ tdTestCopyTo(sSrc = sEmptyFileHst, sDst = os.path.join(sScratchGst, 'HostGABig.dat:ADS-Test')),
3498 tdTestResultSuccess() ],
3499 ]);
3500
3501 #
3502 # Directory handling.
3503 #
3504 if self.oTstDrv.fpApiVer > 5.2: # Copying directories via Main is supported only in versions > 5.2.
3505 # Create a directory to copy.
3506 sHstCopyDir = os.path.join(self.oTstDrv.sScratchPath, 'gctrl-srcdir');
3507 try: ## @todo Take the TestFileSet idea to the generic realm, making host and guest specializations/whatever.
3508 os.mkdir(sHstCopyDir);
3509 os.mkdir( os.path.join(sHstCopyDir, 'subdir1'));
3510 os.mkdir( os.path.join(sHstCopyDir, 'subdir2'));
3511 os.mkdir( os.path.join(sHstCopyDir, 'subdir2', 'subsub1'));
3512 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub1', 'file0'), 0);
3513 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub1', 'file1'), 1023);
3514 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub1', 'file2'), 2048);
3515 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub1', 'file3'), 2047);
3516 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub1', 'file4'), 16887);
3517 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub1', 'file4'), 32);
3518 os.mkdir( os.path.join(sHstCopyDir, 'subdir2', 'subsub2'));
3519 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub2', 'file5'), 31);
3520 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub2', 'file6'), 1);
3521 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub2', 'file7'), 1);
3522 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub2', 'file8'), 0);
3523 os.mkdir( os.path.join(sHstCopyDir, 'subdir2', 'subsub3'));
3524 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub3', 'file9'), 9);
3525 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub3', 'file10'), 63);
3526 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub3', 'file11'), 11);
3527 self.__generateFile(os.path.join(sHstCopyDir, 'subdir2', 'subsub3', 'file12'), 67);
3528 os.mkdir( os.path.join(sHstCopyDir, 'subdir3'));
3529 self.__generateFile(os.path.join(sHstCopyDir, 'file13'), 13);
3530 self.__generateFile(os.path.join(sHstCopyDir, 'file14'), 67);
3531 self.__generateFile(os.path.join(sHstCopyDir, 'file15'), 1111);
3532 except:
3533 reporter.errorXcpt('Error generating test tree on the host for the copy test (%s)' % (sHstCopyDir,));
3534
3535 atTests.extend([
3536 [ tdTestCopyTo(sSrc = sHstCopyDir, sDst = sScratchGst, fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting ]),
3537 tdTestResultSuccess() ],
3538 ## @todo r=bird: Why does this fail???
3539 # [ tdTestCopyTo(sSrc = sHstCopyDir, sDst = oTestVm.pathJoin(sScratchGst, 'target-dir')), tdTestResultSuccess() ],
3540 ]);
3541
3542 fRc = True;
3543 for (i, tTest) in enumerate(atTests):
3544 oCurTest = tTest[0]; # tdTestCopyTo
3545 oCurRes = tTest[1]; # tdTestResult
3546 reporter.log('Testing #%d, sSrc=%s, sDst=%s, fFlags=%s ...' % (i, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags));
3547
3548 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3549 fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyTo: Test #%d' % (i,), fIsError = True);
3550 if fRc is not True:
3551 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3552 break;
3553
3554 fRc2 = False;
3555 if os.path.isdir(oCurTest.sSrc): ## @todo r=bird: Not good enough. Test case must know which one it's testing.
3556 fRc2 = self.gctrlCopyDirTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags, oCurRes.fRc);
3557 else:
3558 fRc2 = self.gctrlCopyFileTo(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags, oCurRes.fRc);
3559 if fRc2 is not oCurRes.fRc:
3560 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3561 else:
3562 pass; ## @todo verify what was copied!!
3563
3564 fRc = oCurTest.closeSession(True) and fRc;
3565
3566 return (fRc, oTxsSession);
3567
3568 def testGuestCtrlCopyFrom(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3569 """
3570 Tests copying files from guest to the host.
3571 """
3572
3573 #
3574 # Paths.
3575 #
3576 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom");
3577 oExistingFileGst = self.oTestFiles.chooseRandomFileFromTree();
3578 oNonEmptyDirGst = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True);
3579 oEmptyDirGst = self.oTestFiles.oEmptyDir;
3580
3581 if oTestVm.isWindows() or oTestVm.isOS2():
3582 sScratchGstInvalid = "?*|<invalid-name>";
3583 else:
3584 sScratchGstInvalid = None;
3585 if utils.getHostOs() in ('win', 'os2'):
3586 sScratchHstInvalid = "?*|<invalid-name>";
3587 else:
3588 sScratchHstInvalid = None;
3589
3590 if os.path.exists(sScratchHst):
3591 if base.wipeDirectory(sScratchHst) != 0:
3592 return reporter.error('Failed to wipe "%s"' % (sScratchHst,));
3593 else:
3594 try:
3595 os.mkdir(sScratchHst)
3596 except:
3597 return reporter.errorXcpt('sScratchHst=%s' % (sScratchHst, ));
3598
3599 #
3600 # Bad parameter tests.
3601 #
3602 atTests = [
3603 # Missing both source and destination:
3604 [ tdTestCopyFromFile(), tdTestResultFailure() ],
3605 [ tdTestCopyFromDir(), tdTestResultFailure() ],
3606 # Missing source.
3607 [ tdTestCopyFromFile(sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3608 [ tdTestCopyFromDir( sDst = sScratchHst), tdTestResultFailure() ],
3609 # Missing destination.
3610 [ tdTestCopyFromFile(oSrc = oExistingFileGst), tdTestResultFailure() ],
3611 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath), tdTestResultFailure() ],
3612 ##
3613 ## @todo main isn't validating flags, so these theses will succeed.
3614 ##
3615 ## Invalid flags:
3616 #[ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somefile'), fFlags = [ 0x40000000] ),
3617 # tdTestResultFailure() ],
3618 #[ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'somedir'), fFlags = [ 0x40000000] ),
3619 # tdTestResultFailure() ],
3620 # Non-existing sources:
3621 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
3622 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3623 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-file-or-directory'),
3624 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3625 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-file'),
3626 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3627 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, 'no-such-directory', 'no-such-subdir'),
3628 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3629 # Non-existing destinations:
3630 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
3631 sDst = os.path.join(sScratchHst, 'no-such-directory', 'somefile') ), tdTestResultFailure() ],
3632 [ tdTestCopyFromDir( oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'no-such-directory', 'somedir') ),
3633 tdTestResultFailure() ],
3634 [ tdTestCopyFromFile(oSrc = oExistingFileGst,
3635 sDst = os.path.join(sScratchHst, 'no-such-directory-slash' + os.path.sep)),
3636 tdTestResultFailure() ],
3637 # Wrong source type:
3638 [ tdTestCopyFromFile(oSrc = oNonEmptyDirGst, sDst = os.path.join(sScratchHst, 'somefile') ), tdTestResultFailure() ],
3639 [ tdTestCopyFromDir(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'somedir') ), tdTestResultFailure() ],
3640 ];
3641 # Bogus names:
3642 if sScratchHstInvalid:
3643 atTests.extend([
3644 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
3645 tdTestResultFailure() ],
3646 [ tdTestCopyFromDir( sSrc = self.oTestFiles.oManyDir.sPath, sDst = os.path.join(sScratchHst, sScratchHstInvalid)),
3647 tdTestResultFailure() ],
3648 ]);
3649 if sScratchGstInvalid:
3650 atTests.extend([
3651 [ tdTestCopyFromFile(sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
3652 sDst = os.path.join(sScratchHst, 'somefile')), tdTestResultFailure() ],
3653 [ tdTestCopyFromDir( sSrc = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sScratchGstInvalid),
3654 sDst = os.path.join(sScratchHst, 'somedir')), tdTestResultFailure() ],
3655 ]);
3656
3657 #
3658 # Single file copying.
3659 #
3660 atTests.extend([
3661 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')),
3662 tdTestResultSuccess() ],
3663 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile1')), # Overwrite it
3664 tdTestResultSuccess() ],
3665 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = os.path.join(sScratchHst, 'copyfile2')),
3666 tdTestResultSuccess() ],
3667 ]);
3668 if self.oTstDrv.fpApiVer >= 5.2:
3669 # Copy into a directory.
3670 atTests.extend([
3671 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst), tdTestResultSuccess() ],
3672 [ tdTestCopyFromFile(oSrc = oExistingFileGst, sDst = sScratchHst + os.path.sep), tdTestResultSuccess() ],
3673 ]);
3674
3675 #
3676 # Directory tree copying:
3677 #
3678 atTests.extend([
3679 # Copy the empty guest directory (should end up as sScratchHst/empty):
3680 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchHst), tdTestResultSuccess() ],
3681 # Repeat -- this time it should fail, as the destination directory already exists (and
3682 # DirectoryCopyFlag_CopyIntoExisting is not specified):
3683 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchHst), tdTestResultFailure() ],
3684 # Add the DirectoryCopyFlag_CopyIntoExisting flag being set and it should work.
3685 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchHst,
3686 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3687 # Try again with trailing slash
3688 [ tdTestRemoveHostDir(os.path.join(sScratchHst, 'empty')), tdTestResult() ],
3689 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchHst + os.path.sep),
3690 tdTestResultSuccess() ],
3691 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchHst + os.path.sep),
3692 tdTestResultFailure() ],
3693 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = sScratchHst + os.path.sep,
3694 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3695 # Copy with a different destination name:
3696 [ tdTestCopyFromDir(oSrc = oEmptyDirGst, sDst = os.path.join(sScratchHst, 'empty2')),
3697 tdTestResultFailure() ],
3698 # Now the same using a directory with files in it:
3699 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchHst), tdTestResultSuccess() ],
3700 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchHst), tdTestResultFailure() ],
3701 [ tdTestCopyFromDir(oSrc = oNonEmptyDirGst, sDst = sScratchHst,
3702 fFlags = [ vboxcon.DirectoryCopyFlag_CopyIntoExisting, ]), tdTestResultSuccess() ],
3703 # Copy the entire test tree:
3704 [ tdTestCopyFromDir(sSrc = self.oTestFiles.oTreeDir.sPath, sDst = sScratchHst), tdTestResultSuccess() ],
3705 ]);
3706
3707 #
3708 # Execute the tests.
3709 #
3710 fRc = True;
3711 for (i, tTest) in enumerate(atTests):
3712 oCurTest = tTest[0]
3713 oCurRes = tTest[1] # type: tdTestResult
3714 if isinstance(oCurTest, tdTestCopyFrom):
3715 reporter.log('Testing #%d, %s: sSrc="%s", sDst="%s", fFlags="%s" ...'
3716 % (i, "directory" if isinstance(oCurTest, tdTestCopyFromDir) else "file",
3717 oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags,));
3718 else:
3719 reporter.log('Testing #%d, tdTestRemoveHostDir "%s" ...' % (i, oCurTest.sDir,));
3720 if isinstance(oCurTest, tdTestCopyFromDir) and self.oTstDrv.fpApiVer < 6.0:
3721 reporter.log('Skipping directoryCopyFromGuest test, not implemented in %s' % (self.oTstDrv.fpApiVer,));
3722 continue;
3723
3724 if isinstance(oCurTest, tdTestRemoveHostDir):
3725 fRc = oCurTest.execute(self.oTstDrv, oSession, oTxsSession, oTestVm, 'testing #%d' % (i,));
3726 else:
3727 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3728 fRc2, oCurGuestSession = oCurTest.createSession('testGuestCtrlCopyFrom: Test #%d' % (i,), fIsError = True);
3729 if fRc2 is not True:
3730 fRc = reporter.error('Test #%d failed: Could not create session' % (i,));
3731 break;
3732
3733 if isinstance(oCurTest, tdTestCopyFromFile):
3734 fRc2 = self.gctrlCopyFileFrom(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags, oCurRes.fRc);
3735 else:
3736 fRc2 = self.gctrlCopyDirFrom(oCurGuestSession, oCurTest.sSrc, oCurTest.sDst, oCurTest.fFlags, oCurRes.fRc);
3737
3738 if fRc2 != oCurRes.fRc:
3739 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
3740 fRc2 = False;
3741
3742 if fRc2 is True:
3743 pass; ## @todo verify the result.
3744
3745 fRc = oCurTest.closeSession(fIsError = True) and fRc;
3746
3747 return (fRc, oTxsSession);
3748
3749 def testGuestCtrlUpdateAdditions(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals
3750 """
3751 Tests updating the Guest Additions inside the guest.
3752
3753 """
3754
3755 # Skip test for updating Guest Additions if we run on a too old (Windows) guest.
3756 ##
3757 ## @todo make it work everywhere!
3758 ##
3759 if oTestVm.sKind in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
3760 reporter.log("Skipping updating GAs on old windows vm (sKind=%s)" % (oTestVm.sKind,));
3761 return (None, oTxsSession);
3762 if oTestVm.isOS2():
3763 reporter.log("Skipping updating GAs on OS/2 guest");
3764 return (None, oTxsSession);
3765
3766 # Some stupid trickery to guess the location of the iso.
3767 sVBoxValidationKitISO = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxValidationKit.iso'));
3768 if not os.path.isfile(sVBoxValidationKitISO):
3769 sVBoxValidationKitISO = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../VBoxTestSuite.iso'));
3770 if not os.path.isfile(sVBoxValidationKitISO):
3771 sCur = os.getcwd();
3772 for i in xrange(0, 10):
3773 sVBoxValidationKitISO = os.path.join(sCur, 'validationkit/VBoxValidationKit.iso');
3774 if os.path.isfile(sVBoxValidationKitISO):
3775 break;
3776 sVBoxValidationKitISO = os.path.join(sCur, 'testsuite/VBoxTestSuite.iso');
3777 if os.path.isfile(sVBoxValidationKitISO):
3778 break;
3779 sCur = os.path.abspath(os.path.join(sCur, '..'));
3780 if i is None: pass; # shut up pychecker/pylint.
3781 if os.path.isfile(sVBoxValidationKitISO):
3782 reporter.log('Validation Kit .ISO found at: %s' % (sVBoxValidationKitISO,));
3783 else:
3784 reporter.log('Warning: Validation Kit .ISO not found -- some tests might fail');
3785
3786 sScratch = os.path.join(self.oTstDrv.sScratchPath, "testGctrlUpdateAdditions");
3787 try:
3788 os.makedirs(sScratch);
3789 except OSError as e:
3790 if e.errno != errno.EEXIST:
3791 reporter.error('Failed: Unable to create scratch directory \"%s\"' % (sScratch,));
3792 return (False, oTxsSession);
3793 reporter.log('Scratch path is: %s' % (sScratch,));
3794
3795 atTests = [];
3796 if oTestVm.isWindows():
3797 atTests.extend([
3798 # Source is missing.
3799 [ tdTestUpdateAdditions(sSrc = ''), tdTestResultFailure() ],
3800
3801 # Wrong fFlags.
3802 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
3803 fFlags = [ 1234 ]), tdTestResultFailure() ],
3804
3805 # Non-existing .ISO.
3806 [ tdTestUpdateAdditions(sSrc = "non-existing.iso"), tdTestResultFailure() ],
3807
3808 # Wrong .ISO.
3809 [ tdTestUpdateAdditions(sSrc = sVBoxValidationKitISO), tdTestResultFailure() ],
3810
3811 # The real thing.
3812 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso()),
3813 tdTestResultSuccess() ],
3814 # Test the (optional) installer arguments. This will extract the
3815 # installer into our guest's scratch directory.
3816 [ tdTestUpdateAdditions(sSrc = self.oTstDrv.getGuestAdditionsIso(),
3817 asArgs = [ '/extract', '/D=' + sScratch ]),
3818 tdTestResultSuccess() ]
3819 # Some debg ISO. Only enable locally.
3820 #[ tdTestUpdateAdditions(
3821 # sSrc = "V:\\Downloads\\VBoxGuestAdditions-r80354.iso"),
3822 # tdTestResultSuccess() ]
3823 ]);
3824 else:
3825 reporter.log('No OS-specific tests for non-Windows yet!');
3826
3827 fRc = True;
3828 for (i, aTest) in enumerate(atTests):
3829 oCurTest = aTest[0]; # tdTestExec, use an index, later.
3830 oCurRes = aTest[1]; # tdTestResult
3831 reporter.log('Testing #%d, sSrc="%s", fFlags="%s" ...' % \
3832 (i, oCurTest.sSrc, oCurTest.fFlags));
3833 oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
3834 fRc, _ = oCurTest.createSession('Test #%d' % (i,));
3835 if fRc is False:
3836 reporter.error('Test #%d failed: Could not create session' % (i,));
3837 break;
3838 try:
3839 oCurProgress = oCurTest.oTest.oGuest.updateGuestAdditions(oCurTest.sSrc, oCurTest.asArgs, oCurTest.fFlags);
3840 if oCurProgress is not None:
3841 oProgress = vboxwrappers.ProgressWrapper(oCurProgress, self.oTstDrv.oVBoxMgr, self.oTstDrv, "gctrlUpGA");
3842 try:
3843 oProgress.wait();
3844 if not oProgress.isSuccess():
3845 oProgress.logResult(fIgnoreErrors = True);
3846 fRc = False;
3847 except:
3848 reporter.logXcpt('Waiting exception for updating Guest Additions:');
3849 fRc = False;
3850 else:
3851 reporter.error('No progress object returned');
3852 fRc = False;
3853 except:
3854 # Just log, don't assume an error here (will be done in the main loop then).
3855 reporter.logXcpt('Updating Guest Additions exception for sSrc="%s", fFlags="%s":' \
3856 % (oCurTest.sSrc, oCurTest.fFlags));
3857 fRc = False;
3858 oCurTest.closeSession();
3859 if fRc is oCurRes.fRc:
3860 if fRc:
3861 ## @todo Verify if Guest Additions were really updated (build, revision, ...).
3862 pass;
3863 else:
3864 reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc, oCurRes.fRc));
3865 fRc = False;
3866 break;
3867
3868 return (fRc, oTxsSession);
3869
3870
3871
3872class tdAddGuestCtrl(vbox.TestDriver): # pylint: disable=too-many-instance-attributes,too-many-public-methods
3873 """
3874 Guest control using VBoxService on the guest.
3875 """
3876
3877 def __init__(self):
3878 vbox.TestDriver.__init__(self);
3879 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
3880 self.asRsrcs = None;
3881 self.fQuick = False; # Don't skip lengthly tests by default.
3882 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
3883
3884 #
3885 # Overridden methods.
3886 #
3887 def showUsage(self):
3888 """
3889 Shows the testdriver usage.
3890 """
3891 rc = vbox.TestDriver.showUsage(self);
3892 reporter.log('');
3893 reporter.log('tdAddGuestCtrl Options:');
3894 reporter.log(' --quick');
3895 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
3896 return rc;
3897
3898 def parseOption(self, asArgs, iArg): # pylint: disable=too-many-branches,too-many-statements
3899 """
3900 Parses the testdriver arguments from the command line.
3901 """
3902 if asArgs[iArg] == '--quick':
3903 self.parseOption(['--virt-modes', 'hwvirt'], 0);
3904 self.parseOption(['--cpu-counts', '1'], 0);
3905 self.fQuick = True;
3906 else:
3907 return vbox.TestDriver.parseOption(self, asArgs, iArg);
3908 return iArg + 1;
3909
3910 def actionConfig(self):
3911 if not self.importVBoxApi(): # So we can use the constant below.
3912 return False;
3913
3914 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
3915 sGaIso = self.getGuestAdditionsIso();
3916 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
3917
3918 def actionExecute(self):
3919 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
3920
3921 #
3922 # Test execution helpers.
3923 #
3924 def testOneCfg(self, oVM, oTestVm): # pylint: disable=too-many-statements
3925 """
3926 Runs the specified VM thru the tests.
3927
3928 Returns a success indicator on the general test execution. This is not
3929 the actual test result.
3930 """
3931
3932 self.logVmInfo(oVM);
3933
3934 fRc = True;
3935 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False);
3936 reporter.log("TxsSession: %s" % (oTxsSession,));
3937 if oSession is not None:
3938 self.addTask(oTxsSession);
3939
3940 fManual = False; # Manual override for local testing. (Committed version shall be False.)
3941 if not fManual:
3942 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
3943 else:
3944 fRc, oTxsSession = self.testGuestCtrlManual(oSession, oTxsSession, oTestVm);
3945
3946 # Cleanup.
3947 self.removeTask(oTxsSession);
3948 if not fManual:
3949 self.terminateVmBySession(oSession);
3950 else:
3951 fRc = False;
3952 return fRc;
3953
3954 def gctrlReportError(self, progress):
3955 """
3956 Helper function to report an error of a
3957 given progress object.
3958 """
3959 if progress is None:
3960 reporter.log('No progress object to print error for');
3961 else:
3962 errInfo = progress.errorInfo;
3963 if errInfo:
3964 reporter.log('%s' % (errInfo.text,));
3965 return False;
3966
3967 def gctrlGetRemainingTime(self, msTimeout, msStart):
3968 """
3969 Helper function to return the remaining time (in ms)
3970 based from a timeout value and the start time (both in ms).
3971 """
3972 if msTimeout == 0:
3973 return 0xFFFFFFFE; # Wait forever.
3974 msElapsed = base.timestampMilli() - msStart;
3975 if msElapsed > msTimeout:
3976 return 0; # No time left.
3977 return msTimeout - msElapsed;
3978
3979 def testGuestCtrlManual(self, oSession, oTxsSession, oTestVm): # pylint: disable=too-many-locals,too-many-statements,unused-argument,unused-variable
3980 """
3981 For manually testing certain bits.
3982 """
3983
3984 reporter.log('Manual testing ...');
3985 fRc = True;
3986
3987 sUser = 'Administrator';
3988 sPassword = 'password';
3989
3990 oGuest = oSession.o.console.guest;
3991 oGuestSession = oGuest.createSession(sUser,
3992 sPassword,
3993 "", "Manual Test");
3994
3995 aWaitFor = [ vboxcon.GuestSessionWaitForFlag_Start ];
3996 _ = oGuestSession.waitForArray(aWaitFor, 30 * 1000);
3997
3998 sCmd = SubTstDrvAddGuestCtrl.getGuestSystemShell(oTestVm);
3999 asArgs = [ sCmd, '/C', 'dir', '/S', 'c:\\windows' ];
4000 aEnv = [];
4001 fFlags = [];
4002
4003 for _ in xrange(100):
4004 oProc = oGuestSession.processCreate(sCmd, asArgs if self.fpApiVer >= 5.0 else asArgs[1:],
4005 aEnv, fFlags, 30 * 1000);
4006
4007 aWaitFor = [ vboxcon.ProcessWaitForFlag_Terminate ];
4008 _ = oProc.waitForArray(aWaitFor, 30 * 1000);
4009
4010 oGuestSession.close();
4011 oGuestSession = None;
4012
4013 time.sleep(5);
4014
4015 oSession.o.console.PowerDown();
4016
4017 return (fRc, oTxsSession);
4018
4019if __name__ == '__main__':
4020 sys.exit(tdAddGuestCtrl().main(sys.argv));
Note: See TracBrowser for help on using the repository browser.

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