def processCheckPidAndName(uPid, sName): """ The Windows version of base.processCheckPidAndName """ fRc = processExists(uPid); if fRc is True: try: from win32com.client import GetObject; # pylint: disable=F0401 oWmi = GetObject('winmgmts:'); aoProcesses = oWmi.InstancesOf('Win32_Process'); for oProcess in aoProcesses: if long(oProcess.Properties_("ProcessId").Value) == uPid: sCurName = oProcess.Properties_("Name").Value; reporter.log2('uPid=%s sName=%s sCurName=%s' % (uPid, sName, sCurName)); sName = sName.lower(); sCurName = sCurName.lower(); if os.path.basename(sName) == sName: sCurName = os.path.basename(sCurName); if sCurName == sName \ or sCurName + '.exe' == sName \ or sCurName == sName + '.exe': fRc = True; break; except: reporter.logXcpt('uPid=%s sName=%s' % (uPid, sName)); return fRc;
def resizeMedium(self, oMedium, cbNewSize): if oMedium.deviceType is not vboxcon.DeviceType_HardDisk: return False; if oMedium.type is not vboxcon.MediumType_Normal: return False; #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself oMediumFormat = oMedium.mediumFormat; if oMediumFormat.id != 'VDI': return False; cbCurrSize = oMedium.logicalSize; # currently reduce is not supported if cbNewSize < cbCurrSize: return False; try: oProgressCom = oMedium.resize(cbNewSize); oProgress = vboxwrappers.ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv, 'Resize medium %s' % (oMedium.name)); oProgress.wait(cMsTimeout = 60 * 1000); oProgress.logResult(); except: reporter.logXcpt('IMedium::resize failed on %s' % (oMedium.name)); return False; return True;
def processCheckPidAndName(uPid, sName): """ The Windows version of base.processCheckPidAndName """ fRc = processExists(uPid) if fRc is True: try: from win32com.client import GetObject # pylint: disable=F0401 oWmi = GetObject("winmgmts:") aoProcesses = oWmi.InstancesOf("Win32_Process") for oProcess in aoProcesses: if long(oProcess.Properties_("ProcessId").Value) == uPid: sCurName = oProcess.Properties_("Name").Value reporter.log2("uPid=%s sName=%s sCurName=%s" % (uPid, sName, sCurName)) sName = sName.lower() sCurName = sCurName.lower() if os.path.basename(sName) == sName: sCurName = os.path.basename(sCurName) if sCurName == sName or sCurName + ".exe" == sName or sCurName == sName + ".exe": fRc = True break except: reporter.logXcpt("uPid=%s sName=%s" % (uPid, sName)) return fRc
def resizeMedium(self, oMedium, cbNewSize): if oMedium.deviceType is not vboxcon.DeviceType_HardDisk: return False if oMedium.type is not vboxcon.MediumType_Normal: return False #currently only VDI can be resizable. Medium variant is not checked, because testcase creates disks itself oMediumFormat = oMedium.mediumFormat if oMediumFormat.id != 'VDI': return False cbCurrSize = oMedium.logicalSize # currently reduce is not supported if cbNewSize < cbCurrSize: return False try: oProgressCom = oMedium.resize(cbNewSize) except: reporter.logXcpt('IMedium::resize failed on %s' % (oMedium.name)) return False oProgress = vboxwrappers.ProgressWrapper( oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv, 'Resize medium %s' % (oMedium.name)) oProgress.wait(cMsTimeout=15 * 60 * 1000) # 15 min oProgress.logResult() return True
def processCheckPidAndName(uPid, sName): """ The Windows version of base.processCheckPidAndName """ fRc = processExists(uPid) if fRc is True: try: from win32com.client import GetObject # pylint: disable=F0401 oWmi = GetObject('winmgmts:') aoProcesses = oWmi.InstancesOf('Win32_Process') for oProcess in aoProcesses: if long(oProcess.Properties_("ProcessId").Value) == uPid: sCurName = oProcess.Properties_("Name").Value reporter.log2('uPid=%s sName=%s sCurName=%s' % (uPid, sName, sCurName)) sName = sName.lower() sCurName = sCurName.lower() if os.path.basename(sName) == sName: sCurName = os.path.basename(sCurName) if sCurName == sName \ or sCurName + '.exe' == sName \ or sCurName == sName + '.exe': fRc = True break except: reporter.logXcpt('uPid=%s sName=%s' % (uPid, sName)) return fRc
def logMemoryStats(): """ Logs windows memory stats. """ class MemoryStatusEx(ctypes.Structure): """ MEMORYSTATUSEX """ kaFields = [ ( 'dwLength', ctypes.c_ulong ), ( 'dwMemoryLoad', ctypes.c_ulong ), ( 'ullTotalPhys', ctypes.c_ulonglong ), ( 'ullAvailPhys', ctypes.c_ulonglong ), ( 'ullTotalPageFile', ctypes.c_ulonglong ), ( 'ullAvailPageFile', ctypes.c_ulonglong ), ( 'ullTotalVirtual', ctypes.c_ulonglong ), ( 'ullAvailVirtual', ctypes.c_ulonglong ), ( 'ullAvailExtendedVirtual', ctypes.c_ulonglong ), ]; _fields_ = kaFields; # pylint: disable=invalid-name def __init__(self): super(MemoryStatusEx, self).__init__(); self.dwLength = ctypes.sizeof(self); try: oStats = MemoryStatusEx(); ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(oStats)); except: reporter.logXcpt(); return False; reporter.log('Memory statistics:'); for sField, _ in MemoryStatusEx.kaFields: reporter.log(' %32s: %s' % (sField, getattr(oStats, sField))); return True;
def logMemoryStats(): """ Logs windows memory stats. """ class MemoryStatusEx(ctypes.Structure): """ MEMORYSTATUSEX """ kaFields = [ ('dwLength', ctypes.c_ulong), ('dwMemoryLoad', ctypes.c_ulong), ('ullTotalPhys', ctypes.c_ulonglong), ('ullAvailPhys', ctypes.c_ulonglong), ('ullTotalPageFile', ctypes.c_ulonglong), ('ullAvailPageFile', ctypes.c_ulonglong), ('ullTotalVirtual', ctypes.c_ulonglong), ('ullAvailVirtual', ctypes.c_ulonglong), ('ullAvailExtendedVirtual', ctypes.c_ulonglong), ] _fields_ = kaFields # pylint: disable=invalid-name def __init__(self): super(MemoryStatusEx, self).__init__() self.dwLength = ctypes.sizeof(self) try: oStats = MemoryStatusEx() ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(oStats)) except: reporter.logXcpt() return False reporter.log('Memory statistics:') for sField, _ in MemoryStatusEx.kaFields: reporter.log(' %32s: %s' % (sField, getattr(oStats, sField))) return True
def isHostCpuAffectedByUbuntuNewAmdBug(self, oTestDrv): """ Checks if the host OS is affected by older ubuntu installers being very picky about which families of AMD CPUs it would run on. The installer checks for family 15, later 16, later 20, and in 11.10 they remove the family check for AMD CPUs. """ if not oTestDrv.isHostCpuAmd(): return False; try: (uMaxExt, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000000, 0); (uFamilyModel, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000001, 0); except: reporter.logXcpt(); return False; if uMaxExt < 0x80000001 or uMaxExt > 0x8000ffff: return False; uFamily = (uFamilyModel >> 8) & 0xf if uFamily == 0xf: uFamily = ((uFamilyModel >> 20) & 0x7f) + 0xf; ## @todo Break this down into which old ubuntu release supports exactly ## which AMD family, if we care. if uFamily <= 15: return False; reporter.log('Skipping "%s" because host CPU is a family %u AMD, which may cause trouble for the guest OS installer.' % (self.sVmName, uFamily,)); return True;
def isHostCpuAffectedByUbuntuNewAmdBug(self, oTestDrv): """ Checks if the host OS is affected by older ubuntu installers being very picky about which families of AMD CPUs it would run on. The installer checks for family 15, later 16, later 20, and in 11.10 they remove the family check for AMD CPUs. """ if not oTestDrv.isHostCpuAmd(): return False try: (uMaxExt, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000000, 0) (uFamilyModel, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000001, 0) except: reporter.logXcpt() return False if uMaxExt < 0x80000001 or uMaxExt > 0x8000ffff: return False uFamily = (uFamilyModel >> 8) & 0xf if uFamily == 0xf: uFamily = ((uFamilyModel >> 20) & 0x7f) + 0xf ## @todo Break this down into which old ubuntu release supports exactly ## which AMD family, if we care. if uFamily <= 15: return False reporter.log( 'Skipping "%s" because host CPU is a family %u AMD, which may cause trouble for the guest OS installer.' % ( self.sVmName, uFamily, )) return True
def _installVBox(self): """ Download / copy the build files into the scratch area and install them. """ reporter.testStart('Installing VirtualBox'); reporter.log('CWD=%s' % (os.getcwd(),)); # curious # # Download the build files. # for i in range(len(self._asBuildUrls)): if webutils.downloadFile(self._asBuildUrls[i], self._asBuildFiles[i], self.sBuildPath, reporter.log, reporter.log) is not True: reporter.testDone(fSkipped = True); return None; # Failed to get binaries, probably deleted. Skip the test run. # # Unpack anything we know what is and append it to the build files # list. This allows us to use VBoxAll*.tar.gz files. # for sFile in list(self._asBuildFiles): if self._maybeUnpackArchive(sFile, fNonFatal = True) is not True: reporter.testDone(fSkipped = True); return None; # Failed to unpack. Probably local error, like busy # DLLs on windows, no reason for failing the build. # # Go to system specific installation code. # sHost = utils.getHostOs() if sHost == 'darwin': fRc = self._installVBoxOnDarwin(); elif sHost == 'linux': fRc = self._installVBoxOnLinux(); elif sHost == 'solaris': fRc = self._installVBoxOnSolaris(); elif sHost == 'win': fRc = self._installVBoxOnWindows(); else: reporter.error('Unsupported host "%s".' % (sHost,)); if fRc is False: reporter.testFailure('Installation error.'); elif fRc is not True: reporter.log('Seems installation was skipped. Old version lurking behind? Not the fault of this build/test run!'); # # Install the extension pack. # if fRc is True and self._fAutoInstallPuelExtPack: fRc = self._installExtPack(); if fRc is False: reporter.testFailure('Extension pack installation error.'); # Some debugging... try: cMbFreeSpace = utils.getDiskUsage(self.sScratchPath); reporter.log('Disk usage after VBox install: %d MB available at %s' % (cMbFreeSpace, self.sScratchPath,)); except: reporter.logXcpt('Unable to get disk free space. Ignored. Continuing.'); reporter.testDone(fRc is None); return fRc;
def postThreadMesssageClose(uTid): """ Posts a WM_CLOSE message to the specified thread.""" fRc = False try: win32api.PostThreadMessage(uTid, win32con.WM_CLOSE, 0, 0) fRc = True except: reporter.logXcpt("uTid=%s" % (uTid,)) return fRc
def postThreadMesssageClose(uTid): """ Posts a WM_CLOSE message to the specified thread.""" fRc = False; try: win32api.PostThreadMessage(uTid, win32con.WM_CLOSE, 0, 0); # pylint: disable=no-member fRc = True; except: reporter.logXcpt('uTid=%s' % (uTid,)); return fRc;
def postThreadMesssageQuit(uTid): """ Posts a WM_QUIT message to the specified thread.""" fRc = False; try: win32api.PostThreadMessage(uTid, win32con.WM_QUIT, 0x40010004, 0); # DBG_TERMINATE_PROCESS # pylint: disable=no-member fRc = True; except: reporter.logXcpt('uTid=%s' % (uTid,)); return fRc;
def postThreadMesssageClose(uTid): """ Posts a WM_CLOSE message to the specified thread.""" fRc = False try: win32api.PostThreadMessage(uTid, win32con.WM_CLOSE, 0, 0) fRc = True except: reporter.logXcpt('uTid=%s' % (uTid, )) return fRc
def processPollByHandle(hProcess): """ Polls the process handle to see if it has finished (True) or not (False). """ try: dwWait = win32event.WaitForSingleObject(hProcess, 0); # pylint: disable=no-member except: reporter.logXcpt('hProcess=%s %#x' % (hProcess, hProcess,)); return True; return dwWait != win32con.WAIT_TIMEOUT; #0x102; #
def processTerminateByHandle(hProcess): """ Terminates the process. """ try: win32api.TerminateProcess(hProcess, 0x40010004); # DBG_TERMINATE_PROCESS # pylint: disable=no-member except: reporter.logXcpt('hProcess=%s %#x' % (hProcess, hProcess,)); return False; return True;
def postThreadMesssageQuit(uTid): """ Posts a WM_QUIT message to the specified thread.""" fRc = False try: win32api.PostThreadMessage(uTid, win32con.WM_QUIT, 0x40010004, 0) # DBG_TERMINATE_PROCESS fRc = True except: reporter.logXcpt('uTid=%s' % (uTid, )) return fRc
def processPollByHandle(hProcess): """ Polls the process handle to see if it has finished (True) or not (False). """ try: dwWait = win32event.WaitForSingleObject(hProcess, 0) except: reporter.logXcpt("hProcess=%s %#x" % (hProcess, hProcess)) return True return dwWait != win32con.WAIT_TIMEOUT
def postThreadMesssageQuit(uTid): """ Posts a WM_QUIT message to the specified thread.""" fRc = False try: win32api.PostThreadMessage(uTid, win32con.WM_QUIT, 0x40010004, 0) # DBG_TERMINATE_PROCESS fRc = True except: reporter.logXcpt("uTid=%s" % (uTid,)) return fRc
def processExists(uPid): """ The Windows version of base.processExists """ fRc = False; try: hProcess = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, False, uPid); except: reporter.logXcpt('uPid=%s' % (uPid,)); else: win32api.CloseHandle(hProcess) fRc = True; return fRc;
def testWrite(self, oSession, oTxsSession, oTestVm, sMode): """ Does a simple write test verifying the output. """ _ = oSession reporter.testStart('Write') tupCmdLine = ( 'SerialTest', '--tests', 'write', '--txbytes', '1048576', ) if self.fVerboseTest: tupCmdLine += ('--verbose') if oTestVm.isWindows(): tupCmdLine += ( '--device', r'\\.\COM1', ) elif oTestVm.isLinux(): tupCmdLine += ( '--device', r'/dev/ttyS0', ) fRc = self.txsRunTest(oTxsSession, 'SerialTest', 3600 * 1000, \ '${CDROM}/${OS/ARCH}/SerialTest${EXESUFF}', tupCmdLine) if not fRc: reporter.testFailure('Running serial test utility failed') elif sMode == 'RawFile': # Open serial port and verify cLast = 0 try: oFile = open(self.sLocation, 'rb') sFmt = '=I' cBytes = 4 for i in xrange(1048576 / 4): _ = i sData = oFile.read(cBytes) tupUnpacked = struct.unpack(sFmt, sData) cLast = cLast + 1 if tupUnpacked[0] != cLast: reporter.testFailure( 'Corruption detected, expected counter value %s, got %s' % (cLast + 1, tupUnpacked[0])) break oFile.close() except: reporter.logXcpt() reporter.testFailure('Verifying the written data failed') reporter.testDone() return fRc
def processTerminateByHandle(hProcess): """ Terminates the process. """ try: win32api.TerminateProcess(hProcess, 0x40010004) # DBG_TERMINATE_PROCESS except: reporter.logXcpt("hProcess=%s %#x" % (hProcess, hProcess)) return False return True
def _uninstallVBoxOnWindows(self): """ Uninstalls VBox on Windows, all installations we find to be on the safe side... """ import win32com.client; # pylint: disable=F0401 win32com.client.gencache.EnsureModule('{000C1092-0000-0000-C000-000000000046}', 1033, 1, 0); oInstaller = win32com.client.Dispatch('WindowsInstaller.Installer', resultCLSID = '{000C1090-0000-0000-C000-000000000046}') # Search installed products for VirtualBox. asProdCodes = []; for sProdCode in oInstaller.Products: try: sProdName = oInstaller.ProductInfo(sProdCode, "ProductName"); except: reporter.logXcpt(); continue; #reporter.log('Info: %s=%s' % (sProdCode, sProdName)); if sProdName.startswith('Oracle VM VirtualBox') \ or sProdName.startswith('Sun VirtualBox'): asProdCodes.append([sProdCode, sProdName]); # Before we start uninstalling anything, just ruthlessly kill any # msiexec process we might find hanging around. cKilled = 0; for oProcess in utils.processListAll(): sBase = oProcess.getBaseImageNameNoExeSuff(); if sBase is not None and sBase.lower() in [ 'msiexec', ]: reporter.log('Killing MSI process: %s (%s)' % (oProcess.iPid, sBase)); utils.processKill(oProcess.iPid); cKilled += 1; if cKilled > 0: time.sleep(16); # fudge. # Do the uninstalling. fRc = True; sLogFile = os.path.join(self.sScratchPath, 'VBoxUninstallLog.txt'); for sProdCode, sProdName in asProdCodes: reporter.log('Uninstalling %s (%s)...' % (sProdName, sProdCode)); fRc2, iRc = self._sudoExecuteSync(['msiexec', '/uninstall', sProdCode, '/quiet', '/passive', '/norestart', '/L*v', '%s' % (sLogFile), ]); if fRc2 is False: if iRc == 3010: # ERROR_SUCCESS_REBOOT_REQUIRED reporter.log('Note: Uninstaller required a reboot to complete uninstallation'); # Optional, don't fail. else: fRc = False; reporter.addLogFile(sLogFile, 'log/uninstaller', "Verbose MSI uninstallation log file"); self._waitForTestManagerConnectivity(30); if fRc is False and os.path.isfile(sLogFile): reporter.addLogFile(sLogFile, 'log/uninstaller'); return fRc;
def test2Teleport(self, oVmSrc, oSessionSrc, oVmDst): """ Attempts a teleportation. Returns the input parameters for the next test2Teleport call (source and destiation are switched around). The input session is closed and removed from the task list, while the return session is in the list. """ # Enable the teleporter of the VM. oSession = self.openSession(oVmDst) fRc = oSession is not None if fRc: fRc = oSession.enableTeleporter() fRc = fRc and oSession.saveSettings() fRc = oSession.close() and fRc and True # pychecker hack. if fRc: # Start the destination VM. oSessionDst, oProgressDst = self.startVmEx( oVmDst, fWait=False) if oSessionDst is not None: if oProgressDst.waitForOperation(iOperation=-3) == 0: # Do the teleportation. try: uDstPort = oVmDst.teleporterPort except: reporter.logXcpt() uDstPort = 6502 oProgressSrc = oSessionSrc.teleport( 'localhost', uDstPort, 'password', 1024) if oProgressSrc is not None: oProgressSrc.wait() if oProgressSrc.isSuccess(): oProgressDst.wait() if oProgressSrc.isSuccess() and oProgressDst.isSuccess( ): # Terminate the source VM. self.terminateVmBySession(oSessionSrc, oProgressSrc) # Return with the source and destination swapped. self.addTask(oSessionDst) return oVmDst, oSessionDst, oVmSrc # Failure / bail out. oProgressSrc.logResult() oProgressDst.logResult() self.terminateVmBySession(oSessionDst, oProgressDst) return oVmSrc, oSessionSrc, oVmDst
def processExists(uPid): """ The Windows version of base.processExists """ # pylint: disable=no-member fRc = False try: hProcess = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, False, uPid) except: reporter.logXcpt('uPid=%s' % (uPid, )) else: win32api.CloseHandle(hProcess) fRc = True return fRc
def test2Teleport(self, oVmSrc, oSessionSrc, oVmDst): """ Attempts a teleportation. Returns the input parameters for the next test2Teleport call (source and destiation are switched around). The input session is closed and removed from the task list, while the return session is in the list. """ # Enable the teleporter of the VM. oSession = self.openSession(oVmDst) fRc = oSession is not None if fRc: fRc = oSession.enableTeleporter() fRc = fRc and oSession.saveSettings() fRc = oSession.close() and fRc and True # pychecker hack. if fRc: # Start the destination VM. oSessionDst, oProgressDst = self.startVmEx(oVmDst, fWait=False) if oSessionDst is not None: if oProgressDst.waitForOperation(iOperation=-3) == 0: # Do the teleportation. try: uDstPort = oVmDst.teleporterPort except: reporter.logXcpt() uDstPort = 6502 oProgressSrc = oSessionSrc.teleport( 'localhost', uDstPort, 'password', 1024) if oProgressSrc is not None: oProgressSrc.wait() if oProgressSrc.isSuccess(): oProgressDst.wait() if oProgressSrc.isSuccess() and oProgressDst.isSuccess( ): # Terminate the source VM. self.terminateVmBySession(oSessionSrc, oProgressSrc) # Return with the source and destination swapped. self.addTask(oSessionDst) return oVmDst, oSessionDst, oVmSrc # Failure / bail out. oProgressSrc.logResult() oProgressDst.logResult() self.terminateVmBySession(oSessionDst, oProgressDst) return oVmSrc, oSessionSrc, oVmDst
def processTerminateByHandle(hProcess): """ Terminates the process. """ try: win32api.TerminateProcess(hProcess, 0x40010004) # DBG_TERMINATE_PROCESS except: reporter.logXcpt('hProcess=%s %#x' % ( hProcess, hProcess, )) return False return True
def processTerminate(uPid): """ The Windows version of base.processTerminate """ fRc = False; try: hProcess = win32api.OpenProcess(win32con.PROCESS_TERMINATE, False, uPid); except: reporter.logXcpt('uPid=%s' % (uPid,)); else: try: win32process.TerminateProcess(hProcess, 0x40010004); # DBG_TERMINATE_PROCESS fRc = True; except: reporter.logXcpt('uPid=%s' % (uPid,)); win32api.CloseHandle(hProcess) return fRc;
def _darwinMountDmg(self, sDmg): """ Mount the DMG at the default mount point. """ self._darwinUnmountDmg(fIgnoreError = True) sMountPath = self._darwinDmgPath(); if not os.path.exists(sMountPath): try: os.mkdir(sMountPath, 0755); except: reporter.logXcpt(); return False; return self._executeSync(['hdiutil', 'attach', '-readonly', '-mount', 'required', '-mountpoint', sMountPath, sDmg, ]);
def processTerminateByHandle(hProcess): """ Terminates the process. """ try: win32api.TerminateProcess( hProcess, # pylint: disable=no-member,c-extension-no-member 0x40010004) # DBG_TERMINATE_PROCESS except: reporter.logXcpt('hProcess=%s %#x' % ( hProcess, hProcess.handle, )) return False return True
def processInterrupt(uPid): """ The Windows version of base.processInterrupt Note! This doesn't work terribly well with a lot of processes. """ try: win32console.GenerateConsoleCtrlEvent(win32con.CTRL_BREAK_EVENT, uPid) #GenerateConsoleCtrlEvent = ctypes.windll.kernel32.GenerateConsoleCtrlEvent #rc = GenerateConsoleCtrlEvent(1, uPid); #reporter.log('GenerateConsoleCtrlEvent -> %s' % (rc,)); fRc = True except: reporter.logXcpt('uPid=%s' % (uPid, )) fRc = False return fRc
def processInterrupt(uPid): """ The Windows version of base.processInterrupt Note! This doesn't work terribly well with a lot of processes. """ try: win32console.GenerateConsoleCtrlEvent(win32con.CTRL_BREAK_EVENT, uPid); #GenerateConsoleCtrlEvent = ctypes.windll.kernel32.GenerateConsoleCtrlEvent #rc = GenerateConsoleCtrlEvent(1, uPid); #reporter.log('GenerateConsoleCtrlEvent -> %s' % (rc,)); fRc = True; except: reporter.logXcpt('uPid=%s' % (uPid,)); fRc = False; return fRc;
def _figureVersion(self): """ Tries to figure which VBox version this is, setting self.aiVBoxVer. """ try: sVer = utils.processOutputChecked(['VBoxManage', '--version']) sVer = sVer.strip() sVer = re.sub(r'_BETA.*r', '.', sVer) sVer = re.sub(r'_ALPHA.*r', '.', sVer) sVer = re.sub(r'_RC.*r', '.', sVer) sVer = sVer.replace('r', '.') self.aiVBoxVer = [int(sComp) for sComp in sVer.split('.')] reporter.log('VBox version: %s' % (self.aiVBoxVer, )) except: reporter.logXcpt() return False return True
def processTerminate(uPid): """ The Windows version of base.processTerminate """ # pylint: disable=no-member fRc = False; try: hProcess = win32api.OpenProcess(win32con.PROCESS_TERMINATE, # pylint: disable=no-member,c-extension-no-member False, uPid); except: reporter.logXcpt('uPid=%s' % (uPid,)); else: try: win32process.TerminateProcess(hProcess, # pylint: disable=no-member,c-extension-no-member 0x40010004); # DBG_TERMINATE_PROCESS fRc = True; except: reporter.logXcpt('uPid=%s' % (uPid,)); hProcess.Close(); #win32api.CloseHandle(hProcess) return fRc;
def processTerminate(uPid): """ The Windows version of base.processTerminate """ # pylint: disable=no-member fRc = False try: hProcess = win32api.OpenProcess(win32con.PROCESS_TERMINATE, False, uPid) except: reporter.logXcpt('uPid=%s' % (uPid, )) else: try: win32process.TerminateProcess(hProcess, 0x40010004) # DBG_TERMINATE_PROCESS fRc = True except: reporter.logXcpt('uPid=%s' % (uPid, )) win32api.CloseHandle(hProcess) return fRc
def _figureVersion(self): """ Tries to figure which VBox version this is, setting self.aiVBoxVer. """ try: sVer = utils.processOutputChecked(["VBoxManage", "--version"]) sVer = sVer.strip() sVer = re.sub(r"_BETA.*r", ".", sVer) sVer = re.sub(r"_ALPHA.*r", ".", sVer) sVer = re.sub(r"_RC.*r", ".", sVer) sVer = sVer.replace("r", ".") self.aiVBoxVer = [int(sComp) for sComp in sVer.split(".")] reporter.log("VBox version: %s" % (self.aiVBoxVer,)) except: reporter.logXcpt() return False return True
def _figureVersion(self): """ Tries to figure which VBox version this is, setting self.aiVBoxVer. """ try: sVer = utils.processOutputChecked(['VBoxManage', '--version']) sVer = sVer.strip(); sVer = re.sub(r'_BETA.*r', '.', sVer); sVer = re.sub(r'_ALPHA.*r', '.', sVer); sVer = re.sub(r'_RC.*r', '.', sVer); sVer = sVer.replace('r', '.'); self.aiVBoxVer = [int(sComp) for sComp in sVer.split('.')]; reporter.log('VBox version: %s' % (self.aiVBoxVer,)); except: reporter.logXcpt(); return False; return True;
def testWrite(self, oSession, oTxsSession, oTestVm, sMode): """ Does a simple write test verifying the output. """ _ = oSession; reporter.testStart('Write'); tupCmdLine = ('SerialTest', '--tests', 'write', '--txbytes', '1048576'); if self.fVerboseTest: tupCmdLine += ('--verbose',); if oTestVm.isWindows(): tupCmdLine += ('--device', r'\\.\COM1',); elif oTestVm.isLinux(): tupCmdLine += ('--device', r'/dev/ttyS0',); fRc = self.txsRunTest(oTxsSession, 'SerialTest', 3600 * 1000, \ '${CDROM}/${OS/ARCH}/SerialTest${EXESUFF}', tupCmdLine); if not fRc: reporter.testFailure('Running serial test utility failed'); elif sMode == 'RawFile': # Open serial port and verify cLast = 0; try: oFile = open(self.sLocation, 'rb'); sFmt = '=I'; cBytes = 4; for i in xrange(1048576 // 4): _ = i; sData = oFile.read(cBytes); tupUnpacked = struct.unpack(sFmt, sData); cLast = cLast + 1; if tupUnpacked[0] != cLast: reporter.testFailure('Corruption detected, expected counter value %s, got %s' % (cLast + 1, tupUnpacked[0])); break; oFile.close(); except: reporter.logXcpt(); reporter.testFailure('Verifying the written data failed'); reporter.testDone(); return fRc;
def deleteVM(self, oVM): try: oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone) except: reporter.logXcpt() if self.fpApiVer >= 4.0: try: if self.fpApiVer >= 4.3: oProgressCom = oVM.deleteConfig([]) else: oProgressCom = oVM.delete(None) except: reporter.logXcpt() else: oProgress = vboxwrappers.ProgressWrapper( oProgressCom, self.oVBoxMgr, self.oVBox.oTstDrv, 'Delete VM %s' % (oVM.name)) oProgress.wait(cMsTimeout=15 * 60 * 1000) # 15 min oProgress.logResult() else: try: oVM.deleteSettings() except: reporter.logXcpt() return None
def processCreate(sName, asArgs): """ Returns a (pid, handle, tid) tuple on success. (-1, None) on failure (logged). """ # Construct a command line. sCmdLine = '' for sArg in asArgs: if sCmdLine == '': sCmdLine += '"' else: sCmdLine += ' "' sCmdLine += sArg sCmdLine += '"' # Try start the process. dwCreationFlags = win32con.CREATE_NEW_PROCESS_GROUP oStartupInfo = win32process.STARTUPINFO() try: (hProcess, hThread, uPid, uTid) = win32process.CreateProcess( sName, sCmdLine, # CommandLine None, # ProcessAttributes None, # ThreadAttibutes 1, # fInheritHandles dwCreationFlags, None, # Environment None, # CurrentDirectory. oStartupInfo) except: reporter.logXcpt('sName="%s" sCmdLine="%s"' % (sName, sCmdLine)) return (-1, None, -1) # Dispense with the thread handle. try: win32api.CloseHandle(hThread) except: reporter.logXcpt() # Try get full access to the process. try: hProcessFullAccess = win32api.DuplicateHandle( \ win32api.GetCurrentProcess(), \ hProcess, \ win32api.GetCurrentProcess(), \ win32con.PROCESS_TERMINATE \ | win32con.PROCESS_QUERY_INFORMATION \ | win32con.SYNCHRONIZE \ | win32con.DELETE, \ False, \ 0) win32api.CloseHandle(hProcess) hProcess = hProcessFullAccess except: reporter.logXcpt() reporter.log2('processCreate -> %#x, hProcess=%#x' % ( uPid, hProcess, )) return (uPid, hProcess, uTid)
def checkProcessHeap(): """ Calls HeapValidate(GetProcessHeap(), 0, NULL); """ # Get the process heap. try: hHeap = ctypes.windll.kernel32.GetProcessHeap() except: reporter.logXcpt() return False # Check it. try: fIsOkay = ctypes.windll.kernel32.HeapValidate(hHeap, 0, None) except: reporter.logXcpt() return False if fIsOkay == 0: reporter.log('HeapValidate failed!') # Try trigger a dump using c:\utils\procdump64.exe. from common import utils iPid = os.getpid() asArgs = [ 'e:\\utils\\procdump64.exe', '-ma', '%s' % (iPid, ), 'c:\\CrashDumps\\python.exe-%u-heap.dmp' % (iPid, ) ] if utils.getHostArch() != 'amd64': asArgs[0] = 'c:\\utils\\procdump.exe' reporter.log('Trying to dump this process using: %s' % (asArgs, )) utils.processCall(asArgs) # Generate a crash exception. ctypes.windll.msvcrt.strcpy(None, None, 1024) return True
def executeHst(self, sWhat, asArgs, asEnv=None, fAsAdmin=False): """ Runs a binary (image) with optional admin (root) rights on the host and waits until it terminates. Windows currently is not supported yet running stuff as Administrator. Returns success status (exit code is 0). """ reporter.log('Executing \"%s\" on host (as admin = %s)' % (sWhat, fAsAdmin)) try: sys.stdout.flush() except: pass try: sys.stderr.flush() except: pass # Initialize thread rc. self.iThreadHstProcRc = -42 try: oThread = threading.Thread(target=self.executeHstThread, args=[sWhat, asArgs, asEnv, fAsAdmin]) oThread.start() while oThread.join(0.1): if not oThread.is_alive(): break self.processEvents(0) reporter.log2('Thread returned exit code for "%s": %d' % (sWhat, self.iThreadHstProcRc)) except: reporter.logXcpt('Starting thread for "%s" failed' % (sWhat, )) return self.iThreadHstProcRc == 0
def processCreate(sName, asArgs): """ Returns a (pid, handle, tid) tuple on success. (-1, None) on failure (logged). """ # Construct a command line. sCmdLine = ''; for sArg in asArgs: if sCmdLine == '': sCmdLine += '"'; else: sCmdLine += ' "'; sCmdLine += sArg; sCmdLine += '"'; # Try start the process. # pylint: disable=no-member dwCreationFlags = win32con.CREATE_NEW_PROCESS_GROUP; oStartupInfo = win32process.STARTUPINFO(); try: (hProcess, hThread, uPid, uTid) = win32process.CreateProcess(sName, sCmdLine, # CommandLine None, # ProcessAttributes None, # ThreadAttibutes 1, # fInheritHandles dwCreationFlags, None, # Environment None, # CurrentDirectory. oStartupInfo); except: reporter.logXcpt('sName="%s" sCmdLine="%s"' % (sName, sCmdLine)); return (-1, None, -1); # Dispense with the thread handle. try: win32api.CloseHandle(hThread); except: reporter.logXcpt(); # Try get full access to the process. try: hProcessFullAccess = win32api.DuplicateHandle( win32api.GetCurrentProcess(), hProcess, win32api.GetCurrentProcess(), win32con.PROCESS_TERMINATE | win32con.PROCESS_QUERY_INFORMATION | win32con.SYNCHRONIZE | win32con.DELETE, False, 0); win32api.CloseHandle(hProcess); hProcess = hProcessFullAccess; except: reporter.logXcpt(); reporter.log2('processCreate -> %#x, hProcess=%#x' % (uPid, hProcess,)); return (uPid, hProcess, uTid);
def checkProcessHeap(): """ Calls HeapValidate(GetProcessHeap(), 0, NULL); """ # Get the process heap. try: hHeap = ctypes.windll.kernel32.GetProcessHeap(); except: reporter.logXcpt(); return False; # Check it. try: fIsOkay = ctypes.windll.kernel32.HeapValidate(hHeap, 0, None); except: reporter.logXcpt(); return False; if fIsOkay == 0: reporter.log('HeapValidate failed!'); # Try trigger a dump using c:\utils\procdump64.exe. from common import utils; iPid = os.getpid(); asArgs = [ 'e:\\utils\\procdump64.exe', '-ma', '%s' % (iPid,), 'c:\\CrashDumps\\python.exe-%u-heap.dmp' % (iPid,)]; if utils.getHostArch() != 'amd64': asArgs[0] = 'c:\\utils\\procdump.exe' reporter.log('Trying to dump this process using: %s' % (asArgs,)); utils.processCall(asArgs); # Generate a crash exception. ctypes.windll.msvcrt.strcpy(None, None, 1024); return True;
def processExists(uPid): """ The Windows version of base.processExists """ # We try open the process for waiting since this is generally only forbidden in a very few cases. try: hProcess = win32api.OpenProcess(win32con.SYNCHRONIZE, False, uPid); # pylint: disable=no-member,c-extension-no-member except pywintypes.error as oXcpt: # pylint: disable=no-member if oXcpt.winerror == winerror.ERROR_INVALID_PARAMETER: return False; if oXcpt.winerror != winerror.ERROR_ACCESS_DENIED: reporter.logXcpt('uPid=%s oXcpt=%s' % (uPid, oXcpt)); return False; reporter.logXcpt('uPid=%s oXcpt=%s' % (uPid, oXcpt)); except Exception as oXcpt: reporter.logXcpt('uPid=%s' % (uPid,)); return False; else: hProcess.Close(); #win32api.CloseHandle(hProcess) return True;
def processExists(uPid): """ The Windows version of base.processExists """ # We try open the process for waiting since this is generally only forbidden in a very few cases. try: hProcess = win32api.OpenProcess(win32con.SYNCHRONIZE, False, uPid) # pylint: disable=no-member except pywintypes.error as oXcpt: # pylint: disable=no-member if oXcpt.winerror == winerror.ERROR_INVALID_PARAMETER: return False if oXcpt.winerror != winerror.ERROR_ACCESS_DENIED: reporter.logXcpt('uPid=%s oXcpt=%s' % (uPid, oXcpt)) return False reporter.logXcpt('uPid=%s oXcpt=%s' % (uPid, oXcpt)) except Exception as oXcpt: reporter.logXcpt('uPid=%s' % (uPid, )) return False else: hProcess.Close() #win32api.CloseHandle(hProcess) return True
def deleteVM(self, oVM): try: oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone); except: reporter.logXcpt(); if self.fpApiVer >= 4.0: try: if self.fpApiVer >= 4.3: oProgress = oVM.deleteConfig([]); else: oProgress = oVM.delete(None); self.waitOnProgress(oProgress); except: reporter.logXcpt(); else: try: oVM.deleteSettings(); except: reporter.logXcpt(); return None;
def deleteVM(self, oVM): try: oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone) except: reporter.logXcpt() if self.fpApiVer >= 4.0: try: if self.fpApiVer >= 4.3: oProgress = oVM.deleteConfig([]) else: oProgress = oVM.delete(None) self.waitOnProgress(oProgress) except: reporter.logXcpt() else: try: oVM.deleteSettings() except: reporter.logXcpt() return None
def _uninstallVBoxOnWindows(self, fIgnoreServices = False): """ Uninstalls VBox on Windows, all installations we find to be on the safe side... """ import win32com.client; # pylint: disable=F0401 win32com.client.gencache.EnsureModule('{000C1092-0000-0000-C000-000000000046}', 1033, 1, 0); oInstaller = win32com.client.Dispatch('WindowsInstaller.Installer', resultCLSID = '{000C1090-0000-0000-C000-000000000046}') # Search installed products for VirtualBox. asProdCodes = []; for sProdCode in oInstaller.Products: try: sProdName = oInstaller.ProductInfo(sProdCode, "ProductName"); except: reporter.logXcpt(); continue; #reporter.log('Info: %s=%s' % (sProdCode, sProdName)); if sProdName.startswith('Oracle VM VirtualBox') \ or sProdName.startswith('Sun VirtualBox'): asProdCodes.append([sProdCode, sProdName]); # Before we start uninstalling anything, just ruthlessly kill any cdb, # msiexec, drvinst and some rundll process we might find hanging around. if self._isProcessPresent('rundll32'): cTimes = 0; while cTimes < 3: cTimes += 1; cKilled = self._terminateProcessesByNameAndArgSubstr('rundll32', 'InstallSecurityPromptRunDllW', 'MSI driver installation'); if cKilled <= 0: break; time.sleep(10); # Give related drvinst process a chance to clean up after we killed the verification dialog. if self._isProcessPresent('drvinst'): time.sleep(15); # In the hope that it goes away. cTimes = 0; while cTimes < 4: cTimes += 1; cKilled = self._killProcessesByName('drvinst', 'MSI driver installation', True); if cKilled <= 0: break; time.sleep(10); # Give related MSI process a chance to clean up after we killed the driver installer. if self._isProcessPresent('msiexec'): cTimes = 0; while cTimes < 3: reporter.log('found running msiexec process, waiting a bit...'); time.sleep(20) # In the hope that it goes away. if not self._isProcessPresent('msiexec'): break; cTimes += 1; ## @todo this could also be the msiexec system service, try to detect this case! if cTimes >= 6: cKilled = self._killProcessesByName('msiexec', 'MSI driver installation'); if cKilled > 0: time.sleep(16); # fudge. # cdb.exe sometimes stays running (from utils.getProcessInfo), blocking # the scratch directory. No idea why. if self._isProcessPresent('cdb'): cTimes = 0; while cTimes < 3: cKilled = self._killProcessesByName('cdb', 'cdb.exe from getProcessInfo'); if cKilled <= 0: break; time.sleep(2); # fudge. # Do the uninstalling. fRc = True; sLogFile = os.path.join(self.sScratchPath, 'VBoxUninstallLog.txt'); for sProdCode, sProdName in asProdCodes: reporter.log('Uninstalling %s (%s)...' % (sProdName, sProdCode)); fRc2, iRc = self._sudoExecuteSync(['msiexec', '/uninstall', sProdCode, '/quiet', '/passive', '/norestart', '/L*v', '%s' % (sLogFile), ]); if fRc2 is False: if iRc == 3010: # ERROR_SUCCESS_REBOOT_REQUIRED reporter.log('Note: Uninstaller required a reboot to complete uninstallation'); reporter.addLogFile(sLogFile, 'log/uninstaller_reboot', \ "Verbose MSI uninstallation log file (reboot required)"); # Optional, don't fail. else: fRc = False; self._waitForTestManagerConnectivity(30); if fRc is False and os.path.isfile(sLogFile): reporter.addLogFile(sLogFile, 'log/uninstaller', "Verbose MSI uninstallation log file"); # Log driver service states (should ls \Driver\VBox* and \Device\VBox*). for sService in self.kasWindowsServices: fRc2, _ = self._sudoExecuteSync(['sc.exe', 'query', sService]); if fIgnoreServices is False and fRc2 is True: fRc = False return fRc;
def _uninstallVBoxOnWindows(self, fIgnoreServices=False): """ Uninstalls VBox on Windows, all installations we find to be on the safe side... """ import win32com.client # pylint: disable=F0401 win32com.client.gencache.EnsureModule( '{000C1092-0000-0000-C000-000000000046}', 1033, 1, 0) oInstaller = win32com.client.Dispatch( 'WindowsInstaller.Installer', resultCLSID='{000C1090-0000-0000-C000-000000000046}') # Search installed products for VirtualBox. asProdCodes = [] for sProdCode in oInstaller.Products: try: sProdName = oInstaller.ProductInfo(sProdCode, "ProductName") except: reporter.logXcpt() continue #reporter.log('Info: %s=%s' % (sProdCode, sProdName)); if sProdName.startswith('Oracle VM VirtualBox') \ or sProdName.startswith('Sun VirtualBox'): asProdCodes.append([sProdCode, sProdName]) # Before we start uninstalling anything, just ruthlessly kill any cdb, # msiexec, drvinst and some rundll process we might find hanging around. if self._isProcessPresent('rundll32'): cTimes = 0 while cTimes < 3: cTimes += 1 cKilled = self._terminateProcessesByNameAndArgSubstr( 'rundll32', 'InstallSecurityPromptRunDllW', 'MSI driver installation') if cKilled <= 0: break time.sleep(10) # Give related drvinst process a chance to clean up after we killed the verification dialog. if self._isProcessPresent('drvinst'): time.sleep(15) # In the hope that it goes away. cTimes = 0 while cTimes < 4: cTimes += 1 cKilled = self._killProcessesByName('drvinst', 'MSI driver installation', True) if cKilled <= 0: break time.sleep(10) # Give related MSI process a chance to clean up after we killed the driver installer. if self._isProcessPresent('msiexec'): cTimes = 0 while cTimes < 3: reporter.log('found running msiexec process, waiting a bit...') time.sleep(20) # In the hope that it goes away. if not self._isProcessPresent('msiexec'): break cTimes += 1 ## @todo this could also be the msiexec system service, try to detect this case! if cTimes >= 6: cKilled = self._killProcessesByName('msiexec', 'MSI driver installation') if cKilled > 0: time.sleep(16) # fudge. # cdb.exe sometimes stays running (from utils.getProcessInfo), blocking # the scratch directory. No idea why. if self._isProcessPresent('cdb'): cTimes = 0 while cTimes < 3: cKilled = self._killProcessesByName( 'cdb', 'cdb.exe from getProcessInfo') if cKilled <= 0: break time.sleep(2) # fudge. # Do the uninstalling. fRc = True sLogFile = os.path.join(self.sScratchPath, 'VBoxUninstallLog.txt') for sProdCode, sProdName in asProdCodes: reporter.log('Uninstalling %s (%s)...' % (sProdName, sProdCode)) fRc2, iRc = self._sudoExecuteSync([ 'msiexec', '/uninstall', sProdCode, '/quiet', '/passive', '/norestart', '/L*v', '%s' % (sLogFile), ]) if fRc2 is False: if iRc == 3010: # ERROR_SUCCESS_REBOOT_REQUIRED reporter.log( 'Note: Uninstaller required a reboot to complete uninstallation' ) reporter.addLogFile(sLogFile, 'log/uninstaller_reboot', \ "Verbose MSI uninstallation log file (reboot required)") # Optional, don't fail. else: fRc = False self._waitForTestManagerConnectivity(30) if fRc is False and os.path.isfile(sLogFile): reporter.addLogFile(sLogFile, 'log/uninstaller', "Verbose MSI uninstallation log file") # Log driver service states (should ls \Driver\VBox* and \Device\VBox*). for sService in self.kasWindowsServices: fRc2, _ = self._sudoExecuteSync(['sc.exe', 'query', sService]) if fIgnoreServices is False and fRc2 is True: fRc = False return fRc
def _executeTestCase(self, sName, sFullPath, sTestCaseSubDir, oDevNull): # pylint: disable=R0914 """ Executes a test case. """ fSkipped = False # # If hardening is enabled, some test cases and their dependencies # needs to be copied to and execute from the sVBoxInstallRoot # directory in order to work. They also have to be executed as # root, i.e. via sudo. # fHardened = False asFilesToRemove = [] # Stuff to clean up. asDirsToRemove = [] # Ditto. if sName in self.kasHardened \ and self.sUnitTestsPathBase != self.sVBoxInstallRoot: sDstDir = os.path.join(self.sVBoxInstallRoot, sTestCaseSubDir) if not os.path.exists(sDstDir): self._hardenedMkDir(sDstDir) asDirsToRemove.append(sDstDir) sDst = os.path.join(sDstDir, os.path.basename(sFullPath)) self._hardenedCopyFile(sFullPath, sDst, 0o755) asFilesToRemove.append(sDst) # Copy any associated .dll/.so/.dylib. for sSuff in ['.dll', '.so', '.dylib']: sSrc = os.path.splitext(sFullPath)[0] + sSuff if os.path.exists(sSrc): sDst = os.path.join(sDstDir, os.path.basename(sSrc)) self._hardenedCopyFile(sSrc, sDst, 0o644) asFilesToRemove.append(sDst) # Copy any associated .r0, .rc and .gc modules. offDriver = sFullPath.rfind('Driver') if offDriver > 0: for sSuff in ['.r0', 'RC.rc', 'RC.gc']: sSrc = sFullPath[:offDriver] + sSuff if os.path.exists(sSrc): sDst = os.path.join(sDstDir, os.path.basename(sSrc)) self._hardenedCopyFile(sSrc, sDst, 0o644) asFilesToRemove.append(sDst) sFullPath = os.path.join(sDstDir, os.path.basename(sFullPath)) fHardened = True # # Set up arguments and environment. # asArgs = [ sFullPath, ] if sName in self.kdArguments: asArgs.extend(self.kdArguments[sName]) os.environ['IPRT_TEST_OMIT_TOP_TEST'] = '1' os.environ['IPRT_TEST_FILE'] = sXmlFile = os.path.join( self.sScratchPath, 'result.xml') if os.path.exists(sXmlFile): try: os.unlink(sXmlFile) except: self._hardenedDeleteFile(sXmlFile) # # Execute the test case. # # Windows is confusing output. Trying a few things to get rid of this. # First, flush both stderr and stdout before running the child. Second, # assign the child stderr to stdout. If this doesn't help, we'll have # to capture the child output. # reporter.log('*** Executing %s%s...' % (asArgs, ' [hardened]' if fHardened else '')) try: sys.stdout.flush() except: pass try: sys.stderr.flush() except: pass if not self.fDryRun: try: if fHardened: oChild = utils.sudoProcessPopen(asArgs, stdin=oDevNull, stdout=sys.stdout, stderr=sys.stdout) else: oChild = utils.processPopenSafe(asArgs, stdin=oDevNull, stdout=sys.stdout, stderr=sys.stdout) except: if sName in [ 'tstAsmStructsRC', # 32-bit, may fail to start on 64-bit linux. Just ignore. ]: reporter.logXcpt() fSkipped = True else: reporter.errorXcpt() iRc = 1023 oChild = None if oChild is not None: self.pidFileAdd(oChild.pid, sName, fSudo=fHardened) iRc = oChild.wait() self.pidFileRemove(oChild.pid) else: iRc = 0 # # Clean up # for sPath in asFilesToRemove: self._hardenedDeleteFile(sPath) for sPath in asDirsToRemove: self._hardenedRemoveDir(sPath) # # Report. # if os.path.exists(sXmlFile): reporter.addSubXmlFile(sXmlFile) if fHardened: self._hardenedDeleteFile(sXmlFile) else: os.unlink(sXmlFile) if iRc == 0: reporter.log('*** %s: exit code %d' % (sFullPath, iRc)) self.cPassed += 1 elif iRc == 4: # RTEXITCODE_SKIPPED reporter.log('*** %s: exit code %d (RTEXITCODE_SKIPPED)' % (sFullPath, iRc)) fSkipped = True self.cSkipped += 1 elif fSkipped: reporter.log('*** %s: exit code %d (Skipped)' % (sFullPath, iRc)) self.cSkipped += 1 else: sName = self.kdExitCodeNames.get(iRc, '') if iRc in self.kdExitCodeNamesWin and utils.getHostOs() == 'win': sName = self.kdExitCodeNamesWin[iRc] if sName != '': sName = ' (%s)' % (sName) if iRc != 1: reporter.testFailure('Exit status: %d%s' % (iRc, sName)) reporter.log('!*! %s: exit code %d%s' % (sFullPath, iRc, sName)) else: reporter.error('!*! %s: exit code %d%s' % (sFullPath, iRc, sName)) self.cFailed += 1 return fSkipped
def _executeTestCase(self, sName, sFullPath, sTestCaseSubDir, oDevNull): # pylint: disable=R0914 """ Executes a test case. """ fSkipped = False; # # If hardening is enabled, some test cases and their dependencies # needs to be copied to and execute from the sVBoxInstallRoot # directory in order to work. They also have to be executed as # root, i.e. via sudo. # fHardened = False; asFilesToRemove = []; # Stuff to clean up. asDirsToRemove = []; # Ditto. if sName in self.kasHardened \ and self.sUnitTestsPathBase != self.sVBoxInstallRoot: sDstDir = os.path.join(self.sVBoxInstallRoot, sTestCaseSubDir); if not os.path.exists(sDstDir): self._hardenedMkDir(sDstDir); asDirsToRemove.append(sDstDir); sDst = os.path.join(sDstDir, os.path.basename(sFullPath)); self._hardenedCopyFile(sFullPath, sDst, 0755); asFilesToRemove.append(sDst); # Copy any associated .dll/.so/.dylib. for sSuff in [ '.dll', '.so', '.dylib' ]: sSrc = os.path.splitext(sFullPath)[0] + sSuff; if os.path.exists(sSrc): sDst = os.path.join(sDstDir, os.path.basename(sSrc)); self._hardenedCopyFile(sSrc, sDst, 0644); asFilesToRemove.append(sDst); # Copy any associated .r0, .rc and .gc modules. offDriver = sFullPath.rfind('Driver') if offDriver > 0: for sSuff in [ '.r0', 'RC.rc', 'RC.gc' ]: sSrc = sFullPath[:offDriver] + sSuff; if os.path.exists(sSrc): sDst = os.path.join(sDstDir, os.path.basename(sSrc)); self._hardenedCopyFile(sSrc, sDst, 0644); asFilesToRemove.append(sDst); sFullPath = os.path.join(sDstDir, os.path.basename(sFullPath)); fHardened = True; # # Set up arguments and environment. # asArgs = [sFullPath,] if sName in self.kdArguments: asArgs.extend(self.kdArguments[sName]); os.environ['IPRT_TEST_OMIT_TOP_TEST'] = '1'; os.environ['IPRT_TEST_FILE'] = sXmlFile = os.path.join(self.sScratchPath, 'result.xml'); if os.path.exists(sXmlFile): try: os.unlink(sXmlFile); except: self._hardenedDeleteFile(sXmlFile); # # Execute the test case. # # Windows is confusing output. Trying a few things to get rid of this. # First, flush both stderr and stdout before running the child. Second, # assign the child stderr to stdout. If this doesn't help, we'll have # to capture the child output. # reporter.log('*** Executing %s%s...' % (asArgs, ' [hardened]' if fHardened else '')); try: sys.stdout.flush(); except: pass; try: sys.stderr.flush(); except: pass; if not self.fDryRun: try: if fHardened: oChild = utils.sudoProcessPopen(asArgs, stdin = oDevNull, stdout = sys.stdout, stderr = sys.stdout); else: oChild = subprocess.Popen( asArgs, stdin = oDevNull, stdout = sys.stdout, stderr = sys.stdout); except: if sName in [ 'tstAsmStructsRC', # 32-bit, may fail to start on 64-bit linux. Just ignore. ]: reporter.logXcpt(); fSkipped = True; else: reporter.errorXcpt(); iRc = 1023; oChild = None; if oChild is not None: self.pidFileAdd(oChild.pid, fSudo = fHardened); iRc = oChild.wait(); self.pidFileRemove(oChild.pid); else: iRc = 0; # # Clean up # for sPath in asFilesToRemove: self._hardenedDeleteFile(sPath); for sPath in asDirsToRemove: self._hardenedRemoveDir(sPath); # # Report. # if os.path.exists(sXmlFile): reporter.addSubXmlFile(sXmlFile); if fHardened: self._hardenedDeleteFile(sXmlFile); else: os.unlink(sXmlFile); if iRc == 0: reporter.log('*** %s: exit code %d' % (sFullPath, iRc)); self.cPassed += 1 elif iRc == 4: # RTEXITCODE_SKIPPED reporter.log('*** %s: exit code %d (RTEXITCODE_SKIPPED)' % (sFullPath, iRc)); fSkipped = True; self.cSkipped += 1; elif fSkipped: reporter.log('*** %s: exit code %d (Skipped)' % (sFullPath, iRc)); self.cSkipped += 1; else: sName = self.kdExitCodeNames.get(iRc, ''); if iRc in self.kdExitCodeNamesWin and utils.getHostOs() == 'win': sName = self.kdExitCodeNamesWin[iRc]; if sName != '': sName = ' (%s)' % (sName); if iRc != 1: reporter.testFailure('Exit status: %d%s' % (iRc, sName)); reporter.log( '!*! %s: exit code %d%s' % (sFullPath, iRc, sName)); else: reporter.error('!*! %s: exit code %d%s' % (sFullPath, iRc, sName)); self.cFailed += 1 return fSkipped;