VirtualBox

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

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

Guest Control/Validation Kit: Pylint.

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