1 #!/usr/bin/python2.4 2 # 3 # Copyright 2010-2012 Google Inc. All Rights Reserved. 4 5 """Renderscript Compiler Test. 6 7 Runs subdirectories of tests for the Renderscript compiler. 8 """ 9 10 import filecmp 11 import glob 12 import os 13 import re 14 import shutil 15 import subprocess 16 import sys 17 18 __author__ = 'Android' 19 20 21 class Options(object): 22 def __init__(self): 23 return 24 verbose = 0 25 cleanup = 1 26 updateCTS = 0 27 28 29 def CompareFiles(actual, expect): 30 """Compares actual and expect for equality.""" 31 if not os.path.isfile(actual): 32 if Options.verbose: 33 print 'Could not find %s' % actual 34 return False 35 if not os.path.isfile(expect): 36 if Options.verbose: 37 print 'Could not find %s' % expect 38 return False 39 40 return filecmp.cmp(actual, expect, False) 41 42 43 def UpdateFiles(src, dst): 44 """Update dst if it is different from src.""" 45 if not CompareFiles(src, dst): 46 print 'Copying from %s to %s' % (src, dst) 47 shutil.copyfile(src, dst) 48 49 50 def GetCommandLineArgs(filename): 51 """Extracts command line arguments from first comment line in a file.""" 52 f = open(filename, 'r') 53 line = f.readline() 54 if line[0] == '/' and line [1] == '/': 55 return line[2:].strip() 56 else: 57 return '' 58 59 60 def ExecTest(dirname): 61 """Executes an llvm-rs-cc test from dirname.""" 62 passed = True 63 64 if Options.verbose != 0: 65 print 'Testing %s' % dirname 66 67 os.chdir(dirname) 68 stdout_file = open('stdout.txt', 'w+') 69 stderr_file = open('stderr.txt', 'w+') 70 71 cmd_string = ('../../../../../out/host/linux-x86/bin/llvm-rs-cc ' 72 '-o tmp/ -p tmp/ ' 73 '-MD ' 74 '-I ../../../../../frameworks/rs/scriptc/ ' 75 '-I ../../../../../external/clang/lib/Headers/') 76 base_args = cmd_string.split() 77 rs_files = glob.glob('*.rs') 78 rs_files.sort() 79 80 # Extra command line arguments can be placed as // comments at the start of 81 # any .rs file. We automatically bundle up all of these extra args and invoke 82 # llvm-rs-cc with them. 83 extra_args_str = '' 84 for rs_file in rs_files: 85 extra_args_str += GetCommandLineArgs(rs_file) 86 extra_args = extra_args_str.split() 87 88 args = base_args + extra_args + rs_files 89 90 if Options.verbose > 1: 91 print 'Executing:', 92 for arg in args: 93 print arg, 94 print 95 96 # Execute the command and check the resulting shell return value. 97 # All tests that are expected to FAIL have directory names that 98 # start with 'F_'. Other tests that are expected to PASS have 99 # directory names that start with 'P_'. 100 ret = 0 101 try: 102 ret = subprocess.call(args, stdout=stdout_file, stderr=stderr_file) 103 except: 104 passed = False 105 106 stdout_file.flush() 107 stderr_file.flush() 108 109 if Options.verbose > 1: 110 stdout_file.seek(0) 111 stderr_file.seek(0) 112 for line in stdout_file: 113 print 'STDOUT>', line, 114 for line in stderr_file: 115 print 'STDERR>', line, 116 117 stdout_file.close() 118 stderr_file.close() 119 120 if dirname[0:2] == 'F_': 121 if ret == 0: 122 passed = False 123 if Options.verbose: 124 print 'Command passed on invalid input' 125 elif dirname[0:2] == 'P_': 126 if ret != 0: 127 passed = False 128 if Options.verbose: 129 print 'Command failed on valid input' 130 else: 131 passed = (ret == 0) 132 if Options.verbose: 133 print 'Test Directory name should start with an F or a P' 134 135 if not CompareFiles('stdout.txt', 'stdout.txt.expect'): 136 passed = False 137 if Options.verbose: 138 print 'stdout is different' 139 if not CompareFiles('stderr.txt', 'stderr.txt.expect'): 140 passed = False 141 if Options.verbose: 142 print 'stderr is different' 143 144 if Options.updateCTS: 145 # Copy resulting files to appropriate CTS directory (if different). 146 if passed and glob.glob('IN_CTS'): 147 cts_path = '../../../../../cts/' 148 cts_res_raw_path = cts_path + 'tests/res/raw/' 149 cts_src_path = cts_path + 'tests/tests/renderscript/src/' 150 for bc_src in glob.glob('tmp/*.bc'): 151 bc_dst = re.sub('tmp\/', cts_res_raw_path, bc_src, 1) 152 UpdateFiles(bc_src, bc_dst) 153 for java_src in glob.glob('tmp/android/renderscript/cts/*.java'): 154 java_dst = re.sub('tmp\/', cts_src_path, java_src, 1) 155 UpdateFiles(java_src, java_dst) 156 157 if Options.cleanup: 158 try: 159 os.remove('stdout.txt') 160 os.remove('stderr.txt') 161 shutil.rmtree('tmp/') 162 except: 163 pass 164 165 os.chdir('..') 166 return passed 167 168 169 def Usage(): 170 """Print out usage information.""" 171 print ('Usage: %s [OPTION]... [TESTNAME]...' 172 'Renderscript Compiler Test Harness\n' 173 'Runs TESTNAMEs (all tests by default)\n' 174 'Available Options:\n' 175 ' -h, --help Help message\n' 176 ' -n, --no-cleanup Don\'t clean up after running tests\n' 177 ' -u, --update-cts Update CTS test versions\n' 178 ' -v, --verbose Verbose output\n' 179 ) % (sys.argv[0]), 180 return 181 182 183 def main(): 184 passed = 0 185 failed = 0 186 files = [] 187 failed_tests = [] 188 189 for arg in sys.argv[1:]: 190 if arg in ('-h', '--help'): 191 Usage() 192 return 0 193 elif arg in ('-n', '--no-cleanup'): 194 Options.cleanup = 0 195 elif arg in ('-u', '--update-cts'): 196 Options.updateCTS = 1 197 elif arg in ('-v', '--verbose'): 198 Options.verbose += 1 199 else: 200 # Test list to run 201 if os.path.isdir(arg): 202 files.append(arg) 203 else: 204 print >> sys.stderr, 'Invalid test or option: %s' % arg 205 return 1 206 207 if not files: 208 tmp_files = os.listdir('.') 209 # Only run tests that are known to PASS or FAIL 210 # Disabled tests can be marked D_ and invoked explicitly 211 for f in tmp_files: 212 if os.path.isdir(f) and (f[0:2] == 'F_' or f[0:2] == 'P_'): 213 files.append(f) 214 215 for f in files: 216 if os.path.isdir(f): 217 if ExecTest(f): 218 passed += 1 219 else: 220 failed += 1 221 failed_tests.append(f) 222 223 print 'Tests Passed: %d\n' % passed, 224 print 'Tests Failed: %d\n' % failed, 225 if failed: 226 print 'Failures:', 227 for t in failed_tests: 228 print t, 229 230 return failed != 0 231 232 233 if __name__ == '__main__': 234 sys.exit(main()) 235