Synopsis - Cross-Reference
File: /tests/QMTest/synopsis_database.py1#!/usr/bin/env python 2# 3# Copyright (C) 2003 Stefan Seefeld 4# All rights reserved. 5# Licensed to the public under the terms of the GNU LGPL (>= 2), 6# see the file COPYING for details. 7# 8 9from qm.fields import TextField 10from qm.test import database 11from qm.test.database import TestDescriptor, ResourceDescriptor 12from qm.test.database import NoSuchTestError, NoSuchSuiteError, NoSuchResourceError 13from explicit_suite import ExplicitSuite 14from qm.test.suite import Suite 15 16import os, string, dircache 17 18class Database(database.Database): 19 """The Database stores the synopsis tests.""" 20 21 arguments = [TextField(name="srcdir")] 22 23 def __init__(self, path, arguments): 24 25 arguments["modifiable"] = "false" 26 database.Database.__init__(self, path, arguments) 27 if os.name == 'nt': 28 self.srcdir = os.popen('cygpath -w "%s"'%self.srcdir).read()[:-1] 29 30 def get_src_path(self, id): 31 return self.srcdir + os.sep + id.replace('.', os.sep) 32 33 def get_build_path(self, id): 34 return id.replace('.', os.sep) 35 36 def get_file_tests(self, path, ext = ''): 37 """tests are file names without extension""" 38 return [t[0] 39 for t in [os.path.splitext(x) for x in dircache.listdir(path)] 40 if t[0] != '' and (not ext or t[1] == ext)] 41 42 def get_dir_tests(self, id, script): 43 """tests are directories if <script> exists""" 44 return [t for t in dircache.listdir(self.get_src_path(id)) 45 if os.path.isfile(os.path.join(self.get_build_path(id), t, script))] 46 47 def get_dir_suites(self, id): 48 """by default all directories are suites""" 49 path = self.get_src_path(id) 50 return filter(lambda x: os.path.isdir(os.path.join(path, x)), 51 dircache.listdir(path)) 52 53 def GetSubdirectories(self, dir): 54 55 if not os.path.isdir(self.get_src_path(dir)): 56 raise NoSuchSuiteError, dir 57 58 suites = [] 59 60 if not dir: 61 62 return ['Cxx', 'Parsers', 'Processors'] 63 64 elif dir.startswith('Processors.Linker'): 65 66 # just make sure this isn't a test itself... 67 if os.path.exists(os.path.join(self.get_build_path(dir), 'synopsis.py')): 68 raise NoSuchSuiteError, dir 69 70 tests = self.get_dir_tests(dir, 'synopsis.py') 71 suites = [s for s in self.get_dir_suites(dir) if s not in tests] 72 73 elif dir.startswith('Cxx-API'): 74 # if 'src' exists, it contains the tests 75 path = os.path.join(self.get_src_path(dir), 'src') 76 if not os.path.isdir(path): 77 suites = self.get_dir_suites(dir) 78 79 elif dir.startswith('Cxx'): 80 if not os.path.isdir(os.path.join(self.get_src_path(dir), 'input')): 81 suites = self.get_dir_suites(dir) 82 suites.remove('src') 83 84 else: 85 if not os.path.isdir(os.path.join(self.get_src_path(dir), 'input')): 86 suites = self.get_dir_suites(dir) 87 88 # ignore accidental inclusion of false tests / suites 89 if '.svn' in suites: suites.remove('.svn') 90 if 'autom4te.cache' in suites: suites.remove('autom4te.cache') 91 92 return suites 93 94 95 def GetTestIds(self, dir = "", scan_subdirs = 1): 96 """Return all test IDs that are part of the given suite.""" 97 98 if not os.path.isdir(self.get_src_path(dir)): 99 raise NoSuchSuiteError, dir 100 101 tests = [] 102 103 if dir.startswith('Processors.Linker'): 104 105 # just make sure this isn't a test itself... 106 if os.path.exists(os.path.join(self.get_build_path(dir), 'synopsis.py')): 107 raise NoSuchSuiteError, dir 108 109 tests = self.get_dir_tests(dir, 'synopsis.py') 110 111 elif dir.startswith('Cxx-API'): 112 # if 'src' exists, it contains the tests 113 path = os.path.join(self.get_src_path(dir), 'src') 114 if os.path.isdir(path): 115 tests = self.get_file_tests(path, '.cc') 116 117 elif dir.startswith('Cxx'): 118 if os.path.isdir(os.path.join(self.get_src_path(dir), 'input')): 119 tests = self.get_file_tests(os.path.join(self.get_src_path(dir), 120 'input'), 121 '.cc') 122 123 else: 124 if os.path.isdir(os.path.join(self.get_src_path(dir), 'input')): 125 tests = self.get_file_tests(os.path.join(self.get_src_path(dir), 126 'input')) 127 # ignore accidental inclusion of false tests / suites 128 if '.svn' in tests: tests.remove('.svn') 129 130 if dir: 131 tests = ['%s.%s'%(dir, t) for t in tests] 132 133 if scan_subdirs: 134 for d in self.GetSubdirectories(dir): 135 d = self.JoinLabels(dir, d) 136 tests.extend(self.GetTestIds(d, scan_subdirs)) 137 138 return tests 139 140 141 def GetResourceIds(self, directory="", scan_subdirs=1): 142 143 if directory == '' and scan_subdirs or directory == 'Cxx': 144 return ['Cxx.Lexer', 145 'Cxx.Parser', 146 'Cxx.Encoding', 147 'Cxx.ConstEvaluator', 148 'Cxx.SymbolLookup', 149 'Cxx.TypeAnalysis'] 150 else: 151 return [] 152 153 def GetResource(self, id): 154 """Construct a resource for the given id. 155 For now the only resources provided are Cxx test applets.""" 156 157 if not id.startswith('Cxx'): raise NoSuchResourceError(id) 158 159 parameters = {} 160 161 suite = id.split('.', 1)[1] 162 if suite not in ['Lexer', 'Parser', 'Encoding', 163 'ConstEvaluator', 'SymbolLookup', 'TypeAnalysis']: 164 raise NoSuchResourceError(id) 165 166 parameters['exe'] = os.path.normpath('bin/%s'%suite) 167 168 return ResourceDescriptor(self, id, 'synopsis_test.CxxResource', parameters) 169 170 def GetSuite(self, id): 171 """Construct a suite for the given id. 172 For suites there is a general mapping from ids to paths: 173 replace the period by os.sep to get the path in the build tree, 174 and prefix that with self.srcdir to get the path in the source tree.""" 175 176 test_ids = self.GetTestIds(id) 177 suite_ids = self.GetSuiteIds(id) 178 179 arguments = {'test_ids' : test_ids, 'suite_ids' : suite_ids} 180 181 return ExplicitSuite(arguments, 182 qmtest_database = self, 183 qmtest_id = id) 184 185 def GetTest(self, id): 186 """Create a test for the given id. Tests are grouped by type, 187 i.e. specific suites contain specific test classes.""" 188 189 if not id: raise NoSuchTestError, id 190 191 if id.startswith('Processors.Linker'): return self.make_linker_test(id) 192 elif id.startswith('Cxx-API'): return self.make_api_test(id) 193 elif id.startswith('Cxx'): return self.make_opencxx_test(id) 194 else: return self.make_processor_test(id) 195 196 def make_processor_test(self, id): 197 """A test id 'a.b.c' corresponds to an input file 198 'a/b/input/c.<ext>. Create a ProcessorTest if that 199 input file exists, and throw NoSuchTestError otherwise.""" 200 201 components = id.split('.') 202 dirname = os.path.join(*[self.srcdir] + components[:-1]) 203 204 input = os.path.join(dirname, 'input', components[-1]) 205 206 if components[:-1] == ['Parsers', 'IDL']: input += '.idl' 207 elif components[:-1] == ['Parsers', 'Python']: input += '.py' 208 elif components[:-1] == ['Parsers', 'C']: input += '.c' 209 else: input += '.cc' 210 if not os.path.isfile(input): raise NoSuchTestError, id 211 212 output = os.path.join(*components[:-1] + ['output', components[-1] + '.xml']) 213 expected = os.path.join(dirname, 'expected', components[-1] + '.xml') 214 if components[0] == 'Processors' and components[1] != 'Linker': 215 synopsis = os.path.join('Processors', 'synopsis.py') 216 else: 217 synopsis = os.path.join(*components[:-1] + ['synopsis.py']) 218 219 parameters = {} 220 parameters['srcdir'] = self.srcdir 221 parameters['input'] = [input] 222 parameters['output'] = output 223 parameters['expected'] = expected 224 parameters['synopsis'] = synopsis 225 226 return TestDescriptor(self, id, 'synopsis_test.ProcessorTest', parameters) 227 228 def make_linker_test(self, id): 229 """A test id 'a.b.c' corresponds to an input directory 230 'a/b/c/input containing files to be linked together. 231 Create a ProcessorTest if that directory exists, 232 and throw NoSuchTestError otherwise.""" 233 234 path = self.get_src_path(id) 235 if not os.path.isdir(path): raise NoSuchTestError, id 236 237 dirname = os.path.join(path, 'input') 238 239 parameters = {} 240 parameters['srcdir'] = self.srcdir 241 parameters['input'] = [os.path.join(dirname, x) for x in dircache.listdir(dirname) if x != '.svn'] 242 parameters['output'] = os.path.join(*id.split('.') + ['output.xml']) 243 parameters['expected'] = os.path.join(path, 'expected.xml') 244 parameters['synopsis'] = os.path.join(*id.split('.') + ['synopsis.py']) 245 246 return TestDescriptor(self, id, 'synopsis_test.ProcessorTest', parameters) 247 248 def make_api_test(self, id): 249 """A test id 'a.b.c' corresponds to an input file 250 'a/b/src/c.cc. Create an APITest if that 251 input file exists, and throw NoSuchTestError otherwise.""" 252 253 components = id.split('.') 254 dirname = os.path.join(*[self.srcdir] + components[:-1]) 255 256 if not os.path.exists(os.path.join(dirname, 'src', components[-1]) + '.cc'): 257 raise NoSuchTestError, id 258 259 parameters = {} 260 parameters['CXX'] = self.CXX 261 parameters['CPPFLAGS'] = self.CPPFLAGS 262 parameters['CXXFLAGS'] = self.CXXFLAGS 263 parameters['LDFLAGS'] = self.LDFLAGS 264 parameters['LIBS'] = self.LIBS 265 parameters['src'] = os.path.join(dirname, 'src', components[-1]) + '.cc' 266 parameters['exe'] = os.path.join(*components[:-1] + ['bin', components[-1]]) 267 parameters['expected'] = os.path.join(dirname, 'expected', 268 components[-1] + '.out') 269 270 return TestDescriptor(self, id, 'synopsis_test.APITest', parameters) 271 272 def make_opencxx_test(self, id): 273 """A test id 'a.b.c' corresponds to an input file 274 'a/b/input/c.<ext>. Create an CxxTest if that 275 input file exists, and throw NoSuchTestError otherwise.""" 276 277 base, suite, test = id.split('.') 278 dirname = os.path.join(*[self.srcdir] + [base, suite]) 279 280 input = os.path.join(dirname, 'input', test) + '.cc' 281 output = os.path.join(*[base, suite, 'output', test + '.out']) 282 283 if not os.path.isfile(input): raise NoSuchTestError, id 284 285 expected = os.path.join(dirname, 'expected', test + '.out') 286 287 parameters = {} 288 parameters['input'] = input 289 parameters['output'] = output 290 parameters['expected'] = expected 291 292 parameters['resources'] = ['Cxx.%s'%suite] 293 parameters['applet'] = 'Cxx/bin/%s'%suite 294 295 return TestDescriptor(self, id, 'synopsis_test.CxxTest', parameters) 296