VirtualBox

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

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

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