TestCenter Reference
Slave.py
Go to the documentation of this file.
2# Copyright 2007, MeVis Medical Solutions AG
3#
4# The user may use this file in accordance with the license agreement provided with
5# the Software or, alternatively, in accordance with the terms contained in a
6# written agreement between the user and MeVis Medical Solutions AG.
7#
8# For further information use the contact form at https://www.mevislab.de/contact
9#
10
13
14import os
15import re
16import traceback
17
18import xml.etree.cElementTree as etree
19
20import mevis
21import PackageSorter
22
23from . import IPC
24from . import Config
25from . import Utils
26from .LogHandler import LogHandler
27from TestSupport.TestHelper import TestHelper
28
29from .TestCaseGeneric import GenericTestCase
30from .TestCaseFunctional import FunctionalTestCase
31import TestSupport
32
33from . import CodeCoverage
34from .CodeTestSupport import getCodeTest, getCodeTestsByPackage, CodeTestTestCase
35
36
37# Determine if the Standard SDK FME modules are available:
38_isPublicSDK = bool(
39 mevis.MLABPackageManager.packagesByGroup("FMEstable") and mevis.MLABPackageManager.packagesByGroup("FMEwork")
40)
41
42
44
45 def __init__(self, com):
46 self.stopped = False
47 self.__com = com
48
49 def startTestCaseFunction(self, testType, testCase, testFunction):
50 resultNode = etree.Element("Progress")
51 resultNode.set("testType", testType)
52 resultNode.set("testCase", testCase)
53 resultNode.set("testFunction", testFunction)
54 if not self.__com.send(etree.tostring(resultNode), 5):
55 mevis.MLAB.logError("Couldn't send progress")
57 # receive the result, if it is "0", we are supposed to stop,
58 # otherwise we can continue
59 result = self.__com.recv(5)
60 if result == "0":
62
63 def endTestCaseFunction(self, status, duration):
64 resultNode = etree.Element("Status")
65 resultNode.set("status", str(status))
66 if not self.__com.send(etree.tostring(resultNode), 5):
67 mevis.MLAB.logError("Couldn't send status")
69
70
71class Slave:
72 """The class controlling a MeVisLab slave instance.
73 The slave is controlled by a master using socket based IPC to send messages.
74 """
75
76 def __init__(self, cfgFile, context, offline=False):
77 """Initializes the slave process.
78
79 @param cfgFile The configuration file used for this test run.
80 @param context The context used for testing.
81 @param offline Specifies whether the tests are run in same MeVisLab instance as master.
82 """
83 self.__ctx = context
84 self.__com = IPC.ComSlave() if not offline else None
85
86 self.__testCaseListener = None
87 self.__agendaTestCase = None
88 self.__isInsideTestCaseManager = False
89 self.__testCase = None
90 self.__running = False
91 self.__testCfg = None
92
93 # The current configuration
95
96 # Create result directory if not available.
97 resultDir = self._config.getResultDir()
98 if not os.path.isdir(resultDir):
99 os.makedirs(resultDir)
100
101 # Set new logfile to use. This is required as there could be multiple
102 # MeVisLab instances writing to the same logfile what would make crash
103 # handling impossible.
104 self.__logfile = self._config.getSlaveLogFilePath()
105
106 # Load test cases if not done already.
107 if not mevis.MLABTestCaseDatabase.areTestCasesLoaded():
108 mevis.MLABTestCaseDatabase.loadTestCases()
109
110 # Initialize the test helper singleton.
111 TestHelper.getInstance(context=self.__ctx, resultDir=self._config.getResultDir())
112
113 def setIsInsideTestCaseManager(self, isInsideTestCaseManager):
114 self.__isInsideTestCaseManager = isInsideTestCaseManager
115
116 def setTestCaseListener(self, listener):
117 self.__testCaseListener = listener
118
119 def loadTestCase(self, testCaseNode):
120 """Load the given test case.
121 If the test case could not be loaded "None" is returned.
122
123 @param testCaseNode XML representation containing information on the test case to load.
124 @return The loaded test case.
125 """
126 testType = testCaseNode.get("type")
127 moduleName = testCaseNode.get("module") if testType == "GenericTestCase" else None
128 return self.__loadTestCase(testCaseNode.get("name"), testType, moduleName)
129
130 @staticmethod
131 def __loadTestCase(testCaseName, testCaseType, moduleName=None):
132 """Internal loading mechanism.
133
134 @param testCaseName Name of the test case to be loaded.
135 @param testCaseType Type of the test case to be loaded.
136 @param moduleName Name of module to be tested (in case of generic test cases.)
137 @return The loaded test case. None if loading failed.
138 """
139 # Create test case depending on the type.
140 try:
141 match testCaseType:
142 case "GenericTestCase":
143 return GenericTestCase(testCaseName, moduleName)
144 case "FunctionalTestCase":
145 return FunctionalTestCase(testCaseName)
146 case "CodeTestTestCase":
147 return CodeTestTestCase(testCaseName)
148 except Exception as e:
149 mevis.MLAB.logError("Error loading test case %s: %s" % (testCaseName, e))
150 return None
151 raise RuntimeError("Unsupported test case type %s" % testCaseType)
152
153 def setAgendaTestCase(self, testCase):
154 """Set the test case that is used for building the agenda/function list.
155 Used in the TestCaseManager module to make local testing possible.
156
157 @param testCase The test case object.
158 """
159 self.__agendaTestCase = testCase
160
161 def getTestCase(self):
162 """Returns the test case that has been run.
163 Used in the TestCaseManager to keep test case after execution.
164 @return The test case object.
165 """
166 return self.__testCase
167
168 def unloadTestCase(self):
169 """Clears the loaded test case."""
170 self.__testCase = None
171
172 def __doTest(self, testCaseNode, resultNode):
173 """Run the test received from the master.
174 The results (returned as an XML node) are appended to the resultNode.
175
176 @param testCaseNode The test case description in XML.
177 @param resultNode The result node returned (call by reference!).
178 """
179
180 try:
181 maxErrorMessagesPerTestFunction = int(testCaseNode.get("maxErrorMessagesPerTestFunction"))
182 except ValueError:
183 maxErrorMessagesPerTestFunction = 10000
184 try:
185 maxInfoMessagesPerTestFunction = int(testCaseNode.get("maxInfoMessagesPerTestFunction"))
186 except ValueError:
187 maxInfoMessagesPerTestFunction = 10000
188
189 # clear encoding cache for each test to prevent it from containing outdated encoding data
191
192 # start coverage right in front of loading, since some code parts are only
193 # traversed during the loading phase of a test case. Those
194 # are mainly function definitions etc.
195 try:
196 pythonCoverage = CodeCoverage.PythonCoverage(config=self._config, testCaseNode=testCaseNode)
197 except CodeCoverage.CoverageException as e:
198 pythonCoverage = None
199 mevis.MLAB.logError(e)
200
201 try:
202 bullseyeCoverage = CodeCoverage.BullseyeCoverage(config=self._config, testCaseNode=testCaseNode)
203 except CodeCoverage.CoverageException as e:
204 bullseyeCoverage = None
205 mevis.MLAB.logError(e)
206
207 self.__testCase = self.loadTestCase(testCaseNode)
208
209 # Run the test case only if it loaded correctly.
210 if self.__testCase:
211 # Do NOT run test, when status is TEST_STATUS_DO_NOT_TEST_MODULE. Only relevant for GenericTests
212 if not testCaseNode.get("status") == Utils.TEST_STATUS_DO_NOT_TEST_MODULE:
213 if pythonCoverage and pythonCoverage.isRunning():
214 # store the target file in a subNode so the HTML creation process knows there
215 # were coverage results for this test.
216 resultNode.set("pythonCoverage", pythonCoverage.getCoverageBinaryFilePath())
217
218 if bullseyeCoverage and bullseyeCoverage.isRunning():
219 # store the target file in a subNode so the HTML creation process knows there
220 # were coverage results for this test.
221 resultNode.set("bullseyeCoverage", bullseyeCoverage.getCoverageBinaryFilePath())
222
223 logHandler = LogHandler(self.__logfile)
224 logHandler.setErrorLimit(maxErrorMessagesPerTestFunction)
225 logHandler.setInfoLimit(maxInfoMessagesPerTestFunction)
226 TestHelper.getInstance().setLogHandler(logHandler)
227
229 self.__testCase.run(testCaseNode)
230
231 TestHelper.getInstance().unsetLogHandler()
232 logHandler.close()
233
234 resultNode.set("errorCode", "Ok")
235 # Append results to the resultNode.
236 resultNode.append(testCaseNode)
237 else:
238 resultNode.set("errorCode", "TestCaseError")
239 etree.SubElement(resultNode, "Error").text = "Unknown test case (%s)." % (testCaseNode.get("name"))
240
241 if pythonCoverage:
242 pythonCoverage.stop()
243
244 if bullseyeCoverage:
245 try:
246 bullseyeCoverage.stop()
247 except CodeCoverage.CoverageException as e:
248 mevis.MLAB.logError(e)
249
250 def __buildTestAgenda(self, testCfg, resultNode):
251 """Build a test agenda for the given request.
252 The agenda contains information which tests should be executed. The
253 information is contained in the returned XML structure.
254
255 @param testCfg The parameterization of the current test run.
256 @param resultNode The resulting agenda.
257 """
258
259 def ___addPackageInfoNode(rootNode):
260 packageInfoNode = etree.SubElement(rootNode, "PackageSortingInReport")
261 packageInfoNode.set(
262 "PackagesByNumberOfDependencies", ",".join(PackageSorter.byNumberOfDependencies.packages)
263 )
264 packageInfoNode.set(
265 "PackageGroupsByNumberOfDependencies", ",".join(PackageSorter.byNumberOfDependencies.packageGroups)
266 )
267
268 testRunNode = etree.Element("TestRun")
269
270 # An internal data structure with easier access than the XML structure.
271 self.__testCfg = {
272 "Packages": {"Tested": [], "Available": []},
273 "TestGroups": [],
274 "TestSuites": [],
275 "Modules": [],
276 }
277
278 # Consolidate the information on the packages available.
279 self.__verifyPackages(testCfg)
280
281 # Get information on the test groups selected.
282 for testGroupNode in testCfg.findall("TestGroups/TestGroup"):
283 self.__testCfg["TestGroups"].append(testGroupNode.get("name"))
284
285 # Add the test cases from given test suites to the TestCases node
286 for testSuiteNode in testCfg.findall("TestSuites/TestSuite"):
287 testSuite = testSuiteNode.get("name")
288 testCaseNames = mevis.MLABTestCaseDatabase.allTestCaseSuites().get(testSuite, {}).get("testCases", [])
289 testCasesNode = testCfg.find("TestCases")
290 for name in testCaseNames:
291 etree.SubElement(testCasesNode, "TestCase", {"name": name})
292
293 # Set system information.
294 testRunNode.set("platform", mevis.MLAB.systemId())
295 testRunNode.set("compiler", mevis.MLAB.compilerInfo())
296 # Set build information.
297 testRunNode.set("builddate", mevis.MLAB.dateOfBuildJob().date().toString("yyyy-MM-dd"))
298 testRunNode.set("version", mevis.MLAB.priv().variable("Version", False))
299
300 # Create nodes to store information on the test run.
301 infoNode = etree.SubElement(testRunNode, "Information")
302 testResultNode = etree.SubElement(testRunNode, "Results")
303 etree.SubElement(infoNode, "MissingTestCases")
304 etree.SubElement(infoNode, "TestCases")
305 etree.SubElement(infoNode, "Modules")
306 ___addPackageInfoNode(infoNode)
307
308 # Consolidate the information on the test cases that should be executed.
309 self.__verifyTestCaseList(testCfg, testRunNode)
310
311 # If no generic test cases are used then don't build information list for
312 # modules (this causes major performance on windows machines when storing
313 # the resulting xml).
314 for testCaseNode in infoNode.findall("./TestCases/TestCase"):
315 if testCaseNode.get("type") == "GenericTestCase":
316 # extend the XML structure and hook in all modules to test
317 self.__collectModulesToTest(testCfg)
318 self.__buildModuleInfo(infoNode.find("Modules"))
319 break
320
321 resultNode.set("errorCode", "Ok")
322 resultNode.append(testRunNode)
323 resultNode.append(testCfg)
324
325 self.__testCfg = None
326
327 def __buildTestCaseAgenda(self, requestNode, resultNode):
328 try:
329 parameterNode = requestNode.find("Parameters")
330 packagesToTest = parameterNode.get("packages", "").split(",")
331 modulesToTest = parameterNode.get("modules", "").split(",")
332 testCaseName = parameterNode.find("TestCase").get("name")
333 testResultsNode = etree.SubElement(resultNode, "Results")
334
335 logHandler = LogHandler(None)
336 logHandler.setErrorLimit(100)
337 logHandler.setInfoLimit(1000)
338 logHandler.allowNonFileBasedMessageLog()
339 TestHelper.getInstance().setLogHandler(logHandler)
340
341 testCase, status = self.__loadAndVerifyTestCase(
342 testCaseName, testResultsNode, packagesToTest, modulesToTest
343 )
344 testCaseAgenda = testCase.getTestCaseNode()
345 testCaseNode = testResultsNode.find("TestCase")
346 # Remove TestFunctions for GenericTests with status TEST_STATUS_DO_NOT_TEST_MODULE.
347 if testCaseNode is not None and testCaseNode.get("status", "") == str(Utils.TEST_STATUS_DO_NOT_TEST_MODULE):
348 functionListNode = testCaseAgenda.find("TestFunctions")
349 functionNodes = functionListNode.findall("Function")
350 for functionNode in functionNodes:
351 functionListNode.remove(functionNode)
352 resultNode.append(testCaseAgenda)
353 if status != "Ok":
354 etree.SubElement(resultNode, "Error").text = "Failed to load the test case."
355 errorMessages = etree.SubElement(resultNode, "Events")
356 for timeStamp, type, info in logHandler.getCachedMessageList():
357 errorNode = etree.SubElement(errorMessages, "Event")
358 errorNode.set("timestamp", timeStamp)
359 errorNode.set("type", type)
360 etree.SubElement(errorNode, "Message").text = info
361
362 TestHelper.getInstance().unsetLogHandler()
363 logHandler.close()
364
365 resultNode.set("errorCode", status)
366 except:
367 resultNode.set("errorCode", "Failed")
368 etree.SubElement(resultNode, "Error").text = traceback.format_exc()
369
370 def __verifyTestCaseList(self, testCfg, testRunNode):
371 """Verify the availability of all the given tests.
372 If no tests are given all available tests are returned.
373
374 @param testCfg The test run parameterization.
375 @param testRunNode The test run agenda.
376 """
377 # Get list of all available test cases.
378 availTestCaseList = []
379 for package in self.__testCfg["Packages"]["Tested"]:
380 availTestCaseList.extend(mevis.MLABTestCaseDatabase.allTestCasesForPackage(package))
382 availTestCaseList.extend(getCodeTestsByPackage().get(package, {}).keys())
383
384 # If no test cases were given use list of available ones.
385 testCaseListNode = testCfg.find("TestCases")
386 if len(testCaseListNode.findall("TestCase")) == 0:
387 for testCaseName in availTestCaseList:
388 etree.SubElement(testCaseListNode, "TestCase", name=testCaseName)
389
390 # Get the node to append information to.
391 testInfoNode = testRunNode.find("Information/TestCases")
392 testInfoNodeMissing = testRunNode.find("Information/MissingTestCases")
393
394 for testCaseNode in testCfg.findall("TestCases/TestCase"):
395 testCaseName = testCaseNode.get("name")
396 if testCaseName in availTestCaseList:
397 infoDict = self.__getTestCaseInfo(testCaseName)
398 # Verify test groups if necessary.
399 if not self.__verifyTestGroups(infoDict, self.__testCfg["TestGroups"]):
400 mevis.MLAB.logError(
401 "TestCase %s not in tested groups (%s)."
402 % (testCaseName, ", ".join(self.__testCfg["TestGroups"]))
403 )
404 testCaseNode.set("isNotInTestGroups", str(True))
405 else:
406 testCaseNode.set("type", infoDict["type"])
407 testInfoNode.append(testCaseNode)
408 testCaseNode.set("status", str(Utils.TEST_STATUS_OK))
409 else:
410 mevis.MLAB.logError("test case not found %s %s" % (testCaseName, availTestCaseList))
411 testInfoNodeMissing.append(testCaseNode)
412 testCaseNode.set("status", str(Utils.TEST_STATUS_LOAD_ERROR))
413
414 def __loadAndVerifyTestCase(self, testCaseName, testResultNode, packagesToTest, modulesToTest):
415 """Verify Test Case and add information on it."""
416 resolvedPackagesToTest = []
417 for package in packagesToTest:
418 pGroup, pName = package.split("/")
419 if pGroup == "*" and pName == "*":
420 for package in mevis.MLABPackageManager.packages():
421 resolvedPackagesToTest.append(package.packageIdentifier())
422 elif pName == "*":
423 for package in mevis.MLABPackageManager.packages():
424 if package.packageGroup() == pGroup:
425 resolvedPackagesToTest.append(package.packageIdentifier())
426 else:
427 resolvedPackagesToTest.append(package)
428 testCase, status = self.__verifyTestCase(
429 testCaseName, testResultNode, resolvedPackagesToTest, modulesToTest
430 )
431 return testCase, status
432
433 @staticmethod
434 def __getTestCaseInfo(testCaseName):
435 infoDict = mevis.MLABTestCaseDatabase.testCaseInfo(testCaseName)
436 if not infoDict:
437 codeTest = getCodeTest(testCaseName)
438 if codeTest is not None:
439 infoDict = codeTest.getInfoDict()
440 return infoDict
441
442 # -- def __verifyTestCase --------------------------------------------------------------------{{{-
443 def __verifyTestCase(self, testCaseName, testResultNode, packagesToTest, modulesToTest):
444 """Verify Test Case and add information on it.
445
446 @param testCaseName The name of the test case to be verified.
447 @param testResultNode The node to append verified test cases.
448 @return The XML info node and a status string.
449 """
450 infoDict = self.__getTestCaseInfo(testCaseName)
451
452 # Try to load the test case.
453 testType = infoDict["type"]
454
455 # if agenda test case is set from outside, use it
456 testCase = self.__agendaTestCase
457 if not testCase:
458 mevis.MLAB.log("Trying to load test case %s" % testCaseName)
459 # no test case set, try loading it instead
460 testCase = self.__loadTestCase(testCaseName, testType)
461 mevis.MLAB.log("Loading complete")
462
463 if testCase is None:
464 return None, "Failed"
465
466 # Add basic information for the actual testing.
467 if testType == "GenericTestCase":
468 modulesToTest, modulesNotToTest = testCase.getModulesToTest(modulesToTest, packagesToTest)
469 for moduleName in modulesToTest:
470 etree.SubElement(testResultNode, "TestCase", name=testCaseName, type=testType, module=moduleName)
471 for moduleName in modulesNotToTest:
472 etree.SubElement(
473 testResultNode,
474 "TestCase",
475 name=testCaseName,
476 type=testType,
477 module=moduleName,
478 status=str(Utils.TEST_STATUS_DO_NOT_TEST_MODULE),
479 )
480 else:
481 etree.SubElement(testResultNode, "TestCase", name=testCaseName, type=testType)
482
483 return testCase, ("Ok" if testCase.isValid() else "FAILED")
484
485 @staticmethod
486 def __verifyTestGroups(infoDict, testGroupList):
487 """Verify whether test case should be executed.
488 TestGroups can be used to specify groups of modules that should be tested.
489 There is one special group: if 'automatic' is given modules of the 'manual' group are not executed.
490 Tests in the testGroup 'disabled' are never executed.
491
492 @param testGroupList The list of test groups that should be tested.
493 @return Whether the test case should be executed.
494 """
495 testCaseGroupList = infoDict["testGroups"].lower() if "testGroups" in infoDict else ""
496 testCaseGroupList = testCaseGroupList.split()
497
498 if "disabled" in testCaseGroupList or ("needspublicsdk" in testCaseGroupList and not _isPublicSDK):
499 return False
500 testGroupList = [tg.lower() for tg in testGroupList]
501 if testGroupList:
502 if "automatic" in testGroupList:
503 if "manual" in testCaseGroupList:
504 return False
505 return True
506 for testGroup in testGroupList:
507 if testGroup in testCaseGroupList:
508 return True
509 return False
510 return True
511
512 def __verifyPackages(self, testCfg):
513 """Build up a list of packages and verify existence of given ones.
514 This method is given an XML node containing the names of all the packages
515 that should be searched for TestCases and those that should be available.
516 The wildcard "*" can be used to select either all available packages
517 ("*/*") or all packages of a selected group ("Standard/*").
518
519 @param testCfg The test run parameterization.
520 """
521 packageRoot = testCfg.find("Packages")
522
523 # First go over list and substitute wildcards and verify all given
524 # packages.
525 tPkgNode = packageRoot.find("Tested")
526 aPkgNode = packageRoot.find("Available")
527 iPkgNode = packageRoot.find("Ignored")
528 # if no ignored package is given,
529 # then self.__verifyPackageListNode() would ignore all packages
530 if len(iPkgNode) > 0:
531 self.__verifyPackageListNode(iPkgNode)
532 ignoredPackageIDs = set()
533 for ignoredPackage in iPkgNode:
534 ignoredPackageIDs.add(ignoredPackage.get("name"))
535
536 self.__verifyPackageListNode(tPkgNode, ignoredPackageIDs)
537 self.__verifyPackageListNode(aPkgNode, ignoredPackageIDs)
538 # Get list of verified packages.
539 tPkgSet = set()
540 for packageNode in tPkgNode.findall("Package"):
541 if packageNode.get("status") in ("Ok", "Added"):
542 tPkgSet.add(packageNode.get("name"))
543
544 aPkgSet = set()
545 for packageNode in aPkgNode.findall("Package"):
546 if packageNode.get("status") in ("Ok", "Added"):
547 aPkgSet.add(packageNode.get("name"))
548
549 # Save lists of packages sets for usage on slave side.
550 self.__testCfg["Packages"]["Tested"] = list(tPkgSet)
551 self.__testCfg["Packages"]["Available"] = list(tPkgSet.union(aPkgSet))
552
553 # Add all available packages for usage on master side.
554 for item in tPkgSet.difference(aPkgSet):
555 etree.SubElement(aPkgNode, "Package", name=item, status="Ok")
556
557 @staticmethod
558 def __verifyPackageListNode(packageListNode, ignoredPackageIDs=None):
559 """Substitute wildcards and verify package nodes.
560
561 @param packageListNode Node with package sub-nodes that contain information
562 on the packages.
563 """
564 # If no packages are given add everything!
565 if len(packageListNode) == 0:
566 etree.SubElement(packageListNode, "Package", name="*/*")
567
568 for packageNode in packageListNode:
569 packageID = packageNode.get("name")
570 try:
571 pGroup, pName = packageID.split("/")
572 except:
573 packageNode.set("status", "Invalid")
574 continue
575
576 ignoredPackageIDs = ignoredPackageIDs or []
577 # Substitute the wildcards.
578 if pGroup == "*":
579 if pName == "*":
580 for package in mevis.MLABPackageManager.packages():
581 packageID = package.packageIdentifier()
582 if not packageID in ignoredPackageIDs:
583 etree.SubElement(packageListNode, "Package", name=packageID, status="Added")
584 # Remove node as the wildcard has been executed.
585 packageNode.set("status", "Substituted")
586 else:
587 packageNode.set("status", "Failed")
588 elif pName == "*":
589 packageNode.set("status", "Substituted")
590 for package in mevis.MLABPackageManager.packagesByGroup(pGroup):
591 packageID = package.packageIdentifier()
592 if not packageID in ignoredPackageIDs:
593 etree.SubElement(packageListNode, "Package", name=packageID, status="Added")
594 else:
595 # If the given package exists add it to the package set otherwise
596 # remove the XML node.
597 if mevis.MLABPackageManager.packageByIdentifier(packageID):
598 packageNode.set("status", "Ok")
599 else:
600 packageNode.set("status", "Failed")
601
602 def __collectModulesToTest(self, testCfg):
603 """Get a list of all modules to test.
604 The list of all available modules is filtered using the settings the user made.
605 Those can either be a specific list of tests or a set of filters to apply on the list of modules.
606
607 @param testCfg The test run parameterization.
608 """
609 modulesNode = testCfg.find("Modules")
610
611 # Build up a dictionary with all specified filters.
612 filterDict = {}
613 for filterNode in modulesNode.findall("Filter"):
614 key, valueList = filterNode.text.split(":")
615 filterDict[key] = []
616 for value in valueList.split(","):
617 filterDict[key].append(value)
618
619 # Build up a list with all modules to be be taken into account.
620 availableModuleList = []
621 for packageName in self.__testCfg["Packages"]["Tested"]:
622 availableModuleList.extend(mevis.MLAB.allModulesForPackageIdentifier(packageName))
623
624 # If the user did not specify a list of modules use all available.
625 if len(modulesNode.findall("Module")) == 0:
626 for moduleName in availableModuleList:
627 etree.SubElement(modulesNode, "Module", name=moduleName)
628
629 # Find all modules to test.
630 for moduleNode in modulesNode.findall("Module"):
631 moduleName = moduleNode.get("name")
632 moduleInfo = mevis.MLAB.moduleInfo(moduleName)
633
634 if moduleInfo and moduleName in availableModuleList:
635 useModule = True
636 # Does module pass filters?
637 for f in filterDict:
638 if not f in moduleInfo or not [x for x in filterDict[f] if re.search(x, moduleInfo[f])]:
639 useModule = False
640 break
641 if useModule:
642 self.__testCfg["Modules"].append(moduleName)
643 moduleNode.set("status", str(Utils.TEST_STATUS_OK))
644 else:
645 moduleNode.set("isModuleFiltered", str(True))
646 else:
647 modulesNode.set("status", str(Utils.TEST_STATUS_ERROR))
648
649 def __buildModuleInfo(self, modulesInfoNode):
650 for moduleName in self.__testCfg["Modules"]:
651 moduleInfo = mevis.MLAB.moduleInfo(moduleName)
652 newModuleNode = etree.SubElement(modulesInfoNode, "Module", name=moduleName)
653 for key in moduleInfo:
654 value = moduleInfo[key]
655 etree.SubElement(newModuleNode, key, type=value.__class__.__name__).text = str(value)
656
657 @staticmethod
658 def __setPackageList(xmlNode, resultNode):
659 """Method to set the list of available packages given in the setting.
660
661 @param xmlNode An XML node containing 'Package' sub-nodes.
662 @param resultNode The result of the request.
663 """
664 packageList = []
665 for item in xmlNode.findall("Package"):
666 packageList.append(item.get("name"))
667 TestHelper.getInstance().setPackageList(packageList)
668 resultNode.set("errorCode", "Ok")
669
670 def runCommand(self, requestNode):
671 """Run a command given via the requestNode.
672
673 @param requestNode The request that contains the command and its parameters.
674 @return An XML node containing the results.
675 """
676 resultNode = etree.Element("Result")
677 if not TestHelper.getInstance().getGlobalContext():
678 command = "Quit"
679 mevis.MLAB.logWarning("Test case manager has been closed - aborting test execution")
680 else:
681 command = requestNode.get("type")
682 mevis.MLAB.log("Running command '%s'" % command)
683
684 try:
685 if command == "Quit":
686 resultNode.set("errorCode", "Ok")
687 self.__running = False
688 elif command == "DoTest":
689 testCaseNode = requestNode.find("TestCase")
690 if self.__com and testCaseNode.get("requestProgress") == "1":
692
693 self.__doTest(testCaseNode, resultNode)
694
695 if self.__com and testCaseNode.get("requestProgress") == "1":
696 self.setTestCaseListener(None)
697
698 elif command == "SetPackageList":
699 self.__setPackageList(requestNode.find("Packages"), resultNode)
700 elif command == "BuildTestAgenda":
701 self.__buildTestAgenda(requestNode.find("Configuration"), resultNode)
702 elif command == "BuildTestCaseAgenda":
703 self.__buildTestCaseAgenda(requestNode, resultNode)
704 else:
705 raise Exception("Unknown command: %s" % (command))
706 except:
707 resultNode.set("errorCode", "Exception")
708 etree.SubElement(resultNode, "Error").text = traceback.format_exc()
709 mevis.MLAB.log(traceback.format_exc())
710 self.__running = False
711
712 content = etree.tostring(resultNode).decode()
713 mevis.MLAB.log("Result content: %s%s" % (content[:150], " [...]" if len(content) > 150 else ""))
714 return resultNode
715
716 def run(self):
717 """The main method which handles all the request from the master."""
718 self.__com.connect()
719 self.__running = True
720 TestHelper.getInstance().runTestInSecureMode()
721 while self.__running:
722 request = self.__com.recv(20)
723 if request in ("", None):
724 mevis.MLAB.logError(self.__com.getLastErrorWithMessage()[1])
725 break
726
727 requestNode = etree.fromstring(request)
728 resultNode = self.runCommand(requestNode)
729
730 if not self.__com.send(etree.tostring(resultNode), 5):
731 mevis.MLAB.logError("Couldn't send result to request %s" % (request))
732 self.__running = False
733 TestHelper.getInstance().runTestInCurrentMlabInstance()
734 self.__com.disconnect()
The connection's slave.
Definition IPC.py:333
The class controlling a MeVisLab slave instance.
Definition Slave.py:71
__init__(self, cfgFile, context, offline=False)
Initializes the slave process.
Definition Slave.py:76
setAgendaTestCase(self, testCase)
Set the test case that is used for building the agenda/function list.
Definition Slave.py:153
__verifyTestCaseList(self, testCfg, testRunNode)
Definition Slave.py:370
__buildTestAgenda(self, testCfg, resultNode)
Definition Slave.py:250
__doTest(self, testCaseNode, resultNode)
Definition Slave.py:172
__verifyPackages(self, testCfg)
Definition Slave.py:512
__loadAndVerifyTestCase(self, testCaseName, testResultNode, packagesToTest, modulesToTest)
Definition Slave.py:414
runCommand(self, requestNode)
Run a command given via the requestNode.
Definition Slave.py:670
getTestCase(self)
Returns the test case that has been run.
Definition Slave.py:161
__loadTestCase(testCaseName, testCaseType, moduleName=None)
Definition Slave.py:131
loadTestCase(self, testCaseNode)
Load the given test case.
Definition Slave.py:119
setTestCaseListener(self, listener)
Definition Slave.py:116
run(self)
The main method which handles all the request from the master.
Definition Slave.py:716
__buildTestCaseAgenda(self, requestNode, resultNode)
Definition Slave.py:327
unloadTestCase(self)
Clears the loaded test case.
Definition Slave.py:168
__getTestCaseInfo(testCaseName)
Definition Slave.py:434
__verifyPackageListNode(packageListNode, ignoredPackageIDs=None)
Definition Slave.py:558
__collectModulesToTest(self, testCfg)
Definition Slave.py:602
__buildModuleInfo(self, modulesInfoNode)
Definition Slave.py:649
__setPackageList(xmlNode, resultNode)
Definition Slave.py:658
setIsInsideTestCaseManager(self, isInsideTestCaseManager)
Definition Slave.py:113
__verifyTestGroups(infoDict, testGroupList)
Definition Slave.py:486
__verifyTestCase(self, testCaseName, testResultNode, packagesToTest, modulesToTest)
Definition Slave.py:443
startTestCaseFunction(self, testType, testCase, testFunction)
Definition Slave.py:49
endTestCaseFunction(self, status, duration)
Definition Slave.py:63
TestCase superclass for functional test cases.
TestCase superclass for generic testing.
clearEncodingCache()
Definition Base.py:47