run_suite.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #!/usr/bin/env python
  2. import os
  3. import re
  4. import sys
  5. from run_utils import Err, log, execute, getPlatformVersion, isColorEnabled, TempEnvDir
  6. from run_long import LONG_TESTS_DEBUG_VALGRIND, longTestFilter
  7. class TestSuite(object):
  8. def __init__(self, options, cache, id):
  9. self.options = options
  10. self.cache = cache
  11. self.nameprefix = "opencv_" + self.options.mode + "_"
  12. self.tests = self.cache.gatherTests(self.nameprefix + "*", self.isTest)
  13. self.id = id
  14. def getOS(self):
  15. return getPlatformVersion() or self.cache.getOS()
  16. def getLogName(self, app):
  17. return self.getAlias(app) + '_' + str(self.id) + '.xml'
  18. def listTests(self, short=False, main=False):
  19. if len(self.tests) == 0:
  20. raise Err("No tests found")
  21. for t in self.tests:
  22. if short:
  23. t = self.getAlias(t)
  24. if not main or self.cache.isMainModule(t):
  25. log.info("%s", t)
  26. def getAlias(self, fname):
  27. return sorted(self.getAliases(fname), key=len)[0]
  28. def getAliases(self, fname):
  29. def getCuts(fname, prefix):
  30. # filename w/o extension (opencv_test_core)
  31. noext = re.sub(r"\.(exe|apk)$", '', fname)
  32. # filename w/o prefix (core.exe)
  33. nopref = fname
  34. if fname.startswith(prefix):
  35. nopref = fname[len(prefix):]
  36. # filename w/o prefix and extension (core)
  37. noprefext = noext
  38. if noext.startswith(prefix):
  39. noprefext = noext[len(prefix):]
  40. return noext, nopref, noprefext
  41. # input is full path ('/home/.../bin/opencv_test_core') or 'java'
  42. res = [fname]
  43. fname = os.path.basename(fname)
  44. res.append(fname) # filename (opencv_test_core.exe)
  45. for s in getCuts(fname, self.nameprefix):
  46. res.append(s)
  47. if self.cache.build_type == "Debug" and "Visual Studio" in self.cache.cmake_generator:
  48. res.append(re.sub(r"d$", '', s)) # MSVC debug config, remove 'd' suffix
  49. log.debug("Aliases: %s", set(res))
  50. return set(res)
  51. def getTest(self, name):
  52. # return stored test name by provided alias
  53. for t in self.tests:
  54. if name in self.getAliases(t):
  55. return t
  56. raise Err("Can not find test: %s", name)
  57. def getTestList(self, white, black):
  58. res = [t for t in white or self.tests if self.getAlias(t) not in black]
  59. if len(res) == 0:
  60. raise Err("No tests found")
  61. return set(res)
  62. def isTest(self, fullpath):
  63. if fullpath in ['java', 'python2', 'python3']:
  64. return self.options.mode == 'test'
  65. if not os.path.isfile(fullpath):
  66. return False
  67. if self.cache.getOS() == "nt" and not fullpath.endswith(".exe"):
  68. return False
  69. return os.access(fullpath, os.X_OK)
  70. def wrapCommand(self, module, cmd, env):
  71. if self.options.valgrind:
  72. res = ['valgrind']
  73. supp = self.options.valgrind_supp or []
  74. for f in supp:
  75. if os.path.isfile(f):
  76. res.append("--suppressions=%s" % f)
  77. else:
  78. print("WARNING: Valgrind suppression file is missing, SKIP: %s" % f)
  79. res.extend(self.options.valgrind_opt)
  80. has_gtest_filter = next((True for x in cmd if x.startswith('--gtest_filter=')), False)
  81. return res + cmd + ([longTestFilter(LONG_TESTS_DEBUG_VALGRIND, module)] if not has_gtest_filter else [])
  82. elif self.options.qemu:
  83. import shlex
  84. res = shlex.split(self.options.qemu)
  85. for (name, value) in [entry for entry in os.environ.items() if entry[0].startswith('OPENCV') and not entry[0] in env]:
  86. res += ['-E', '"{}={}"'.format(name, value)]
  87. for (name, value) in env.items():
  88. res += ['-E', '"{}={}"'.format(name, value)]
  89. return res + ['--'] + cmd
  90. return cmd
  91. def tryCommand(self, cmd, workingDir):
  92. try:
  93. if 0 == execute(cmd, cwd=workingDir):
  94. return True
  95. except:
  96. pass
  97. return False
  98. def runTest(self, module, path, logfile, workingDir, args=[]):
  99. args = args[:]
  100. exe = os.path.abspath(path)
  101. if module == "java":
  102. cmd = [self.cache.ant_executable, "-Dopencv.build.type=%s" % self.cache.build_type]
  103. if self.options.package:
  104. cmd += ["-Dopencv.test.package=%s" % self.options.package]
  105. if self.options.java_test_exclude:
  106. cmd += ["-Dopencv.test.exclude=%s" % self.options.java_test_exclude]
  107. cmd += ["buildAndTest"]
  108. ret = execute(cmd, cwd=self.cache.java_test_dir)
  109. return None, ret
  110. elif module in ['python2', 'python3']:
  111. executable = os.getenv('OPENCV_PYTHON_BINARY', None)
  112. if executable is None or module == 'python{}'.format(sys.version_info[0]):
  113. executable = sys.executable
  114. if executable is None:
  115. executable = path
  116. if not self.tryCommand([executable, '--version'], workingDir):
  117. executable = 'python'
  118. cmd = [executable, self.cache.opencv_home + '/modules/python/test/test.py', '--repo', self.cache.opencv_home, '-v'] + args
  119. module_suffix = '' if 'Visual Studio' not in self.cache.cmake_generator else '/' + self.cache.build_type
  120. env = {}
  121. env['PYTHONPATH'] = self.cache.opencv_build + '/lib' + module_suffix + os.pathsep + os.getenv('PYTHONPATH', '')
  122. if self.cache.getOS() == 'nt':
  123. env['PATH'] = self.cache.opencv_build + '/bin' + module_suffix + os.pathsep + os.getenv('PATH', '')
  124. else:
  125. env['LD_LIBRARY_PATH'] = self.cache.opencv_build + '/bin' + os.pathsep + os.getenv('LD_LIBRARY_PATH', '')
  126. ret = execute(cmd, cwd=workingDir, env=env)
  127. return None, ret
  128. else:
  129. if isColorEnabled(args):
  130. args.append("--gtest_color=yes")
  131. env = {}
  132. if not self.options.valgrind and self.options.trace:
  133. env['OPENCV_TRACE'] = '1'
  134. env['OPENCV_TRACE_LOCATION'] = 'OpenCVTrace-{}'.format(self.getLogBaseName(exe))
  135. env['OPENCV_TRACE_SYNC_OPENCL'] = '1'
  136. tempDir = TempEnvDir('OPENCV_TEMP_PATH', "__opencv_temp.")
  137. tempDir.init()
  138. cmd = self.wrapCommand(module, [exe] + args, env)
  139. log.warning("Run: %s" % " ".join(cmd))
  140. ret = execute(cmd, cwd=workingDir, env=env)
  141. try:
  142. if not self.options.valgrind and self.options.trace and int(self.options.trace_dump) >= 0:
  143. import trace_profiler
  144. trace = trace_profiler.Trace(env['OPENCV_TRACE_LOCATION']+'.txt')
  145. trace.process()
  146. trace.dump(max_entries=int(self.options.trace_dump))
  147. except:
  148. import traceback
  149. traceback.print_exc()
  150. pass
  151. tempDir.clean()
  152. hostlogpath = os.path.join(workingDir, logfile)
  153. if os.path.isfile(hostlogpath):
  154. return hostlogpath, ret
  155. return None, ret
  156. def runTests(self, tests, black, workingDir, args=[]):
  157. args = args[:]
  158. logs = []
  159. test_list = self.getTestList(tests, black)
  160. if len(test_list) != 1:
  161. args = [a for a in args if not a.startswith("--gtest_output=")]
  162. ret = 0
  163. for test in test_list:
  164. more_args = []
  165. exe = self.getTest(test)
  166. if exe in ["java", "python2", "python3"]:
  167. logname = None
  168. else:
  169. userlog = [a for a in args if a.startswith("--gtest_output=")]
  170. if len(userlog) == 0:
  171. logname = self.getLogName(exe)
  172. more_args.append("--gtest_output=xml:" + logname)
  173. else:
  174. logname = userlog[0][userlog[0].find(":")+1:]
  175. log.debug("Running the test: %s (%s) ==> %s in %s", exe, args + more_args, logname, workingDir)
  176. if self.options.dry_run:
  177. logfile, r = None, 0
  178. else:
  179. logfile, r = self.runTest(test, exe, logname, workingDir, args + more_args)
  180. log.debug("Test returned: %s ==> %s", r, logfile)
  181. if r != 0:
  182. ret = r
  183. if logfile:
  184. logs.append(os.path.relpath(logfile, workingDir))
  185. return logs, ret
  186. if __name__ == "__main__":
  187. log.error("This is utility file, please execute run.py script")