Merge pull request #9252 from jbms:fix/tiff-in-memory
[platform/upstream/opencv.git] / modules / ts / misc / run_suite.py
1 #!/usr/bin/env python
2
3 import datetime
4 from run_utils import *
5 from run_long import LONG_TESTS_DEBUG_VALGRIND, longTestFilter
6
7 timestamp = datetime.datetime.now()
8
9 class TestSuite(object):
10     def __init__(self, options, cache):
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
16     def getOS(self):
17         return getPlatformVersion() or self.cache.getOS()
18
19     def getHardware(self):
20         res = []
21         if self.cache.getArch() in ["x86", "x64"] and self.cache.withCuda():
22             res.append("CUDA")
23         return res
24
25     def getLogBaseName(self, app):
26         global timestamp
27         app = self.getAlias(app)
28         rev = self.cache.getGitVersion()
29         if isinstance(timestamp, datetime.datetime):
30             timestamp = timestamp.strftime("%Y%m%d-%H%M%S")
31         if self.options.longname:
32             small_pieces = [self.getOS(), self.cache.getArch()] + self.cache.getDependencies() + self.getHardware() + [self.cache.getSIMDFeatures()]
33             big_pieces = [app, str(rev), timestamp, "_".join([p for p in small_pieces if p])]
34             l = "__".join(big_pieces)
35         else:
36             pieces = [app, self.cache.getOS(), self.cache.getArch()] + self.getHardware() + [rev, timestamp]
37             lname = "_".join([p for p in pieces if p])
38             lname = re.sub(r'[\(\)\[\]\s,]', '_', lname)
39             l = re.sub(r'_+', '_', lname)
40         return l
41
42     def getLogName(self, app):
43         return self.getLogBaseName(app) + '.xml'
44
45     def listTests(self, short = False, main = False):
46         if len(self.tests) == 0:
47             raise Err("No tests found")
48         for t in self.tests:
49             if short:
50                 t = self.getAlias(t)
51             if not main or self.cache.isMainModule(t):
52                 log.info("%s", t)
53
54     def getAlias(self, fname):
55         return sorted(self.getAliases(fname), key = len)[0]
56
57     def getAliases(self, fname):
58         def getCuts(fname, prefix):
59             # filename w/o extension (opencv_test_core)
60             noext = re.sub(r"\.(exe|apk)$", '', fname)
61             # filename w/o prefix (core.exe)
62             nopref = fname
63             if fname.startswith(prefix):
64                 nopref = fname[len(prefix):]
65             # filename w/o prefix and extension (core)
66             noprefext = noext
67             if noext.startswith(prefix):
68                 noprefext = noext[len(prefix):]
69             return noext, nopref, noprefext
70         # input is full path ('/home/.../bin/opencv_test_core') or 'java'
71         res = [fname]
72         fname = os.path.basename(fname)
73         res.append(fname) # filename (opencv_test_core.exe)
74         for s in getCuts(fname, self.nameprefix):
75             res.append(s)
76             if self.cache.build_type == "Debug" and "Visual Studio" in self.cache.cmake_generator:
77                 res.append(re.sub(r"d$", '', s)) # MSVC debug config, remove 'd' suffix
78         log.debug("Aliases: %s", set(res))
79         return set(res)
80
81     def getTest(self, name):
82         # return stored test name by provided alias
83         for t in self.tests:
84             if name in self.getAliases(t):
85                 return t
86         raise Err("Can not find test: %s", name)
87
88     def getTestList(self, white, black):
89         res = [t for t in white or self.tests if self.getAlias(t) not in black]
90         if len(res) == 0:
91             raise Err("No tests found")
92         return set(res)
93
94     def isTest(self, fullpath):
95         if fullpath in ['java', 'python2', 'python3']:
96             return self.options.mode == 'test'
97         if not os.path.isfile(fullpath):
98             return False
99         if self.cache.getOS() == "nt" and not fullpath.endswith(".exe"):
100             return False
101         return os.access(fullpath, os.X_OK)
102
103     def wrapInValgrind(self, cmd = []):
104         if self.options.valgrind:
105             res = ['valgrind']
106             supp = self.options.valgrind_supp or []
107             for f in supp:
108                 if os.path.isfile(f):
109                     res.append("--suppressions=%s" % f)
110                 else:
111                     print("WARNING: Valgrind suppression file is missing, SKIP: %s" % f)
112             res.extend(self.options.valgrind_opt)
113             has_gtest_filter = next((True for x in cmd if x.startswith('--gtest_filter=')), False)
114             return res + cmd + ([longTestFilter(LONG_TESTS_DEBUG_VALGRIND)] if not has_gtest_filter else [])
115         return cmd
116
117     def tryCommand(self, cmd):
118         try:
119             if 0 == execute(cmd, cwd = workingDir):
120                 return True
121         except:
122             pass
123         return False
124
125     def runTest(self, path, logfile, workingDir, args = []):
126         args = args[:]
127         exe = os.path.abspath(path)
128         if path == "java":
129             cmd = [self.cache.ant_executable, "-Dopencv.build.type=%s" % self.cache.build_type, "buildAndTest"]
130             ret = execute(cmd, cwd = self.cache.java_test_binary_dir + "/.build")
131             return None, ret
132         elif path in ['python2', 'python3']:
133             executable = os.getenv('OPENCV_PYTHON_BINARY', None)
134             if executable is None:
135                 executable = path
136                 if not self.tryCommand([executable, '--version']):
137                     executable = 'python'
138             cmd = [executable, self.cache.opencv_home + '/modules/python/test/test.py', '--repo', self.cache.opencv_home, '-v'] + args
139             module_suffix = '' if not 'Visual Studio' in self.cache.cmake_generator else '/' + self.cache.build_type
140             env = {}
141             env['PYTHONPATH'] = self.cache.opencv_build + '/lib' + module_suffix + os.pathsep + os.getenv('PYTHONPATH', '')
142             if self.cache.getOS() == 'nt':
143                 env['PATH'] = self.cache.opencv_build + '/bin' + module_suffix + os.pathsep + os.getenv('PATH', '')
144             else:
145                 env['LD_LIBRARY_PATH'] = self.cache.opencv_build + '/bin' + os.pathsep + os.getenv('LD_LIBRARY_PATH', '')
146             ret = execute(cmd, cwd = workingDir, env = env)
147             return None, ret
148         else:
149             if isColorEnabled(args):
150                 args.append("--gtest_color=yes")
151             cmd = self.wrapInValgrind([exe] + args)
152             env = {}
153             if not self.options.valgrind and self.options.trace:
154                 env['OPENCV_TRACE'] = '1'
155                 env['OPENCV_TRACE_LOCATION'] = 'OpenCVTrace-{}'.format(self.getLogBaseName(exe))
156                 env['OPENCV_TRACE_SYNC_OPENCL'] = '1'
157             tempDir = TempEnvDir('OPENCV_TEMP_PATH', "__opencv_temp.")
158             tempDir.init()
159             log.warning("Run: %s" % " ".join(cmd))
160             ret = execute(cmd, cwd = workingDir, env=env)
161             try:
162                 if not self.options.valgrind and self.options.trace and int(self.options.trace_dump) >= 0:
163                     import trace_profiler
164                     trace = trace_profiler.Trace(env['OPENCV_TRACE_LOCATION']+'.txt')
165                     trace.process()
166                     trace.dump(max_entries=int(self.options.trace_dump))
167             except:
168                 import traceback
169                 traceback.print_exc()
170                 pass
171             tempDir.clean()
172             hostlogpath = os.path.join(workingDir, logfile)
173             if os.path.isfile(hostlogpath):
174                 return hostlogpath, ret
175             return None, ret
176
177     def checkPrerequisites(self):
178         if self.cache.getArch() == "x64" and hostmachine == "x86":
179             raise Err("Target architecture is incompatible with current platform")
180
181     def runTests(self, tests, black, workingDir, args = []):
182         self.checkPrerequisites()
183         args = args[:]
184         logs = []
185         test_list = self.getTestList(tests, black)
186         if len(test_list) != 1:
187             args = [a for a in args if not a.startswith("--gtest_output=")]
188         ret = 0
189         for test in test_list:
190             more_args = []
191             exe = self.getTest(test)
192
193             if exe in ["java", "python2", "python3"]:
194                 logname = None
195             else:
196                 userlog = [a for a in args if a.startswith("--gtest_output=")]
197                 if len(userlog) == 0:
198                     logname = self.getLogName(exe)
199                     more_args.append("--gtest_output=xml:" + logname)
200                 else:
201                     logname = userlog[0][userlog[0].find(":")+1:]
202
203             log.debug("Running the test: %s (%s) ==> %s in %s", exe, args + more_args, logname, workingDir)
204             if self.options.dry_run:
205                 logfile, r = None, 0
206             else:
207                 logfile, r = self.runTest(exe, logname, workingDir, args + more_args)
208             log.debug("Test returned: %s ==> %s", r, logfile)
209
210             if r != 0:
211                 ret = r
212             if logfile:
213                 logs.append(os.path.relpath(logfile, workingDir))
214         return logs, ret
215
216 #===================================================================================================
217
218 if __name__ == "__main__":
219     log.error("This is utility file, please execute run.py script")