26 from copy
import deepcopy
28 import xml.etree.cElementTree
as etree
42 from .LogHandler
import LogHandler
44 if sys.version_info.major >= 3:
55 passedSeconds = time.time() - self.
startstart
67 def __init__(self, config, logfileDir, env, isInsideTestCaseManager):
68 self.
__id__id = SlaveProcess.nextSlaveId
69 SlaveProcess.nextSlaveId += 1
75 self.
__logger__logger = logging.getLogger(
"TestCenter")
76 self.
__workDir__workDir = os.path.join(config.getResultDir(),
"work")
78 cmd = self.
__getCommandLine__getCommandLine(config, logfileDir, isInsideTestCaseManager)
85 def __getCommandLine(self, config, logfileDir, isInsideTestCaseManager):
87 cmd = config.getMLABTestCenterCommand(macroName=
"TestCenter")
89 self.
__slaveLogFile__slaveLogFile = os.path.join(logfileDir, f
"slaveLogfile_{self.getID()}.log")
90 cmd.insert(1,
'-logfile')
92 if isInsideTestCaseManager:
93 cmd.append(
'--started-from-test-case-manager')
98 self.
__logger__logger.
error(
"Failed to start slave as no MeVisLab executable was found. " + \
99 "Please verify your configuration (see TestCase Manager's " + \
100 "Configuration tab or check the file %s)!" % config.getConfigFilePath())
103 def __startProcess(self, cmd, _, env):
105 self.
__logger__logger.debug(
'Starting slave with command line %s' %
' '.join(cmd))
107 preexec_fn = os.setpgrp
if Utils.isUnix
else None
108 self.
__process__process = subprocess.Popen(cmd, cwd=self.
__workDir__workDir, preexec_fn=preexec_fn, env=env,
109 stdin=subprocess.PIPE,
113 self.
__logger__logger.
error(
"Failed to start slave (%s)\n%s" % (cmd, traceback.format_exc()))
134 def __printLogsAfterError(self):
138 with open(self.
__slaveLogFile__slaveLogFile,
'r', errors=
"replace")
as fh:
140 if os.path.exists(self.
__logFile__logFile):
141 with open(self.
__logFile__logFile,
'r', errors=
"replace")
as fh:
154 self.
logErrorWithPIDlogErrorWithPID(
"Could not close log file: %s" % str(e))
157 if os.path.exists(self.
__logFile__logFile):
159 Utils.removeFile(self.
__logFile__logFile)
161 self.
logErrorWithPIDlogErrorWithPID(
"Could not remove log file: %s" % str(e))
166 return "%s (PID: %s)" % (message, str(self.
getPIDgetPID()))
176 def __init__(self, name, status, errorCount, warningCount, duration):
227 __testCasesToIgnoreList = []
240 def __init__ (self, cfgFile=None, verbose=False, slave=None, slaveEnvironment=None,
241 isInsideTestCaseManager=False):
242 self.
__logger__logger = logging.getLogger(
"TestCenter")
246 self.
__com__com =
None if slave
is not None else IPC.ComMaster(connectTimeout=self.
__config__config.getIPCConnectionTimeout())
252 self.
__lock__lock = threading.Lock()
259 resultDir = self.
__config__config.getResultDir()
260 imgDir = os.path.join(resultDir,
"images")
261 fileDir = os.path.join(resultDir,
"files")
262 workDir = os.path.join(resultDir,
"work")
263 self.
logfileDirlogfileDir = os.path.join(resultDir,
"logfiles")
265 if not os.path.exists(resultDir):
266 os.makedirs(resultDir)
268 Utils.rmtree(fileDir)
274 Utils.rmtree(workDir)
287 if self.
__slave__slave
is None:
289 raise Exception(
"Failed to start slave")
295 slaveProc.finish(printLog=
True)
296 if not slaveProc.kill():
297 self.
__logger__logger.
error(
"Finally killing process %s failed." % slaveProc.getPID())
312 self.
__lock__lock.acquire()
314 self.
__lock__lock.release()
317 self.
__lock__lock.acquire()
319 self.
__lock__lock.release()
323 self.
__lock__lock.acquire()
325 self.
__lock__lock.release()
329 self.
__lock__lock.acquire()
331 self.
__lock__lock.release()
334 progressTestCase =
None
335 if finishedTestCase
is not None:
338 for function
in finishedTestCase.findall(
"Function"):
339 status = int(function.get(
"status", str(Utils.TEST_STATUS_DISABLED)))
340 if status
in (Utils.TEST_STATUS_ERROR, Utils.TEST_STATUS_CRASHED,
341 Utils.TEST_STATUS_FUNCTION_NOT_FOUND, Utils.TEST_STATUS_TIMEOUT):
343 elif status == Utils.TEST_STATUS_WARNING:
346 int(finishedTestCase.get(
"status", str(Utils.TEST_STATUS_CANCELLED))),
349 float(finishedTestCase.get(
"duration",
"0")))
351 self.
__lock__lock.acquire()
352 if progressTestCase
is not None:
353 self.
__testProgress__testProgress.finishedTestCases.append(progressTestCase)
354 if additionalTestCaseCount
is not None:
355 self.
__testProgress__testProgress.testCaseCount += additionalTestCaseCount
356 self.
__lock__lock.release()
362 self.
__lock__lock.acquire()
364 self.
__lock__lock.release()
368 def __testConfigSkeleton(self):
369 return etree.fromstring(
"""
393 xmlNode = self.
__testCfg__testCfg.find(
"TestCases")
394 for testCaseName
in testCaseList:
395 etree.SubElement(xmlNode,
"TestCase", name=testCaseName)
411 xmlNode = self.
__testCfg__testCfg.find(
"TestGroups")
412 for testGroupName
in testGroupList:
413 etree.SubElement(xmlNode,
"TestGroup", name=testGroupName)
419 xmlNode = self.
__testCfg__testCfg.find(
"TestSuites")
420 for testSuiteName
in testSuiteList:
421 etree.SubElement(xmlNode,
"TestSuite", name=testSuiteName)
433 xmlNode = self.
__testCfg__testCfg.find(
"Modules")
434 for moduleName
in moduleList:
435 etree.SubElement(xmlNode,
"Module", name=moduleName)
436 for filter
in filterList:
437 etree.SubElement(xmlNode,
"Filter").text = filter
450 def setPackages (self, testedPkgList=[], availablePkgList=[], ignoredPkgList=[]):
455 xmlNode = self.
__testCfg__testCfg.find(
"Packages/Tested")
456 for packageID
in testedPkgList:
457 etree.SubElement(xmlNode,
"Package", name=packageID)
459 xmlNode = self.
__testCfg__testCfg.find(
"Packages/Available")
460 for packageID
in availablePkgList:
461 etree.SubElement(xmlNode,
"Package", name=packageID)
463 xmlNode = self.
__testCfg__testCfg.find(
"Packages/Ignored")
464 for packageID
in ignoredPkgList:
465 etree.SubElement(xmlNode,
"Package", name=packageID)
468 def __testTypeAndName(self, xmlNode):
470 testType = xmlNode.get(
'type')
471 testName = xmlNode.get(
'name')
if testType ==
'FunctionalTestCase' else "%s::%s" % (xmlNode.get(
'name'), xmlNode.get(
'module'))
473 return testType, testName
480 def __statusMessage (self, xmlNode, status):
481 assert type(status) == int
482 assert xmlNode.tag ==
'TestCase'
484 statusStr = Utils.getStatusString(status)
486 fillIn =
"."*(80-len(testType+testName+statusStr)-2)
487 msg =
"%s::%s%s%s" % (testType, testName, fillIn, statusStr)
488 if status == Utils.TEST_STATUS_OK
or status == Utils.TEST_STATUS_DO_NOT_TEST_MODULE:
490 elif status == Utils.TEST_STATUS_WARNING:
508 def __testFailed (self, xmlNode, comError):
509 assert xmlNode.tag ==
"TestCase"
511 testType = xmlNode.get(
'type')
512 if testType ==
u"GenericTestCase":
513 testName =
"%s::%s" % (xmlNode.get(
'name'), xmlNode.get(
'module'))
515 testName = xmlNode.get(
'name')
519 for funcNode
in xmlNode.findall(
'Function'):
520 funcDict.setdefault(funcNode.get(
'name'), funcNode)
523 status = Utils.TEST_STATUS_ERROR
524 if comError
in (IPC.Error.EMPTY_MESSAGE, IPC.Error.ON_RECEIVING_2):
525 status = Utils.TEST_STATUS_CRASHED
526 elif comError == IPC.Error.ON_RECEIVING_TIMEOUT:
527 status = Utils.TEST_STATUS_TIMEOUT
530 logHandler = LogHandler(self.
__config__config.getSlaveLogFilePath())
531 logHandler.parseLogFile(testType, testName, status, funcDict)
540 def __buildTestAgenda (self):
542 if resultNode.get(
'errorCode') !=
"Ok":
543 self.
__logger__logger.critical(
"Error (%s) in generating the test agenda!\n%s" % (resultNode.get(
'errorCode'), resultNode.find(
'Error').text))
545 self.
__xmlRoot__xmlRoot = resultNode.find(
'TestRun')
549 self.
__sendRequest__sendRequest(
'SetPackageList', self.
__testCfg__testCfg.find(
'Packages'), 5, restart=
True)
554 def __buildTestCaseAgenda (self, testCaseNode):
555 parameterNode = etree.Element(
'Parameters')
556 genericTestCase =
True
559 for module
in self.
__xmlRoot__xmlRoot.findall(
'Information/Modules/Module'):
560 moduleList.append(module.attrib[
'name'])
561 parameterNode.attrib[
'modules'] =
','.join(moduleList)
563 parameterNode.attrib[
'packages'] =
','.join(self.
__testedPkgList__testedPkgList)
566 parameterNode.attrib[
'packages'] =
'*/*'
567 parameterNode.append(testCaseNode)
568 resultNode = self.
__sendRequest__sendRequest(
"BuildTestCaseAgenda", parameterNode, restart=
True)
569 if resultNode.get(
'errorCode') !=
"Ok":
570 self.
__logger__logger.critical(
"Error (%s) in generating the test case agenda!\n%s" % (resultNode.get(
'errorCode'), resultNode.find(
'Error').text))
585 def __verifyConfiguration (self, testCfg):
587 packageRoot = testCfg.find(
'Packages')
589 tPkgNode = packageRoot.find(
'Tested')
590 for packageNode
in tPkgNode.findall(
'Package'):
591 if packageNode.get(
'status')
not in (
'Ok',
'Added',
'Substituted'):
592 self.
__logger__logger.
error(
"Failed to verify package (%s with status '%s')!" % (packageNode.get(
'name'), packageNode.get(
'status')))
594 aPkgNode = packageRoot.find(
'Available')
595 for packageNode
in aPkgNode.findall(
'Package'):
596 if packageNode.get(
'status')
not in (
'Ok',
'Added',
'Substituted'):
597 self.
__logger__logger.
error(
"Failed to verify package (%s with status '%s')!" % (packageNode.get(
'name'), packageNode.get(
'status')))
599 if packageNode.get(
'status')
not in (
'Substituted'):
600 packageRoot.append(packageNode)
602 packageRoot.remove(tPkgNode)
603 packageRoot.remove(aPkgNode)
605 iPkgNode = packageRoot.find(
'Ignored')
606 packageRoot.remove(iPkgNode)
609 for moduleNode
in testCfg.findall(
'Modules/Module'):
610 isModuleFiltered = moduleNode.get(
'isModuleFiltered') == str(
True)
611 if not isModuleFiltered
and moduleNode.get(
'status') != str(Utils.TEST_STATUS_OK):
612 self.
__logger__logger.
error(
"Failed to verify module (%s with status '%s')" % (moduleNode.get(
'name'), moduleNode.get(
'status')))
613 testCfg.find(
'Modules').clear()
616 for testCaseNode
in testCfg.findall(
'TestCases/TestCase'):
617 isNotInTestGroups = testCaseNode.get(
'isNotInTestGroups') == str(
True)
618 if not isNotInTestGroups
and testCaseNode.get(
'status') != str(Utils.TEST_STATUS_OK):
619 self.
__logger__logger.
error(
"Failed to verify test case (%s with status '%s')" % (testCaseNode.get(
'name'), testCaseNode.get(
'status')))
620 testCfg.find(
'TestCases').clear()
625 def __createTimeoutTooHighErrorFunction(self, testCaseInfoNode, testResultNode, timeout):
626 functionName =
'TEST001_VerifyTestCaseTimeout'
627 testFunctions = testCaseInfoNode.find(
'TestFunctions')
628 testFunction = etree.SubElement(testFunctions,
"Function")
629 testFunction.attrib = {
'basename':
'VerifyTestCaseTimeout',
'is_disabled':
'False',
'name': functionName}
630 etree.SubElement(testFunction,
"Documentation").text =
'Verifies if the TestCase timeout.'
631 timeoutTooHighTestFunction = etree.SubElement(testResultNode,
"Function")
632 timeoutTooHighTestFunction.attrib = {
'duration':
'0',
'name': functionName,
'status':
'2',
'is_disabled':
'False',
'try':
'1'}
633 events = etree.SubElement(timeoutTooHighTestFunction,
'Events')
634 filename = testCaseInfoNode.find(
'File').text
635 line = testCaseInfoNode.find(
'Line').text
636 event = etree.SubElement(events,
'Event')
637 event.attrib = {
'file': filename,
'internal':
'true',
'line': line,
'origin':
'',
'type':
'Error',
638 'timestamp': datetime.datetime.now().strftime(
'%Y-%m-%d %H:%M:%S')}
639 error =
'The TestCase timeout (%ss) exceeds the maximum allowed timeout (%ss)' % (timeout, self.
__config__config.getMaxTestTimeoutSeconds())
640 etree.SubElement(event,
'Message').text = error
642 def __buildListOfTestFunctionsToExecute (self, testCaseInfoNode, testCaseNode, funcList=None):
645 for funcNode
in testCaseInfoNode.findall(
".//Function"):
646 funcName = funcNode.get(
'name')
648 if funcList
and funcName
not in funcList
and not funcName
in Utils.VIRTUAL_TEST_CASE_FUNCTIONS:
651 isDisabled = funcNode.get(
"is_disabled", str(
False)) == str(
True)
654 if isDisabled
and funcList:
657 funcNode.set(
'is_disabled', str(
False))
658 funcResultNode = etree.SubElement(testCaseNode,
'Function', name=funcName, is_disabled=str(isDisabled))
659 testFuncList.append(funcName)
671 def __doTest (self, testCaseInfoNode, testResultNode, funcList=None):
672 assert testResultNode.tag ==
'TestCase'
674 testCaseNode = deepcopy(testResultNode)
679 testCaseName = testCaseInfoNode.get(
'name')
684 hasValidTimeout =
True
685 timeout = int(testCaseInfoNode.get(
'timeout'))
687 timeout = self.
__config__config.getDefaultTestTimeoutSeconds()
688 if self.
__config__config.getMaxTestTimeoutSeconds():
689 if timeout > self.
__config__config.getMaxTestTimeoutSeconds():
691 hasValidTimeout =
False
694 if self.
__config__config.isPythonCoverageEnabled():
695 timeout = timeout * 4.
696 if self.
__config__config.isBullseyeCoverageEnabled():
697 timeout = timeout * 4.
700 retries, status = self.
__executeTestFunctions__executeTestFunctions(testCaseInfoNode, testResultNode, testCaseNode, testFuncList, timeout)
703 status = Utils.TEST_STATUS_ERROR
706 testResultNode.set(
"status",
unicode(status))
707 testResultNode.set(
"retries",
unicode(retries))
716 coverageFile = executionNode.get(nodeName)
717 if executionNode.get(nodeName)
is not None:
718 testResultNode.set(nodeName, coverageFile)
720 def __executeTestFunctions (self, testCaseInfoNode, testResultNode, testCaseNode, testFuncList, timeout):
721 if testCaseNode.get(
'status') == str(Utils.TEST_STATUS_DO_NOT_TEST_MODULE):
722 return 0, Utils.TEST_STATUS_DO_NOT_TEST_MODULE
728 status = Utils.TEST_STATUS_OK
729 maxFuncStatus = Utils.TEST_STATUS_OK
731 while testFuncList
and not timer.isExpired()
and not cancelled:
736 status = Utils.TEST_STATUS_CANCELLED
741 testCaseNode.set(
"requestProgress",
"1")
743 testCaseNode.set(
"maxErrorMessagesPerTestFunction", str(self.
__config__config.getReportOptions().maxErrorMessagesPerTestFunction))
744 testCaseNode.set(
"maxInfoMessagesPerTestFunction", str(self.
__config__config.getReportOptions().maxInfoMessagesPerTestFunction))
747 executionNode = self.
__sendRequest__sendRequest(
"DoTest", testCaseNode, timeout=timer.getSecondsRemaining(), tries=1)
748 if executionNode.get(
'errorCode') !=
"Ok":
749 self.
__logger__logger.debug(
'Restarting due to error in test execution.\n%s' % executionNode.find(
'Error').text)
752 comError = self.
__com__com.getLastError()
if self.
__com__com
else 0
758 status = self.
__testFailed__testFailed(testCaseNode, comError)
761 self.
__logger__logger.debug(
'Failed to re-start slave.')
763 testCaseNode = executionNode.find(
'TestCase')
768 extraTestCasesResults = testCaseNode.find(
'ExtraTestCasesResults')
769 if extraTestCasesResults !=
None:
770 testResultNode.append(deepcopy(extraTestCasesResults))
773 for funcResultNode
in testCaseNode.findall(
'Function'):
774 funcName = funcResultNode.get(
"name")
777 funcStatus = funcResultNode.get(
"status")
782 funcStatus = int(funcStatus)
783 if maxFuncStatus < funcStatus:
784 maxFuncStatus = funcStatus
786 if funcName
not in failedFuncList:
787 funcResultNode.set(
'try',
'1')
789 if funcStatus
in (Utils.TEST_STATUS_CRASHED , Utils.TEST_STATUS_TIMEOUT):
790 failedFuncList.append(funcName)
793 testResultNode.append(deepcopy(funcResultNode))
794 funcResultNode.remove(funcResultNode.find(
"Events"))
796 funcResultNode.set(
'try',
'2')
797 failedFuncList.remove(funcName)
801 if funcName
not in failedFuncList:
802 testFuncList.remove(funcName)
804 testResultNode.append(funcResultNode)
805 testCaseNode.remove(funcResultNode)
806 if funcStatus == Utils.TEST_STATUS_CANCELLED
or funcStatus == Utils.TEST_STATUS_FUNCTION_NOT_FOUND:
810 if timer.isExpired():
811 status = Utils.TEST_STATUS_TIMEOUT
819 status = status
if status > Utils.TEST_STATUS_ERROR
else maxFuncStatus
820 return retries, status
827 def __handleExtraTestCaseResults(self, testCaseInfos, resultNode, testResultNode):
828 node = testResultNode.find(
"ExtraTestCasesResults")
830 testResultNode.remove(node)
831 for node
in node.findall(
"ExtraTestCaseResult"):
832 testCaseInfos.append(node.find(
"Information/TestCase"))
833 extraTestCaseResult = node.find(
"Result/TestCase")
834 extraTestCaseResult.set(
"slave_id", testResultNode.get(
"slave_id"))
835 resultNode.append(extraTestCaseResult)
840 return self.
__config__config.isPythonCoverageEnabled()
and self.
__config__config.isGlobalPythonCoverageEnabled()
853 def run(self, funcDict=None, stopSlaveAfterTestRun=True):
859 timeStarted = time.time()
861 testCaseInfos = self.
__xmlRoot__xmlRoot.find(
'Information/TestCases')
865 freshCounterValue = self.
__config__config.getRestartInterval()
866 restartCounter = freshCounterValue
867 restartDisabled = (restartCounter == 0)
869 testCaseInfosTestCases = testCaseInfos.findall(
'TestCase')
872 for node
in testCaseInfosTestCases:
873 testNames.append(node.get(
'name'))
879 finishedTestCases = 0
880 totalTestCases = len(testCaseInfosTestCases)
882 resultNode = self.
__xmlRoot__xmlRoot.find(
'Results')
884 for testCaseNode
in testCaseInfosTestCases:
886 testCaseInfos.remove(testCaseNode)
891 if testCaseAgenda !=
None:
893 testCaseInfoNodes = testCaseAgenda.findall(
'TestCase')
894 assert(len(testCaseInfoNodes) == 1)
895 testCaseInfoNode = testCaseInfoNodes[0]
897 testCaseInfos.remove(testCaseNode)
898 testCaseInfos.append(testCaseInfoNode)
900 testResultNodes = testCaseAgenda.find(
'Results').findall(
'TestCase')
901 if len(testResultNodes) > 1:
902 self.
updateTestProgressupdateTestProgress(additionalTestCaseCount=len(testResultNodes)-1)
903 totalTestCases += len(testResultNodes)-1
904 for testResultNode
in testResultNodes:
908 testCaseName = testCaseInfoNode.get(
'name')
911 preferredRendererNode = testCaseInfoNode.find(
'preferredRenderer')
912 preferredRenderer =
"" if preferredRendererNode
is None else preferredRendererNode.text.lower()
913 forceSoftwareRendering = (preferredRenderer ==
"software")
914 if preferredRenderer ==
"hardware" and Utils.isMesaForced():
915 self.
__logger__logger.
warning(
'preferredRenderer settings "hardware" detected but use of software driver is enforced.')
917 if not restartDisabled
or forceSoftwareRendering:
918 shouldRestart = (restartCounter == 0)
919 if shouldRestart
or forceSoftwareRendering:
920 self.
__logger__logger.
info(
"Restart slave for test case %s::%s" % (debugType, debugName))
921 if not self.
__startSlave__startSlave(forceSoftwareRendering=forceSoftwareRendering):
922 raise Exception(
'Failed to start slave.')
924 restartCounter = freshCounterValue
932 self.
__updateProgressFunc__updateProgressFunc(testCaseName, failedTestCases, finishedTestCases, totalTestCases)
934 timeFunctionStarted = time.time()
935 funcList = funcDict[testCaseName]
if (funcDict
and testCaseName
in funcDict)
else None
936 self.
__doTest__doTest(testCaseInfoNode, testResultNode, funcList)
937 timeFunctionStopped = time.time()
938 if int(testResultNode.get(
"status")) == Utils.TEST_STATUS_CANCELLED:
941 if int(testResultNode.get(
"status"))
in (Utils.TEST_STATUS_CRASHED,
942 Utils.TEST_STATUS_ERROR,
943 Utils.TEST_STATUS_FUNCTION_NOT_FOUND,
944 Utils.TEST_STATUS_TIMEOUT):
946 finishedTestCases += 1
948 testResultNode.set(
'duration', str(timeFunctionStopped-timeFunctionStarted))
950 testResultNode.set(
'slave_id',
'0' if self.
__slave__slave
else str(self.
__slaveProc__slaveProc.getID()))
952 resultNode.append(testResultNode)
956 except Exception
as e:
957 traceback.print_exc()
958 self.
__logger__logger.
error(
"Error executing test case %s::%s\n%s" % (debugType, debugName, e))
959 testResultNode.set(
"status",
unicode(Utils.TEST_STATUS_TIMEOUT))
962 self.
__logger__logger.
error(
"Failed to build the test agenda for test case %s." % testCaseNode.get(
'name',
'unknown'))
963 except Exception
as e:
964 self.
__logger__logger.
error(
"Error executing test case %s" % e)
967 resultNode.set(
"combinePythonCoverage",
"True")
970 timeStopped = time.time()
972 self.
__xmlRoot__xmlRoot.set(
'timestamp', str(timeStarted))
973 self.
__xmlRoot__xmlRoot.set(
'duration', str(timeStopped-timeStarted))
975 if stopSlaveAfterTestRun:
978 xml = Utils.saveXMLTree(self.
__xmlRoot__xmlRoot, self.
__config__config.getResultFile())
1002 def __isSlaveRunning (self):
1005 def __isSlaveStopped(self):
1010 pidString = str(self.
__slaveProc__slaveProc.getPID())
if self.
__slaveProc__slaveProc
is not None else str(
None)
1012 return "%s (PID: %s)" % (message, pidString)
1021 errorCode, errorMessage = self.
__com__com.getLastErrorWithMessage()
1022 return "%s ([%d] %s)" % (message, errorCode, errorMessage)
1029 def __startSlave (self, forceSoftwareRendering=False):
1035 self.
__logger__logger.
error(
"Failed to stop the slave before restart.")
1040 env = Utils.setTestCenterPort(env, self.
__com__com.getPort())
1042 if slaveProc.hasStarted():
1050 def __connectToSlave(self):
1054 while retries < maxTries
and not self.
__com__com.connect(timeout = self.
__config__config.getIPCConnectionTimeout()):
1064 self.
__logger__logger.debug(
"Sleeping for %s seconds" % (timerSleep))
1065 time.sleep(timerSleep)
1067 if not self.
__com__com.isConnected():
1069 self.
logErrorWithPIDlogErrorWithPID(
"Failed to connect to slave within %d seconds." % (maxTries*timerSleep))
1071 self.
__logger__logger.
error(
"Failed to stop the slave after connection error.")
1075 self.
logDebugWithPIDlogDebugWithPID(
"Connected to slave in %s. try" % (retries+1))
1081 resultNode = self.
__sendRequest__sendRequest(
'SetPackageList', self.
__testCfg__testCfg.find(
'Packages'), 5)
1082 return resultNode.get(
'errorCode') ==
"Ok"
1102 xmlNode = self.
__sendRequest__sendRequest(
'Quit', timeout=1, tries=1)
1104 if xmlNode.get(
'errorCode') ==
'Ok':
1105 self.
logDebugWithPIDlogDebugWithPID(
"Response received, waiting for shutdown")
1135 def __sendRequest (self, command, parameterNode=None, timeout=None, tries=2, restart=False):
1138 requestNode = etree.Element(
'Command', type=command)
1139 requestNode.append(parameterNode
if parameterNode !=
None else etree.Element(
'Dummy'))
1142 self.
logDebugWithPIDlogDebugWithPID(
"Handling '%s' request" % command)
1143 resultNode = self.
__slave__slave.runCommand(requestNode)
1145 self.
logDebugWithPIDlogDebugWithPID(
"Sending '%s' request to slave" % command)
1149 timeout = self.
__config__config.getDefaultTestTimeoutSeconds()
1153 and (trial < tries)):
1155 if self.
__com__com.send(etree.tostring(requestNode), timer.getSecondsRemaining()):
1158 while not string
and not timer.isExpired():
1159 string = self.
__com__com.recv(timer.getSecondsRemaining())
1161 recvNode = Utils.filterXMLString(string)
1162 self.
logDebugWithPIDlogDebugWithPID(
"Received node of type '%s'" % recvNode.tag)
1163 if recvNode.tag ==
"Progress":
1167 self.
__testCaseListener__testCaseListener.startTestCaseFunction(recvNode.get(
"testType"), recvNode.get(
"testCase"), recvNode.get(
"testFunction"))
1171 self.
__com__com.send(
"0" if shouldStop
else "1", 5)
1173 elif recvNode.tag ==
"Status":
1175 self.
__testCaseListener__testCaseListener.endTestCaseFunction(int(recvNode.get(
"status")), 0)
1178 resultNode = recvNode
1185 if restart
and (trial < tries):
1186 self.
__logger__logger.
info(
"Restarting due to communication error ...")
1189 if resultNode ==
None:
1190 self.
logDebugWithPIDlogDebugWithPID(
"Error: Received no result from slave.")
1191 resultNode = etree.Element(
'Result', errorCode=
'CommunicationError')
1192 etree.SubElement(resultNode,
'Error').text =
"Communication error [%d]: %s" % self.
__com__com.getLastErrorWithMessage()
1193 self.
logDebugWithPIDlogDebugWithPID(
"Result error code: %s" % resultNode.get(
'errorCode'))
1194 content = etree.tostring(resultNode).decode()
1195 self.
logDebugWithPIDlogDebugWithPID(
"Result content: %s%s" % (content[:150],
" [...]" if len(content)>150
else ""))
The coordinator of test execution.
def __isSlaveRunning(self)
def logMessageWithPID(self, message)
def setTestCasesToIgnore(self, testCaseToIgnoreList)
Set the list of test cases to ignore.
def run(self, funcDict=None, stopSlaveAfterTestRun=True)
The main method which handles all the request from the master.
def logMessageWithLastError(self, message)
def setModules(self, moduleList=[], filterList=[])
Specify the list of modules to test.
def setUpdateProgressFunc(self, updateProgressFunc)
def __testFailed(self, xmlNode, comError)
def setActiveTestCase(self, testCase)
__isInsideTestCaseManager
list __testCasesToIgnoreList
def __buildListOfTestFunctionsToExecute(self, testCaseInfoNode, testCaseNode, funcList=None)
def __createTimeoutTooHighErrorFunction(self, testCaseInfoNode, testResultNode, timeout)
def __connectToSlave(self)
def __doTest(self, testCaseInfoNode, testResultNode, funcList=None)
def __executeTestFunctions(self, testCaseInfoNode, testResultNode, testCaseNode, testFuncList, timeout)
def __statusMessage(self, xmlNode, status)
def logDebugWithPID(self, message)
def setTestSuites(self, testSuiteList)
def __testTypeAndName(self, xmlNode)
def setTestCaseListener(self, listener)
def setTestGroups(self, testGroupList)
Set the list of test groups to respect.
def setPackages(self, testedPkgList=[], availablePkgList=[], ignoredPkgList=[])
Specify the packages that should be tested and thought available.
def __verifyConfiguration(self, testCfg)
def shouldMeasurePythonCoverageGlobally(self)
def __sendRequest(self, command, parameterNode=None, timeout=None, tries=2, restart=False)
def __isSlaveStopped(self)
def __init__(self, cfgFile=None, verbose=False, slave=None, slaveEnvironment=None, isInsideTestCaseManager=False)
The default constructor.
def __buildTestAgenda(self)
def transferNodeFromExecutionToResultXML(self, nodeName, executionNode, testResultNode)
def reset(self)
Resets the master to the state after instantiation.
def updateTestProgress(self, finishedTestCase=None, additionalTestCaseCount=None)
def logErrorWithPID(self, message)
def resetTestProgress(self, testCaseCount)
def setTestCases(self, testCaseList)
Set the list of test cases to execute.
def getTestProgress(self)
def __testConfigSkeleton(self)
def __startSlave(self, forceSoftwareRendering=False)
def __handleExtraTestCaseResults(self, testCaseInfos, resultNode, testResultNode)
def __buildTestCaseAgenda(self, testCaseNode)
def __init__(self, name, status, errorCount, warningCount, duration)
def logMessageWithPID(self, message)
def __getCommandLine(self, config, logfileDir, isInsideTestCaseManager)
def __printLogsAfterError(self)
def __startProcess(self, cmd, _, env)
def logErrorWithPID(self, message)
def __init__(self, config, logfileDir, env, isInsideTestCaseManager)
def finish(self, printLog)
def logDebugWithPID(self, message)
def __init__(self, seconds)
def getSecondsRemaining(self)
def reset(self, testCaseCount)
def error(message, stack=False, type='', depth=0)
Put an error to the log.
def warning(message, stack=False, type='', depth=0)
Put a warning to the log.
def info(message, stack=False, type='', depth=0)
Put an info message to the log.