16 from mevis
import MLAB, MLABPackageManager, MLABTestCaseDatabase
30 match = re.search(
r"\$\(MLAB_([^_)]+)_([^_)]+)\)", executable)
32 package = MLABPackageManager.packageByIdentifier(match.group(1) +
"/" + match.group(2))
34 executable = executable.replace(match.group(0), package.binariesPath())
35 test =
CodeTest(executable = context.expandFilename(executable))
36 test.injectTestFunctions(context)
38 pathToBuildSystemScripts = MLABPackageManager.getPathInPackage(
'MeVis/BuildSystem',
'BuildTools/Scripts')
39 if os.path.isdir(pathToBuildSystemScripts):
40 if not pathToBuildSystemScripts
in sys.path:
41 sys.path.insert(0, pathToBuildSystemScripts)
42 from MeVisPython
import MeVisPython
43 del pathToBuildSystemScripts
45 def _parseGoogleTestOutput(result, allowRestart=False):
46 colorOk =
'color: rgb(78,154,6);'
47 colorFailed =
'color: rgb(204,0,0);'
48 commonStyle =
'font-family: monospace;'
50 statusFormat =
'<div style="%s"><span style="%s">%%s</span>%%s</div>'
51 errorFormat = statusFormat % (commonStyle, colorFailed)
52 infoFormat = statusFormat % (commonStyle, colorOk)
54 statusRegExp = re.compile(
"(?P<status>\\[\\s*\\S+\\s*\\])(?P<message>.*)")
56 hasNotifiedStdErrOutput =
False
63 lowerStderrMsg = result[
'stderr'].lower()
64 stdErrContainsError = (lowerStderrMsg.find(
"error") >=0)
or (lowerStderrMsg.find(
"failed") >=0)
66 needsRestartWithoutSanitizer =
False
67 if stdErrContainsError:
70 if lowerStderrMsg.find(
"sanitizer check failed:") >=0
and \
71 lowerStderrMsg.find(
"src/libsanitizer/asan/asan_malloc_linux.cc") >= 0
and \
72 lowerStderrMsg.find(
"allocated_for_dlsym") >= 0:
73 needsRestartWithoutSanitizer = allowRestart
75 if not needsRestartWithoutSanitizer:
77 EXPECT_EQ(result[
"status"], 0, msg=
'The test status is not 0.', logOnSuccess=
False)
78 EXPECT_TRUE(result[
"ok"], msg=
'The test run failed.', logOnSuccess=
False)
79 ASSERT_TRUE(
"stdout" in result, msg=
'The test output does not exists.', logOnSuccess=
False)
81 for outChannel
in [
'stdout',
'stderr']:
82 for line
in result[outChannel].splitlines():
84 if outChannel==
'stderr' and not hasNotifiedStdErrOutput:
85 if stdErrContainsError:
86 errorHTML((
'Note: The stderr channel output contained "error" or "failed" which is handled as test failure.'))
87 infoHTML(
'The test printed the following messages to stderr channel:')
88 hasNotifiedStdErrOutput =
True
90 m = statusRegExp.match(line)
92 status = m.group(
'status').replace(
' ',
' ').replace(
'\t',
' '*4)
93 message = m.group(
'message').replace(
' ',
' ').replace(
'\t',
' '*4)
94 if 'FAILED' in status:
95 errorHTML(errorFormat % (status, message))
97 infoHTML(infoFormat % (status, message))
99 line = line.replace(
' ',
' ').replace(
'\t',
' '*4)
100 infoHTML((
'<div style="%s">' + line +
'</div>') % commonStyle)
102 return needsRestartWithoutSanitizer
123 def __init__(self, cmakeFile = None, executable = None):
131 if cmakeFile
is not None:
134 def _getUniqueTestCaseName(self, name):
137 while MLABTestCaseDatabase.testCaseInfo(uniqueName):
143 uniqueName = name + str(i)
149 package = MLABPackageManager.findPackageContainingPath(self.
cmakeFilecmakeFile)
150 self.
__infoDict__infoDict = {
'package': package.packageIdentifier(),
154 'type':
'CodeTestTestCase',
155 'scriptFile':
'ScriptFileNotAvailable'}
165 MLAB.logError(
"Could not locate CodeTest executable: " + self.
namename)
167 if not os.path.exists(self.
executableexecutable):
169 exeSuffix =
".exe" if MLAB.isWindows()
else ""
170 if os.path.exists(self.
executableexecutable + exeSuffix):
173 elif os.path.exists(self.
executableexecutable +
"_d" + exeSuffix):
178 def __executableExists(executable):
179 return executable
and os.path.exists(executable)
188 arguments = [
'--build',
'.',
'--config', (
'Debug' if MLAB.isDebug()
else 'Release'),
'--target', self.
namename]
189 result = MLAB.runCommandStdInOut(executable, arguments, self.
_getBuildRoot_getBuildRoot())
194 MLAB.showCritical(self.
_getError_getError(result))
196 if result[
'ok'] !=
True:
197 MLAB.logError(self.
_getError_getError(result))
198 return result[
'ok'] ==
True
200 def _getError(self, result):
202 stderr = result.get(
'stderr')
203 stdout = result.get(
'stdout')
204 if stdout: message.append(stdout.encode(
'latin1').decode(
'UTF-8'))
205 if stderr: message.append(stderr.encode(
'latin1').decode(
'UTF-8'))
206 if not stdout
and not stderr:
207 message.append(
'An unknown error occurred')
208 return '\n'.join(message)
210 def _parseCMakeFile(self, cmakeFile):
211 testRegex = re.compile(
r'^(?!#)\s*mlab_add_test\(\s*(\w*)')
213 with open(cmakeFile,
'r')
as f:
215 match = testRegex.match(line)
216 if match
and match.group(1):
217 target = match.group(1)
221 def _getBuildRoot(self):
222 if 'MLAB_BUILD' in os.environ:
223 buildRoot = os.environ[
'MLAB_BUILD']
225 buildRoot = os.path.normpath(os.path.join(MLABPackageManager.packageByIdentifier(
'MeVisLab/IDE').binariesPath(),
"..",
".."))
228 def _findExecutables(self):
231 testArguments = [
"-V",
"-R", self.
namename,
"-C", (
"Debug" if MLAB.isDebug()
else "Release"),
"--show-only=json-v1"]
232 result = MLAB.runCommandStdInOut(command, testArguments, self.
_getBuildRoot_getBuildRoot())
233 if result[
'ok'] ==
True:
234 testDetails = json.loads(result[
'stdout'])
235 if 'tests' in testDetails
and len(testDetails[
'tests'])>0
and 'command' in testDetails[
'tests'][0]
and len(testDetails[
'tests'][0][
'command']) > 0:
236 executable = testDetails[
'tests'][0][
'command'][0]
244 result = MLAB.runCommandStdInOut(executable, [
"--gtest_list_tests"], os.path.dirname(executable))
245 if result[
'ok'] ==
True:
248 def __getUniqueFunctionName(self, name):
253 uniqueName = name + str(i)
257 def _parseTestFunctionsFromOutput(self, output):
258 identifierRegExp = re.compile(
r'^[\S]+$')
264 for line
in output.splitlines():
265 commentIdx = line.find(
'#')
267 line = line[:commentIdx].rstrip(
' ')
268 if not line.startswith(
' '):
269 name = line.rstrip(
'.')
270 if identifierRegExp.match(name):
271 sourceName =
'GROUP%03d_%s' % (groupIdx, name.replace(
'/',
'_'))
277 if identifierRegExp.match(name):
280 if uniqueName.startswith(
'DISABLED_'):
281 uniqueName = uniqueName[len(
'DISABLED_'):]
284 sourceName =
'TEST%03d_%s' % (functionIdx, uniqueName.replace(
'/',
'_'))
286 sourceName =
'DISABLED_' + sourceName
288 group.addFunction(function)
297 globalSymbols = globals()
298 localSymbols= locals()
301 for function
in group.getFunctions():
305 eval(compile(testCode,
'<string>',
'exec'), globalSymbols, localSymbols)
307 def _groupCode(self, group):
309 for f
in group.getFunctions():
310 functions.append(
"'" + f.sourceName +
"'")
311 return '''def %(sourceName)s():
312 return %(functions)s,
313 ctx.setScriptVariable(%(sourceName)s.__name__, %(sourceName)s)
314 ''' % dict(sourceName = group.sourceName, functions =
",".join(functions))
316 def _hasSanitizerSuppression(self, sanitizerPrefix, envVar, compilerVersion):
317 mlabRootPath = MLAB.variable(
'MLAB_MeVis_BuildSystem')
318 suppressionFile = mlabRootPath +
'/BuildTools/linux/' + sanitizerPrefix +
u'SanitizerSuppressions_gcc' + compilerVersion +
'.supp'
320 return os.path.isfile(suppressionFile)
and os.path.exists(suppressionFile)
322 def _determineSanitizerSetUpCode(self):
324 compilerInfo = MLAB.compilerInfo()
325 compilerVersion =
'4'
326 if compilerInfo.find(
u'GCC_64_7') >= 0:
327 compilerVersion =
u'7'
328 elif compilerInfo.find(
u'GCC_64_9') >= 0:
329 compilerVersion =
u'9'
330 elif compilerInfo.find(
u'') >= 0:
331 compilerVersion =
u'5'
333 hasSuppressions = self.
_hasSanitizerSuppression_hasSanitizerSuppression(
'Leak',
'LSAN_OPTIONS', compilerVersion)
and \
339 MLAB.log(u"Running in sanitizer environment of gcc%(compilerVer)s ('asan' and 'ubsan' libs with LD_PRELOAD as well as suppression files).")
340 mlabRootPath = MLAB.variable("MLAB_MeVis_BuildSystem")
341 sanitizerEnvVarIntro = "suppressions=" + mlabRootPath + os.sep
342 os.environ["LSAN_OPTIONS"] = sanitizerEnvVarIntro + u"BuildTools/linux/LeakSanitizerSuppressions_gcc%(compilerVer)s.supp"
343 os.environ["ASAN_OPTIONS"] = sanitizerEnvVarIntro + u"BuildTools/linux/AddressSanitizerSuppressions_gcc%(compilerVer)s.supp"
344 os.environ["UBSAN_OPTIONS"] = sanitizerEnvVarIntro + u"BuildTools/linux/UBSanitizerSuppressions_gcc%(compilerVer)s.supp"
345 os.environ["TSAN_OPTIONS"] = sanitizerEnvVarIntro + u"linux/ThreadSanitizerSuppressions_gcc%(compilerVer)s.supp"
346 os.environ["LD_PRELOAD"] = u"/usr/lib/gcc/x86_64-linux-gnu/%(compilerVer)s/libasan.so:/usr/lib/gcc/x86_64-linux-gnu/%(compilerVer)s/libubsan.so"
347 ''' % dict(compilerVer = compilerVersion)
350 MLAB.log(u"Could not find (all) sanitizer suppression files: not running test in gcc sanitizer environment.")
355 def _functionCode(self, group, function):
357 exePath = exePath.replace(
'\\',
'\\\\')
359 return '''def %(sourceName)s():
360 executable = "%(executable)s"
361 for package in MLABPackageManager.packages():
362 os.environ[package.packageEnvVariableName()] = package.scriptsPath()
363 %(sanitizerSetUpCode)s
364 result = MLAB.runCommandStdInOut(executable, ['--gtest_also_run_disabled_tests', '--gtest_filter=%(groupName)s.%(functionName)s'], os.path.dirname(executable))
365 from TestSupport.CodeTest import _parseGoogleTestOutput
366 needsRestartWithoutSanitizer = _parseGoogleTestOutput(result, True)
367 if needsRestartWithoutSanitizer:
368 os.environ["LD_PRELOAD"] = ""
369 MLAB.log(u"Sanitizer is incompatible with unittest. Restarting test without sanitzer preload.")
370 result = MLAB.runCommandStdInOut(executable, ['--gtest_also_run_disabled_tests', '--gtest_filter=%(groupName)s.%(functionName)s'], os.path.dirname(executable))
371 _parseGoogleTestOutput(result)
372 ctx.setScriptVariable(%(sourceName)s.__name__, %(sourceName)s)
373 ''' % dict(sourceName = function.sourceName, executable = exePath, sanitizerSetUpCode = saniCode, groupName = group.name, functionName = function.name)
def __init__(self, cmakeFile=None, executable=None)
def _parseCMakeFile(self, cmakeFile)
def __getUniqueFunctionName(self, name)
def _getError(self, result)
def getTestFunctionGroups(self)
def _findExecutables(self)
def _determineSanitizerSetUpCode(self)
def __executableExists(executable)
def _groupCode(self, group)
def _hasSanitizerSuppression(self, sanitizerPrefix, envVar, compilerVersion)
def existsExecutable(self)
def loadTestFunctions(self)
def _parseTestFunctionsFromOutput(self, output)
def _functionCode(self, group, function)
def injectTestFunctions(self, context)
def __init__(self, name, sourceName)
def addFunction(self, function)
def __init__(self, name, sourceName)
def inject(executable, context)
Package to provide logging functions.
def errorHTML(message, type='', depth=0)
Put an error to the log while interpreting HTML.
def infoHTML(message, type='', depth=0)
Put an info message to the log while interpreting HTML.
Adds GoogleTest like methods.
def EXPECT_EQ(expected, actual, msg=None, logOnSuccess=None)
Expect given values to be equal.
def EXPECT_TRUE(expr, msg=None, logOnSuccess=None)
Expect given expression to evaluate to true.
def ASSERT_TRUE(expr, msg=None, logOnSuccess=None)
Throw exception if given expression does not evaluate to true.