run_suite.py 8.6 KB

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