From: epetrich Date: Tue, 6 Jan 2004 07:14:55 +0000 (+0000) Subject: A python script to validate compiler diagnostic messages. It can be X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=b6b587198da1121c1f1422db782263f5540763a9;p=fw%2Fsdcc A python script to validate compiler diagnostic messages. It can be used to verify that sdcc complains about bad c source code and gives a good location of the error. * support/valdiag/Makefile, * support/valdiag/valdiag.py, * support/valdiag/tests/* git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3086 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index 2189e0d3..3c48f3ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-01-06 Erik Petrich + + A python script to validate compiler diagnostic messages. It can be + used to verify that sdcc complains about bad c source code and + gives a good location of the error. + * support/valdiag/Makefile, + * support/valdiag/valdiag.py, + * support/valdiag/tests/* + 2004-01-06 Erik Petrich * src/SDCC.y (enum_specifier, enumerator_list, opt_assign_expr), diff --git a/support/valdiag/Makefile b/support/valdiag/Makefile new file mode 100644 index 00000000..12c61c1d --- /dev/null +++ b/support/valdiag/Makefile @@ -0,0 +1,45 @@ +.SILENT: + +TESTS_DIR = tests +RESULTS_DIR = results +PORTS_DIR = ports +BUILD_DIR = gen +ALL_PORTS = host mcs51 mcs51-large mcs51-stack-auto ds390 z80 hc08 + +ALL_TESTS = $(shell find $(TESTS_DIR) -name "*.c") + +PORT_RESULTS_DIR = $(RESULTS_DIR)/$(PORT) +PORT_RESULTS = $(ALL_TESTS:$(TESTS_DIR)/%.c=$(PORT_RESULTS_DIR)/%.out) +PORT_BUILD_DIR = $(BUILD_DIR)/$(PORT) + +all: test-ports + +test-ports: + for i in $(ALL_PORTS); do $(MAKE) test-port PORT=$$i; done + +test-mcs51: + $(MAKE) test-port PORT=mcs51 + +test-port: port-results + +clean: clean-gen + rm -rf $(RESULTS_DIR) *.pyc + rm -rf $(BUILD_DIR) + +clean-gen: + for i in $(ALL_PORTS); do $(MAKE) clean-port PORT=$$i; done + +clean-port: + rm -rf $(PORT_BUILD_DIR) + +$(PORT_RESULTS_DIR)/%.out: $(TESTS_DIR)/%.c + echo Processing $< + python valdiag.py $(PORT) $< $(PORT_BUILD_DIR)/$* > $@ + +port-results: port-dirs $(PORT_RESULTS) + echo Summary for \'$(PORT)\': `cat $(PORT_RESULTS) | \ + python ../regression/collate-results.py` + +port-dirs: + mkdir -p $(PORT_RESULTS_DIR) + mkdir -p $(PORT_BUILD_DIR) diff --git a/support/valdiag/tests/cflow.c b/support/valdiag/tests/cflow.c new file mode 100644 index 00000000..b5845501 --- /dev/null +++ b/support/valdiag/tests/cflow.c @@ -0,0 +1,26 @@ + +int x; + +#ifdef TEST0 +void foo(void) +{ + while (1) ; +} +#endif + +#ifdef TEST1 +void foo(void) +{ + while (1) ; + x++; /* WARNING(SDCC) */ +} +#endif + +#ifdef TEST2 +void foo(void) +{ + int y=1; + while (y) ; /* WARNING(SDCC) */ + x++; /* WARNING(SDCC) */ +} +#endif diff --git a/support/valdiag/tests/const.c b/support/valdiag/tests/const.c new file mode 100644 index 00000000..50820814 --- /dev/null +++ b/support/valdiag/tests/const.c @@ -0,0 +1,21 @@ + +char a; +const char ca=2; +const char *pca; +char * const cpa=&a; + +void test(void) +{ + a = 1; +#ifdef TEST1 + ca = a; /* ERROR */ +#endif +#ifdef TEST2 + pca = &a; + *pca = 2; /* ERROR */ +#endif +#ifdef TEST3 + *cpa = 3; + cpa = &ca; /* ERROR */ +#endif +} diff --git a/support/valdiag/tests/enum.c b/support/valdiag/tests/enum.c new file mode 100644 index 00000000..78eeb00d --- /dev/null +++ b/support/valdiag/tests/enum.c @@ -0,0 +1,89 @@ + +#ifdef TEST1 +enum tag +{ + first, + second, + third +}; +#endif + +#ifdef TEST2 +enum tag +{ + first, /* IGNORE */ + second, + third, + first, /* ERROR */ + fourth +}; +#endif + + +#ifdef TEST3 +enum +{ + first, /* IGNORE */ + second, + third, + first, /* ERROR */ + fourth +}; +#endif + + +#ifdef TEST4 +enum +{ + first=1, + second, + third, +}; +#endif + + +#ifdef TEST5 +enum +{ + first=1.1, /* ERROR */ + second, + third, +}; +#endif + +#ifdef TEST6 +int second; /* IGNORE */ + +enum tag +{ + first, + second, /* ERROR */ + third +}; +#endif + +#ifdef TEST7 +enum tag +{ + first, + second, + third +}; + +enum tag { /* ERROR */ + fourth, + fifth, + sixth +}; +#endif + +#ifdef TEST8 +enum tag x; + +enum tag +{ + first, + second, + third +}; +#endif diff --git a/support/valdiag/tests/funcdec.c b/support/valdiag/tests/funcdec.c new file mode 100644 index 00000000..5af72e45 --- /dev/null +++ b/support/valdiag/tests/funcdec.c @@ -0,0 +1,48 @@ + +#ifdef TEST1 +void foo(void); /* IGNORE */ +int foo(void) { } /* ERROR */ +#endif + +#ifdef TEST2 +void foo(void); /* IGNORE */ +void foo(int a) {a; } /* ERROR */ +#endif + + +#ifdef TEST3 +void foo(int); /* IGNORE */ +void foo(int a, int b) {a;b; } /* ERROR */ +#endif + +#ifdef TEST4 +void foo(int, int); /* IGNORE */ +void foo(int a) {a; } /* ERROR */ +#endif + +#if defined(SDCC) && !(defined(__z80) || defined(__gbz80)) +#define REENTRANT reentrant +#define HAS_REENTRANT 1 +#else +#define REENTRANT +#define HAS_REENTRANT 0 +#endif + +#ifdef TEST5 +void foo(int, int) REENTRANT; /* IGNORE */ +#if HAS_REENTRANT +void foo(int a, int b) {a; b;} /* ERROR(SDCC && !(__z80 || __gbz80 || SDCC_STACK_AUTO)) */ +#endif +#endif + +#ifdef TEST6 +void foo(int a=1) /* ERROR */ +{ +} +#endif + +#ifdef TEST7 +void foo(static int a) /* ERROR */ +{ +} +#endif diff --git a/support/valdiag/tests/primtypes.c b/support/valdiag/tests/primtypes.c new file mode 100644 index 00000000..1fa00a35 --- /dev/null +++ b/support/valdiag/tests/primtypes.c @@ -0,0 +1,100 @@ +#ifdef TESTchar +char a; +#endif + +#ifdef TESTint +int a; +#endif + +#ifdef TESTlong +long a; +#endif + +#ifdef TESTshort +short a; +#endif + +#ifdef TESTintlong +long int a; +#endif + +#ifdef TESTintshort +short int a; +#endif + +#ifdef TESTsigned +signed a; +#endif + +#ifdef TESTunsigned +unsigned a; +#endif + +#ifdef TESTintsigned +signed int a; +#endif + +#ifdef TESTintunsigned +unsigned int a; +#endif + +#ifdef TESTfloat +float a; +#endif + +#ifdef TESTfloatsigned +signed float a; /* ERROR */ +#endif + +#ifdef TESTfloatunsigned +unsigned float a; /* ERROR */ +#endif + +#ifdef TESTfloatshort +short float a; /* ERROR */ +#endif + +#ifdef TESTfloatlong +long float a; /* ERROR */ +#endif + +#ifdef TESTdouble +double a; /* WARNING(SDCC) */ +#endif + +#ifdef TESTdoubleshort +short double a; /* ERROR */ +#endif + +#ifdef TESTdoublelong +long double a; /* WARNING(SDCC) */ +#endif + +#ifdef TESTdoublesigned +signed double a; /* ERROR */ +#endif + +#ifdef TESTdoubleunsigned +unsigned double a; /* ERROR */ +#endif + +#ifdef TESTbit +bit a; /* ERROR(__z80||__gbz80||__hc08||PORT_HOST) */ +#endif + +#ifdef TESTsu1 +signed unsigned int a; /* ERROR */ +#endif + +#ifdef TESTsu2 +unsigned signed int a; /* ERROR */ +#endif + +#ifdef TESTsu3 +unsigned signed a; /* ERROR */ +#endif + +#ifdef TESTsu4 +signed unsigned a; /* ERROR */ +#endif + diff --git a/support/valdiag/tests/struct.c b/support/valdiag/tests/struct.c new file mode 100644 index 00000000..615024df --- /dev/null +++ b/support/valdiag/tests/struct.c @@ -0,0 +1,76 @@ + +#ifdef TEST1 +struct tag { + int good1; + register int bad; /* ERROR */ + int good2; +} badstruct; /* IGNORE */ +#endif + +#ifdef TEST2 +struct tag { + int good1; + int bad; + int bad; /* ERROR */ + int good2; +} badstruct; +#endif + + +#ifdef TEST3 +struct tag { + int good1; + int bad:255; /* ERROR */ + int good2; +} badstruct; +#endif + +#ifdef TEST4 +struct tag { + int good1; + int good2; +} goodstruct1; + +struct tag goodstruct2; +#endif + +#ifdef TEST5a +struct tag { + int good1; + int good2; +} goodstruct1; + +union tag badunion; /* ERROR */ +#endif + +#ifdef TEST5b +union tag { + int good1; + int good2; +} goodunion1; + +struct tag badstruct; /* ERROR */ +#endif + + +#ifdef TEST6 +struct linklist { + struct linklist *prev; + struct linklist *next; + int x; +} ll; +#endif + +#ifdef TEST7a +union tag { + struct tag *next; /* ERROR */ + int x; +} ll; +#endif + +#ifdef TEST7b +struct tag { + union tag *next; /* ERROR */ + int x; +} ll; +#endif diff --git a/support/valdiag/tests/switch.c b/support/valdiag/tests/switch.c new file mode 100644 index 00000000..6a29a9d8 --- /dev/null +++ b/support/valdiag/tests/switch.c @@ -0,0 +1,157 @@ + +char x; + +/* Valid switch statement */ +#ifdef TEST1 +char foo(void) +{ + switch(x) + { + char y; + + case 0: + return 0; + case 1: + return 1; + default: + y = x+1; + return y; + } +} +#endif + +/* Error, duplicate cases */ +#ifdef TEST2 +char foo(void) +{ + switch(x) + { + char y; + + case 0: /* IGNORE */ + return 0; + case 1: + return 1; + case 0: /* ERROR */ + return 0; + default: + y = x; + return y; + } +} +#endif + +/* Error, more than one default */ +#ifdef TEST3 +char foo(void) +{ + switch(x) + { + char y; + + case 0: + return 0; + case 1: + return 1; + default: /* IGNORE */ + y = x; + return y; + default: /* ERROR */ + return 2; + } +} +#endif + +/* Warn about unreachable code */ +#ifdef TEST4 +char foo(void) +{ + switch(x) + { + char y; + x++; /* WARNING */ + + case 0: + return 0; + case 1: + return 1; + default: + y = x; + return x; + } +} +#endif + +/* Warn about unreachable initializer */ +#ifdef TEST5 +char foo(void) +{ + switch(x) + { + char y=1; /* WARNING */ + + case 0: + return 0; + case 1: + return 1; + default: + return y; /* IGNORE */ + } +} +#endif + +/* Error, missing switch */ +#ifdef TEST6 +char foo(void) +{ + { + case 0: /* ERROR */ + return 0; + case 1: /* ERROR */ + return 1; + default: /* ERROR */ + return x; + } +} +#endif + +/* Error, switch condition must be integral */ +#ifdef TEST7 +char foo(void) +{ + float f; + f=x; + switch(f) /* ERROR */ + { + char y; + + case 0: + return 0; + case 1: + return 1; + default: + y = x; + return x; + } +} +#endif + +/* Error, cases must be integral */ +#ifdef TEST8 +char foo(void) +{ + switch(x) + { + char y; + + case 0.0: /* ERROR */ + return 0; + case 1: + return 1; + default: + y = x; + return x; + } +} +#endif + diff --git a/support/valdiag/tests/tentdecl.c b/support/valdiag/tests/tentdecl.c new file mode 100644 index 00000000..90bc17fd --- /dev/null +++ b/support/valdiag/tests/tentdecl.c @@ -0,0 +1,119 @@ + +#ifdef TEST0 +int a; +int a; +#endif + +#ifdef TEST1 +int a; /* IGNORE */ +char a; /* ERROR */ +#endif + +#ifdef TEST2 +int a; /* IGNORE */ +int *a; /* ERROR */ +#endif + +#ifdef TEST3 +int *a; /* IGNORE */ +int a[5]; /* ERROR */ +#endif + +/* array size must match */ + +#ifdef TEST4 +int a[4]; /* IGNORE */ +int a[5]; /* ERROR */ +#endif + +/* but it is legal to clarify */ +/* an incomplete type */ + +#ifdef TEST4b +int a[]; +int a[5]; +#endif + +/* type qualifier must match */ + +#ifdef TEST5 +int a; /* IGNORE */ +volatile int a; /* ERROR */ +#endif + +#ifdef TEST6 +int a; /* IGNORE */ +const int a; /* ERROR */ +#endif + +#ifdef TEST7 +int a=1; /* IGNORE */ +int a=2; /* ERROR */ +#endif + +#ifdef TEST7a +int a=1; +int a; +#endif + +#ifdef TEST8 +int a=1; /* IGNORE */ +int a=1; /* ERROR */ +#endif + +#if defined(__z80) || defined(__gbz80) +#define XDATA +#define DATA +#else +#define XDATA xdata +#define DATA data +#endif + +#ifdef TEST9 +#ifdef SDCC +XDATA int a; +DATA int a; /* ERROR(SDCC && !(__z80 || __gbz80)) */ +#endif +#endif + +#ifdef TEST9b +#ifdef SDCC +DATA int a; +XDATA int a; /* ERROR(SDCC && !(__z80 || __gbz80)) */ +#endif +#endif + +#ifdef TEST9c +#ifdef SDCC +extern DATA int a; +DATA int a; +#endif +#endif + +#ifdef TEST9d +#ifdef SDCC +extern XDATA int a; +XDATA int a; +#endif +#endif + +#ifdef TEST9e +#ifdef SDCC +extern XDATA int a; +DATA int a; /* ERROR(SDCC && !(__z80 || __gbz80)) */ +#endif +#endif + +#ifdef TEST9f +#ifdef SDCC +extern DATA int a; +XDATA int a; /* ERROR(SDCC && !(__z80 || __gbz80)) */ +#endif +#endif + +#ifdef TEST10 +#if defined(SDCC) && !(defined(__z80) || defined(__gbz80)) +extern volatile XDATA at 0 int a; +volatile XDATA int a; /* ERROR(SDCC && !(__z80 || __gbz80)) */ +#endif +#endif diff --git a/support/valdiag/tests/typedef.c b/support/valdiag/tests/typedef.c new file mode 100644 index 00000000..a3c84229 --- /dev/null +++ b/support/valdiag/tests/typedef.c @@ -0,0 +1,43 @@ + +#ifdef TEST1 +typedef union { + long l; + float f; +} floatlong; + +char func(char floatlong) +{ + return floatlong; +} +#endif + +#ifdef TEST2 +typedef union { + long l; + float f; +} floatlong; + +long func(float x) +{ + typedef union { + float f2; + long l2; + char c[4]; + } floatlong; + floatlong fl; + + fl.f2=x; + return fl.l2; +} +#endif + +#ifdef TEST3 +typedef int I; /* IGNORE */ +typedef int I; /* ERROR */ +#endif + +#ifdef TEST4 +typedef int I; /* IGNORE */ +typedef char I; /* ERROR */ +#endif + diff --git a/support/valdiag/valdiag.py b/support/valdiag/valdiag.py new file mode 100644 index 00000000..2a4ed750 --- /dev/null +++ b/support/valdiag/valdiag.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python +#--------------------------------------------------------------------------- +# valdiag.py - Validate diagnostic messages from SDCC/GCC +# Written By - Erik Petrich . epetrich@users.sourceforge.net (2003) +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# In other words, you are welcome to use, share and improve this program. +# You are forbidden to forbid anyone else to use, share and improve +# what you give them. Help stamp out software-hoarding! +#--------------------------------------------------------------------------- + +import sys, string, os, popen2, re + +macrodefs = {} + +gcc = { + "CC":"gcc", + "CCFLAGS":"-c -Wall", + "CCDEF":"-D", + "CCOUTPUT":"-o", + "defined": { + "__GNUC__":"1" + }, + "ignoremsg": [ + ] +} + +sdcc = { + "CC":"../../bin/sdcc", + "CCFLAGS":"-c -m{port}", + "CCDEF":"-D", + "CCOUTPUT":"-o", + "defined": { + "SDCC":"1", + "SDCC_{port}":"1", + "__{port}":"1" + }, + "ignoremsg": [ + "code not generated.*due to previous errors", + "unreferenced function argument" + ] +} + +testmodes = { + "host":{ + "compiler":gcc, + "port":"host", + "defined": { + "PORT_HOST":"1" + } + }, + "mcs51":{ + "compiler":sdcc, + "port":"mcs51" + }, + "mcs51-large":{ + "compiler":sdcc, + "port":"mcs51", + "flags":"--model-large", + "defined": { + "SDCC_MODEL_LARGE":"1" + } + }, + "mcs51-stack-auto":{ + "compiler":sdcc, + "port":"mcs51", + "flags":"--stack-auto", + "defined": { + "SDCC_STACK_AUTO":"1" + } + }, + "ds390":{ + "compiler":sdcc, + "port":"ds390" + }, + "z80":{ + "compiler":sdcc, + "port":"z80" + }, + "gbz80":{ + "compiler":sdcc, + "port":"gbz80" + }, + "hc08":{ + "compiler":sdcc, + "port":"hc08" + }, + "pic14":{ + "compiler":sdcc, + "port":"pic14" + }, + "pic16":{ + "compiler":sdcc, + "port":"pic16" + } +} + + +def evalQualifier(expr): + global macrodefs + tokens = re.split("([^0-9A-Za-z_])", expr) + for tokenindex in range(len(tokens)): + token = tokens[tokenindex] + if token in macrodefs: + tokens[tokenindex] = macrodefs[token] + elif token == "defined": + tokens[tokenindex] = "" + if tokens[tokenindex+2] in macrodefs: + tokens[tokenindex+2] = "1" + else: + tokens[tokenindex+2] = "0" + elif len(token)>0: + if token[0]=="_" or token[0] in string.ascii_letters: + tokens[tokenindex] = "0" + expr = string.join(tokens,"") + expr = string.replace(expr,"&&"," and "); + expr = string.replace(expr,"||"," or "); + expr = string.replace(expr,"!"," not "); + return eval(expr) + +def expandPyExpr(expr): + tokens = re.split("({|})", expr) + for tokenindex in range(1,len(tokens)): + if tokens[tokenindex-1]=="{": + tokens[tokenindex]=eval(tokens[tokenindex]) + tokens[tokenindex-1]="" + tokens[tokenindex+1]="" + expandedExpr = string.join(tokens,"") + return expandedExpr + +def addDefines(deflist): + for define in deflist.keys(): + expandeddef = expandPyExpr(define) + macrodefs[expandeddef] = expandPyExpr(deflist[define]) + +def parseInputfile(inputfilename): + inputfile = open(inputfilename, "r") + testcases = {} + testname = "" + linenumber = 1 + + # Find the test cases and tests in this file + for line in inputfile.readlines(): + + # See if a new testcase is being defined + p = string.find(line, "TEST") + if p>=0: + testname = string.split(line[p:])[0] + if not testcases.has_key(testname): + testcases[testname] = {} + + # See if a new test is being defined + for testtype in ["ERROR", "WARNING", "IGNORE"]: + p = string.find(line, testtype); + if p>=0: + # Found a test definition + qualifier = string.strip(line[p+len(testtype):]) + p = string.find(qualifier, "*/") + if p>=0: + qualifier = string.strip(qualifier[:p]) + if len(qualifier)==0: + qualifier="1" + qualifier = evalQualifier(qualifier) + if qualifier: + if not linenumber in testcases[testname]: + testcases[testname][linenumber]=[] + testcases[testname][linenumber].append(testtype) + + linenumber = linenumber + 1 + + inputfile.close() + return testcases + +def parseResults(output): + results = {} + for line in output: + print line, + + if string.count(line, "SIGSEG"): + results[0] = ["FAULT", string.strip(line)] + continue + + # look for something of the form: + # filename:line:message + msg = string.split(line,":",2) + if len(msg)<3: continue + if msg[0]!=inputfilename: continue + if len(msg[1])==0: continue + if not msg[1][0] in string.digits: continue + + # it's in the right form; parse it + linenumber = int(msg[1]) + msgtype = "UNKNOWN" + uppermsg = string.upper(msg[2]) + if string.count(uppermsg,"ERROR"): + msgtype = "ERROR" + if string.count(uppermsg,"WARNING"): + msgtype = "WARNING" + msgtext = string.strip(msg[2]) + ignore = 0 + for ignoreExpr in ignoreExprList: + if re.search(ignoreExpr,msgtext)!=None: + ignore = 1 + if not ignore: + results[linenumber]=[msgtype,string.strip(msg[2])] + return results + +def showUsage(): + print "Usage: test testmode cfile [objectfile]" + print "Choices for testmode are:" + for testmodename in testmodes.keys(): + print " %s" % testmodename + sys.exit(1) + +# Start here +if len(sys.argv)<3: + showUsage() + +testmodename = sys.argv[1] +if not testmodename in testmodes: + print "Unknown test mode '%s'" % testmodename + showUsage() + +testmode = testmodes[testmodename] +compilermode = testmode["compiler"] +port = expandPyExpr(testmode["port"]) +cc = expandPyExpr(compilermode["CC"]) +ccflags = expandPyExpr(compilermode["CCFLAGS"]) +if "flags" in testmode: + ccflags = string.join([ccflags,expandPyExpr(testmode["flags"])]) +if len(sys.argv)>=4: + if "CCOUTPUT" in compilermode: + ccflags = string.join([ccflags,expandPyExpr(compilermode["CCOUTPUT"]),sys.argv[3]]) +if "defined" in compilermode: + addDefines(compilermode["defined"]) +if "defined" in testmode: + addDefines(testmode["defined"]) +if "ignoremsg" in compilermode: + ignoreExprList = compilermode["ignoremsg"] +else: + ignoreExprList = [] + +inputfilename = sys.argv[2] +try: + testcases = parseInputfile(inputfilename) +except IOError: + print "Unable to read file '%s'" % inputfilename + sys.exit(1) + +casecount = len(testcases.keys()) +testcount = 0 +failurecount = 0 + +for testname in testcases.keys(): + ccdef = compilermode["CCDEF"]+testname + cmd = string.join([cc,ccflags,ccdef,inputfilename]) + print + print cmd + spawn = popen2.Popen4(cmd) + spawn.wait() + output = spawn.fromchild.readlines() + + results = parseResults(output) + + if len(testcases[testname])==0: + testcount = testcount + 1 #implicit test for no errors + + # Go through the tests of this case and make sure + # the compiler gave a diagnostic + for checkline in testcases[testname].keys(): + testcount = testcount + 1 + if checkline in results: + if "IGNORE" in testcases[testname][checkline]: + testcount = testcount - 1 #this isn't really a test + del results[checkline] + else: + for wanted in testcases[testname][checkline]: + if not wanted=="IGNORE": + print "--- FAIL: expected %s" % wanted, + print "at %s:%d" % (inputfilename, checkline) + failurecount = failurecount + 1 + + # Output any unexpected diagnostics + for checkline in results.keys(): + print '--- FAIL: unexpected message "%s" ' % results[checkline][1], + print "at %s:%d" % (inputfilename, checkline) + failurecount = failurecount + 1 + +print +print "--- Summary: %d/%d/%d: " % (failurecount, testcount, casecount), +print "%d failed of %d tests in %d cases." % (failurecount, testcount, casecount)