3 from __future__ import print_function
4 import argparse, glob, itertools, re, shutil, os, sys
6 config_reg = re.compile('.*\/\/\s*(?P<name>\S+):\s*(?P<value>.*)$')
9 def __init__(self,args,test):
12 self.update = args.updateref
13 self.config = self.get_config()
14 self.test_name = '[%s]: %s' % (self.test,self.config['objective'][0])
15 self.test_id = self.test.split('_')[0]
17 self.test_out = self.args.inputdir+'/'+self.test_id
19 self.test_out = self.args.outputdir+'/test_output_'+self.test_id
22 def compare_ok(self,got_file,expected_file,name):
23 if not os.path.isfile(got_file):
24 return (True,'%s absent' % got_file)
25 elif not os.path.isfile(expected_file):
26 return (True,'%s absent' % expected_file)
28 diff = os.popen('diff -b -w -u %s %s' % (got_file,expected_file)).read()
29 if diff and not diff.startswith("No differences"):
30 return (True,'Difference between generated output and reference:\n%s' % diff)
35 with open(self.args.inputdir+'/'+self.test,'r') as f:
36 for line in f.readlines():
37 m = config_reg.match(line)
40 value = m.group('value')
42 value = value.replace('$INPUTDIR',self.args.inputdir)
43 #print('key=%s value=%s' % (key,value))
44 config.setdefault(key, []).append(value)
47 def prepare_test(self):
48 # prepare test environment
49 shutil.rmtree(self.test_out,ignore_errors=True)
50 os.mkdir(self.test_out)
51 shutil.copy(self.args.inputdir+'/Doxyfile',self.test_out)
52 with open(self.test_out+'/Doxyfile','a') as f:
53 print('INPUT=%s/%s' % (self.args.inputdir,self.test), file=f)
54 print('STRIP_FROM_PATH=%s' % self.args.inputdir, file=f)
55 print('XML_OUTPUT=%s/out' % self.test_out, file=f)
56 print('EXAMPLE_PATH=%s' % self.args.inputdir, file=f)
57 if 'config' in self.config:
58 for option in self.config['config']:
61 if 'check' not in self.config or not self.config['check']:
62 print('Test doesn\'t specify any files to check')
66 if (sys.platform == 'win32'):
70 if os.system('%s %s/Doxyfile %s' % (self.args.doxygen,self.test_out, redir))!=0:
71 print('Error: failed to run %s on %s/Doxyfile' % (self.args.doxygen,self.test_out));
74 # update the reference data for this test
75 def update_test(self,testmgr):
76 print('Updating reference for %s' % self.test_name)
78 if 'check' in self.config:
79 for check in self.config['check']:
80 check_file='%s/out/%s' % (self.test_out,check)
81 # check if the file we need to check is actually generated
82 if not os.path.isfile(check_file):
83 print('Non-existing file %s after \'check:\' statement' % check_file)
85 # convert output to canonical form
86 data = os.popen('%s --format --noblanks --nowarning %s' % (self.args.xmllint,check_file)).read()
89 data = re.sub(r'xsd" version="[0-9.-]+"','xsd" version=""',data).rstrip('\n')
91 print('Failed to run %s on the doxygen output file %s' % (self.args.xmllint,self.test_out))
93 out_file='%s/%s' % (self.test_out,check)
94 with open(out_file,'w') as f:
96 shutil.rmtree(self.test_out+'/out',ignore_errors=True)
97 os.remove(self.test_out+'/Doxyfile')
99 # check the relevant files of a doxygen run with the reference material
100 def perform_test(self,testmgr):
101 # look for files to check against the reference
102 if 'check' in self.config:
103 for check in self.config['check']:
104 check_file='%s/out/%s' % (self.test_out,check)
105 # check if the file we need to check is actually generated
106 if not os.path.isfile(check_file):
107 testmgr.ok(False,self.test_name,msg='Non-existing file %s after \'check:\' statement' % check_file)
109 # convert output to canonical form
110 data = os.popen('%s --format --noblanks --nowarning %s' % (self.args.xmllint,check_file)).read()
113 data = re.sub(r'xsd" version="[0-9.-]+"','xsd" version=""',data).rstrip('\n')
115 testmgr.ok(False,self.test_name,msg='Failed to run %s on the doxygen output file %s' % (self.args.xmllint,self.test_out))
117 out_file='%s/%s' % (self.test_out,check)
118 with open(out_file,'w') as f:
120 ref_file='%s/%s/%s' % (self.args.inputdir,self.test_id,check)
121 (failed,msg) = self.compare_ok(out_file,ref_file,self.test_name)
123 testmgr.ok(False,self.test_name,msg)
125 shutil.rmtree(self.test_out,ignore_errors=True)
126 testmgr.ok(True,self.test_name)
128 def run(self,testmgr):
130 self.update_test(testmgr)
132 self.perform_test(testmgr)
135 def __init__(self,args,tests):
138 self.num_tests = len(tests)
141 print('1..%d' % self.num_tests)
143 def ok(self,result,test_name,msg='Ok'):
145 print('ok %s - %s' % (self.count,test_name))
146 self.passed = self.passed + 1
148 print('not ok %s - %s' % (self.count,test_name))
149 print('-------------------------------------')
151 print('-------------------------------------')
152 self.count = self.count + 1
155 if self.passed==self.num_tests:
156 print('All tests passed!')
158 print('%d out of %s tests failed' % (self.num_tests-self.passed,self.num_tests))
159 return 0 if self.passed==self.num_tests else 1
161 def perform_tests(self):
162 for test in self.tests:
163 tester = Tester(self.args,test)
165 return 0 if self.args.updateref else self.result()
169 parser = argparse.ArgumentParser(description='run doxygen tests')
170 parser.add_argument('--updateref',help='update the reference data for a test',action="store_true")
171 parser.add_argument('--doxygen',nargs='?',default='doxygen',help='path/name of the doxygen executable')
172 parser.add_argument('--xmllint',nargs='?',default='xmllint',help='path/name of the xmllint executable')
173 parser.add_argument('--id',nargs='+',dest='ids',action='append',type=int,help='id of the test to perform')
174 parser.add_argument('--all',help='perform all tests',action="store_true")
175 parser.add_argument('--inputdir',nargs='?',default='.',help='input directory containing the tests')
176 parser.add_argument('--outputdir',nargs='?',default='.',help='output directory to write the doxygen output to')
177 args = parser.parse_args()
180 if (not args.updateref is None) and (args.ids is None) and (args.all is None):
181 parser.error('--updateref requires either --id or --all')
183 starting_directory = os.getcwd()
184 os.chdir(args.inputdir)
185 # find the tests to run
186 if args.ids: # test ids are given by user
188 for id in list(itertools.chain.from_iterable(args.ids)):
189 tests.append(glob.glob('%s_*'%id))
190 tests.append(glob.glob('0%s_*'%id))
191 tests.append(glob.glob('00%s_*'%id))
192 tests = list(itertools.chain.from_iterable(tests))
193 else: # find all tests
194 tests = glob.glob('[0-9][0-9][0-9]_*')
195 os.chdir(starting_directory)
197 # create test manager to run the tests
198 testManager = TestManager(args,tests)
199 sys.exit(testManager.perform_tests())
201 if __name__ == '__main__':