VirtualBox

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

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

ValKit: Refactored sub-test driver initialization so it can have both a shortish name for --disable-sub-driver (new) and a test name for reporter.testStart. Working on extending tdGuestOsUnattendedInst1.py to do GA testings. bugref:9151

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