VirtualBox

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

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

tdAddGuestCtrl.py: More cleanups. bugref:9151 bugref:9320

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