VirtualBox

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

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

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