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