1#! /usr/bin/env python 2 3# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 4# This program is distributed with GNU Go, a Go program. # 5# # 6# Write gnugo@gnu.org or see http://www.gnu.org/software/gnugo/ # 7# for more information. # 8# # 9# Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 and 2006 # 10# by the Free Software Foundation. # 11# # 12# This program is free software; you can redistribute it and/or # 13# modify it under the terms of the GNU General Public License # 14# as published by the Free Software Foundation - version 3 # 15# or (at your option) any later version. # 16# # 17# This program is distributed in the hope that it will be # 18# useful, but WITHOUT ANY WARRANTY; without even the implied # 19# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR # 20# PURPOSE. See the GNU General Public License in file COPYING # 21# for more details. # 22# # 23# You should have received a copy of the GNU General Public # 24# License along with this program; if not, write to the Free # 25# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # 26# Boston, MA 02111, USA. # 27# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 28 29import string 30import sys, getopt 31import re 32 33help_string = """ 34Usage: 35breakage2tst.py [--pike] <BREAKAGE_FILE 36 This creates a command line invoking regress.pike to run all tes 37 cases that appear as unexpected PASS or FAIL in BREAKAGE_FILE. 38breakage2tst.py [--pike] --update <BREAKAGE_FILE 39 This changes all .tst files so that the expected results match 40 the behaviour of the version that produced BREAKAGE_FILE. 41In both cases, it needs to be run from the regression test directory. 42""" 43 44# This prints out the list of tests from testfile in the format 45# <tstfile>:number 46def write_tests(tstfilename, tests): 47 for number, expected in tests: 48 print "%s:%d" % (tstfilename, number), 49 50 51def toggled_result(resultline, expected): 52 if (re.search(r"\]$", resultline)): 53 if (not expected == 0): 54 print "Result line doesn't match 'unexpected FAIL':", 55 print resultline 56 sys.exit(2) 57 return (re.sub(r"\]$", "]*", resultline)) 58 elif (re.search(r"\]\*$", resultline)): 59 if (not expected == 1): 60 print "Result line doesn't match 'unexpected PASS':", 61 print resultline 62 sys.exit(2) 63 return (re.sub(r"\]\*$", "]", resultline)) 64 else: 65 print "Couldn't parse alleged result line:", resultline 66 sys.exit(2) 67 68 69# This toggles the expected result in the .tst-file "tstfilename" for 70# all tests whose id is listed in "tests" 71def update_tstfile(tstfilename, tests): 72 if len(tests) == 0: 73 print tstfilename, "unchanged." 74 return 75 print "Updating", tstfilename 76 tstfile = open(tstfilename, 'r') 77 tstlines = tstfile.readlines() 78 tstfile.close 79 new_tstfile = '' 80 81 for number, expected in tests: 82 current_line = tstlines.pop(0) 83 command_pattern = re.compile("^%d " % number) 84 85 # Look for the line containing the command with matching id, 86 # while keeping recent commands and comments 87 while (not command_pattern.match(current_line)): 88 new_tstfile = new_tstfile + current_line 89 current_line = tstlines.pop(0) 90 91 # Found match. Now look for the result line: 92 while (not re.match(r"^#\?", current_line)): 93 new_tstfile = new_tstfile + current_line 94 current_line = tstlines.pop(0) 95 96 new_tstfile = new_tstfile + toggled_result(current_line, 97 expected) 98 99 # Now copy the rest of the file without change. 100 new_tstfile = new_tstfile + string.join(tstlines, '') 101 102 tstfile = open(tstfilename, 'w') 103 tstfile.write(new_tstfile) 104 tstfile.close 105 106def parse_input(do_work): 107 tests = [] 108 filename = '' 109 while 1: 110 try: 111 inputline = raw_input() 112 except EOFError: 113 do_work(filename, tests) 114 break 115 else: 116 s = string.split(inputline) 117 if len(s) == 0: 118 continue 119 if (re.search(r"regress\.sh", s[0]) 120 or re.search(r"eval\.sh", s[0])): 121 if (filename != ''): 122 do_work(filename, tests) 123 filename = re.search(r"[^\s]+\.tst", inputline).group() 124 tests = [] 125 elif (re.search("PASS", string.join(s[1:3]))): 126 tests.append([int(s[0]), 1]) 127 elif (re.search("FAIL", string.join(s[1:3]))): 128 tests.append([int(s[0]), 0]) 129 130def parse_pike_input(do_work): 131 tests = [] 132 filename = '' 133 while 1: 134 try: 135 inputline = raw_input() 136 except EOFError: 137 if (filename != ''): 138 do_work(filename, tests) 139 break 140 else: 141 s = string.split(inputline) 142 if (not re.search(r"\:", s[0])): 143 continue 144 new_filename = re.search(r"[^:]+", s[0]).group() \ 145 + ".tst" 146 if (filename != new_filename): 147 if (filename != ''): 148 do_work(filename, tests) 149 filename = new_filename 150 tests = [] 151 number = int(re.search(r"[\d]+$", s[0]).group()) 152 if (s[1] == "PASS"): 153 tests.append([number, 1]) 154 elif (s[1] == "FAIL"): 155 tests.append([number, 0]) 156 else: 157 print "Inconsistent input line:", inputline 158 sys.exit(2) 159 160 161def main(): 162 mode = 0 163 pike = 0 164 try: 165 opts, args = getopt.getopt(sys.argv[1:], "", 166 ["update", "help", "pike"]) 167 except getopt.GetoptError: 168 print "breakage2tst: Unrecognized option." 169 print help_string 170 sys.exit(2) 171 if (args != []): 172 print "I know nothing about arguments", args 173 print help_string 174 sys.exit(2) 175 176 for o, a in opts: 177 if (o == "--help"): 178 print help_string 179 sys.exit() 180 if (o == "--update"): 181 mode = 1 182 if (o == "--pike"): 183 pike = 1 184 185 if (mode == 0): 186 print "./regress.pike ", 187 do_work = write_tests 188 else: 189 do_work = update_tstfile 190 191 192 if (pike): 193 parse_pike_input(do_work) 194 else: 195 parse_input(do_work) 196 197 if (mode == 0): 198 print 199 else: 200 print "Done." 201 202 203main() 204