Home | History | Annotate | Download | only in tests
      1 #!/usr/bin/python
      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   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 
    171 def 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.  Enter multiple -v to get more verbose.\n'
    181         ) % (sys.argv[0]),
    182   return
    183 
    184 
    185 def 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 
    235 if __name__ == '__main__':
    236   sys.exit(main())
    237