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