VirtualBox

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

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

ValKit: New pylint version - cleanup in progress.

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