#!/usr/bin/python from collections import defaultdict from os import listdir from os.path import abspath, dirname, isdir, isfile, join, realpath, relpath, splitext import re from subprocess import Popen, PIPE import sys # Runs the tests. WREN_DIR = dirname(realpath(__file__)) TEST_DIR = join(WREN_DIR, 'test') if sys.platform == 'win32': WREN_APP = join(WREN_DIR, 'Debug', 'wren.exe') if not isfile(WREN_DIR): WREN_APP = join(WREN_DIR, 'Release', 'wren.exe') if not isfile(WREN_APP): sys.exit('Cannot find wren.exe!') elif sys.platform.startswith('linux'): WREN_APP = join(WREN_DIR, '1', 'out', 'Debug', 'wren') if not isfile(WREN_APP): WREN_APP = join(WREN_DIR, '1', 'out', 'Release', 'wren') if not isfile(WREN_APP): sys.exit('Cannot find wren!') elif sys.platform.startswith('darwin'): WREN_APP = join(WREN_DIR, 'build', 'Debug', 'wren') if not isfile(WREN_APP): WREN_APP = join(WREN_DIR, 'build', 'Release', 'wren') if not isfile(WREN_APP): sys.exit('Cannot find wren!') else: sys.exit('System not supported!') EXPECT_PATTERN = re.compile(r'// expect: (.*)') EXPECT_ERROR_PATTERN = re.compile(r'// expect error') ERROR_PATTERN = re.compile(r'\[Line (\d+)\] Error ') SKIP_PATTERN = re.compile(r'// skip: (.*)') NONTEST_PATTERN = re.compile(r'// nontest') if sys.platform == 'win32': class color: GREEN = '' RED = '' DEFAULT = '' PINK = '' YELLOW = '' else: class color: GREEN = '\033[32m' RED = '\033[31m' DEFAULT = '\033[0m' PINK = '\033[91m' YELLOW = '\033[33m' passed = 0 failed = 0 skipped = defaultdict(int) num_skipped = 0; def walk(dir, callback): """ Walks [dir], and executes [callback] on each file. """ dir = abspath(dir) for file in [file for file in listdir(dir) if not file in [".",".."]]: nfile = join(dir, file) if isdir(nfile): walk(nfile, callback) else: callback(nfile) def print_line(line=None): # Erase the line. print '\033[2K', # Move the cursor to the beginning. print '\r', if line: print line, sys.stdout.flush() def run_test(path): global passed global failed global skipped global num_skipped if (splitext(path)[1] != '.wren'): return # Check if we are just running a subset of the tests. if len(sys.argv) == 2: this_test = relpath(path, join(WREN_DIR, 'test')) if not this_test.startswith(sys.argv[1]): return # Make a nice short path relative to the working directory. path = relpath(path) # Read the test and parse out the expectations. expect_output = [] expect_error = [] expect_return = 0 print_line('Passed: ' + color.GREEN + str(passed) + color.DEFAULT + ' Failed: ' + color.RED + str(failed) + color.DEFAULT + ' Skipped: ' + color.YELLOW + str(num_skipped) + color.DEFAULT) line_num = 1 with open(path, 'r') as file: for line in file: match = EXPECT_PATTERN.search(line) if match: expect_output.append((match.group(1), line_num)) match = EXPECT_ERROR_PATTERN.search(line) if match: expect_error.append(line_num) # If we expect compile errors in the test, it should return # exit code 1. expect_return = 1 match = SKIP_PATTERN.search(line) if match: num_skipped += 1 skipped[match.group(1)] += 1 return match = NONTEST_PATTERN.search(line) if match: # Not a test file at all, so ignore it. return line_num += 1 # Invoke wren and run the test. proc = Popen([WREN_APP, path], stdout=PIPE, stderr=PIPE) (out, err) = proc.communicate() (out, err) = out.replace('\r\n', '\n'), err.replace('\r\n', '\n') fails = [] # Validate that no unexpected errors occurred. if expect_return == 1 and err != '': lines = err.split('\n') while len(lines) > 0: line = lines.pop(0) match = ERROR_PATTERN.search(line) if match: if float(match.group(1)) not in expect_error: fails.append('Unexpected error:') fails.append(line) elif line != '': fails.append('Unexpected output on stderr:') fails.append(line) else: for line in expect_error: fails.append('Expected error on line ' + str(line) + ' and got none.') # Validate the exit code. if proc.returncode != expect_return: fails.append('Expected return code {0} and got {1}.' .format(expect_return, proc.returncode)) else: # Validate the output. expect_index = 0 # Remove the trailing last empty line. out_lines = out.split('\n') if out_lines[-1] == '': del out_lines[-1] for line in out_lines: if expect_index >= len(expect_output): fails.append('Got output "{0}" when none was expected.'.format(line)) elif expect_output[expect_index][0] != line: fails.append('Expected output "{0}" on line {1} and got "{2}".'. format(expect_output[expect_index][0], expect_output[expect_index][1], line)) expect_index += 1 while expect_index < len(expect_output): fails.append('Missing expected output "{0}" on line {1}.'. format(expect_output[expect_index][0], expect_output[expect_index][1])) expect_index += 1 # Display the results. if len(fails) == 0: passed += 1 #print color.GREEN + 'PASS' + color.DEFAULT + ': ' + path else: failed += 1 print_line(color.RED + 'FAIL' + color.DEFAULT + ': ' + path) print for fail in fails: print ' ', color.PINK + fail + color.DEFAULT print walk(TEST_DIR, run_test) print_line() if failed == 0: print 'All ' + color.GREEN + str(passed) + color.DEFAULT + ' tests passed.' else: print (color.GREEN + str(passed) + color.DEFAULT + ' tests passed. ' + color.RED + str(failed) + color.DEFAULT + ' tests failed.') for key in sorted(skipped.keys()): print ('Skipped ' + color.YELLOW + str(skipped[key]) + color.DEFAULT + ' tests: ' + key)