Home | History | Annotate | Download | only in test
      1 /*
      2  * [The "BSD license"]
      3  *  Copyright (c) 2010 Terence Parr
      4  *  All rights reserved.
      5  *
      6  *  Redistribution and use in source and binary forms, with or without
      7  *  modification, are permitted provided that the following conditions
      8  *  are met:
      9  *  1. Redistributions of source code must retain the above copyright
     10  *      notice, this list of conditions and the following disclaimer.
     11  *  2. Redistributions in binary form must reproduce the above copyright
     12  *      notice, this list of conditions and the following disclaimer in the
     13  *      documentation and/or other materials provided with the distribution.
     14  *  3. The name of the author may not be used to endorse or promote products
     15  *      derived from this software without specific prior written permission.
     16  *
     17  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 package org.antlr.test;
     29 
     30 
     31 import org.antlr.Tool;
     32 import org.antlr.analysis.Label;
     33 import org.antlr.runtime.CommonTokenStream;
     34 import org.antlr.runtime.Token;
     35 import org.antlr.runtime.TokenSource;
     36 import org.stringtemplate.v4.ST;
     37 import org.stringtemplate.v4.STGroup;
     38 import org.antlr.tool.ANTLRErrorListener;
     39 import org.antlr.tool.ErrorManager;
     40 import org.antlr.tool.GrammarSemanticsMessage;
     41 import org.antlr.tool.Message;
     42 import org.junit.After;
     43 import org.junit.Assert;
     44 import org.junit.Before;
     45 
     46 import javax.tools.*;
     47 import java.io.*;
     48 import java.util.*;
     49 
     50 
     51 public abstract class BaseTest {
     52 	public static final String newline = System.getProperty("line.separator");
     53 
     54 	public static final String jikes = null;//"/usr/bin/jikes";
     55 	public static final String pathSep = System.getProperty("path.separator");
     56 
     57    /**
     58     * When runnning from Maven, the junit tests are run via the surefire plugin. It sets the
     59     * classpath for the test environment into the following property. We need to pick this up
     60     * for the junit tests that are going to generate and try to run code.
     61     */
     62     public static final String SUREFIRE_CLASSPATH = System.getProperty("surefire.test.class.path", "");
     63 
     64     /**
     65      * Build up the full classpath we need, including the surefire path (if present)
     66      */
     67     public static final String CLASSPATH = System.getProperty("java.class.path") + (SUREFIRE_CLASSPATH.equals("") ? "" : pathSep + SUREFIRE_CLASSPATH);
     68 
     69 	public String tmpdir = null;
     70 
     71     /** reset during setUp and set to true if we find a problem */
     72     protected boolean lastTestFailed = false;
     73 
     74 	/** If error during parser execution, store stderr here; can't return
     75      *  stdout and stderr.  This doesn't trap errors from running antlr.
     76      */
     77 	protected String stderrDuringParse;
     78 
     79     @Before
     80 	public void setUp() throws Exception {
     81         lastTestFailed = false; // hope for the best, but set to true in asserts that fail
     82         // new output dir for each test
     83         tmpdir = new File(System.getProperty("java.io.tmpdir"),
     84 						  "antlr-"+getClass().getName()+"-"+
     85 						  System.currentTimeMillis()).getAbsolutePath();
     86         ErrorManager.resetErrorState();
     87         STGroup.defaultGroup = new STGroup();
     88     }
     89 
     90     @After
     91     public void tearDown() throws Exception {
     92         // remove tmpdir if no error.
     93         if ( !lastTestFailed ) eraseTempDir();
     94 
     95     }
     96 
     97     protected Tool newTool(String[] args) {
     98 		Tool tool = new Tool(args);
     99 		tool.setOutputDirectory(tmpdir);
    100 		return tool;
    101 	}
    102 
    103 	protected Tool newTool() {
    104 		Tool tool = new Tool();
    105 		tool.setOutputDirectory(tmpdir);
    106 		return tool;
    107 	}
    108 
    109 	protected boolean compile(String fileName) {
    110 		String classpathOption = "-classpath";
    111 
    112 		String[] args = new String[] {
    113 					"javac", "-d", tmpdir,
    114 					classpathOption, tmpdir+pathSep+CLASSPATH,
    115 					tmpdir+"/"+fileName
    116 		};
    117 		String cmdLine = "javac" +" -d "+tmpdir+" "+classpathOption+" "+tmpdir+pathSep+CLASSPATH+" "+fileName;
    118 		//System.out.println("compile: "+cmdLine);
    119 
    120 
    121 		File f = new File(tmpdir, fileName);
    122 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    123 
    124 		StandardJavaFileManager fileManager =
    125 			compiler.getStandardFileManager(null, null, null);
    126 
    127 		Iterable<? extends JavaFileObject> compilationUnits =
    128 			fileManager.getJavaFileObjectsFromFiles(Arrays.asList(f));
    129 
    130 		Iterable<String> compileOptions =
    131 			Arrays.asList(new String[]{"-d", tmpdir, "-cp", tmpdir+pathSep+CLASSPATH} );
    132 
    133 		JavaCompiler.CompilationTask task =
    134 			compiler.getTask(null, fileManager, null, compileOptions, null,
    135 							 compilationUnits);
    136 		boolean ok = task.call();
    137 
    138 		try {
    139 			fileManager.close();
    140 		}
    141 		catch (IOException ioe) {
    142 			ioe.printStackTrace(System.err);
    143 		}
    144 		return ok;
    145 	}
    146 
    147 	/** Return true if all is ok, no errors */
    148 	protected boolean antlr(String fileName, String grammarFileName, String grammarStr, boolean debug) {
    149 		boolean allIsWell = true;
    150 		mkdir(tmpdir);
    151 		writeFile(tmpdir, fileName, grammarStr);
    152 		try {
    153 			final List options = new ArrayList();
    154 			if ( debug ) {
    155 				options.add("-debug");
    156 			}
    157 			options.add("-o");
    158 			options.add(tmpdir);
    159 			options.add("-lib");
    160 			options.add(tmpdir);
    161 			options.add(new File(tmpdir,grammarFileName).toString());
    162 			final String[] optionsA = new String[options.size()];
    163 			options.toArray(optionsA);
    164 			/*
    165 			final ErrorQueue equeue = new ErrorQueue();
    166 			ErrorManager.setErrorListener(equeue);
    167 			*/
    168 			Tool antlr = newTool(optionsA);
    169 			antlr.process();
    170 			ANTLRErrorListener listener = ErrorManager.getErrorListener();
    171 			if ( listener instanceof ErrorQueue ) {
    172 				ErrorQueue equeue = (ErrorQueue)listener;
    173 				if ( equeue.errors.size()>0 ) {
    174 					allIsWell = false;
    175 					System.err.println("antlr reports errors from "+options);
    176 					for (int i = 0; i < equeue.errors.size(); i++) {
    177 						Message msg = (Message) equeue.errors.get(i);
    178 						System.err.println(msg);
    179 					}
    180                     System.out.println("!!!\ngrammar:");
    181                     System.out.println(grammarStr);
    182                     System.out.println("###");
    183                 }
    184 			}
    185 		}
    186 		catch (Exception e) {
    187 			allIsWell = false;
    188 			System.err.println("problems building grammar: "+e);
    189 			e.printStackTrace(System.err);
    190 		}
    191 		return allIsWell;
    192 	}
    193 
    194 	protected String execLexer(String grammarFileName,
    195 							   String grammarStr,
    196 							   String lexerName,
    197 							   String input,
    198 							   boolean debug)
    199 	{
    200 		rawGenerateAndBuildRecognizer(grammarFileName,
    201 									  grammarStr,
    202 									  null,
    203 									  lexerName,
    204 									  debug);
    205 		writeFile(tmpdir, "input", input);
    206 		return rawExecRecognizer(null,
    207 								 null,
    208 								 lexerName,
    209 								 null,
    210 								 null,
    211 								 false,
    212 								 false,
    213 								 false,
    214 								 debug);
    215 	}
    216 
    217 	protected String execParser(String grammarFileName,
    218 								String grammarStr,
    219 								String parserName,
    220 								String lexerName,
    221 								String startRuleName,
    222 								String input, boolean debug)
    223 	{
    224 		rawGenerateAndBuildRecognizer(grammarFileName,
    225 									  grammarStr,
    226 									  parserName,
    227 									  lexerName,
    228 									  debug);
    229 		writeFile(tmpdir, "input", input);
    230 		boolean parserBuildsTrees =
    231 			grammarStr.indexOf("output=AST")>=0 ||
    232 			grammarStr.indexOf("output = AST")>=0;
    233 		boolean parserBuildsTemplate =
    234 			grammarStr.indexOf("output=template")>=0 ||
    235 			grammarStr.indexOf("output = template")>=0;
    236 		return rawExecRecognizer(parserName,
    237 								 null,
    238 								 lexerName,
    239 								 startRuleName,
    240 								 null,
    241 								 parserBuildsTrees,
    242 								 parserBuildsTemplate,
    243 								 false,
    244 								 debug);
    245 	}
    246 
    247 	protected String execTreeParser(String parserGrammarFileName,
    248 									String parserGrammarStr,
    249 									String parserName,
    250 									String treeParserGrammarFileName,
    251 									String treeParserGrammarStr,
    252 									String treeParserName,
    253 									String lexerName,
    254 									String parserStartRuleName,
    255 									String treeParserStartRuleName,
    256 									String input)
    257 	{
    258 		return execTreeParser(parserGrammarFileName,
    259 							  parserGrammarStr,
    260 							  parserName,
    261 							  treeParserGrammarFileName,
    262 							  treeParserGrammarStr,
    263 							  treeParserName,
    264 							  lexerName,
    265 							  parserStartRuleName,
    266 							  treeParserStartRuleName,
    267 							  input,
    268 							  false);
    269 	}
    270 
    271 	protected String execTreeParser(String parserGrammarFileName,
    272 									String parserGrammarStr,
    273 									String parserName,
    274 									String treeParserGrammarFileName,
    275 									String treeParserGrammarStr,
    276 									String treeParserName,
    277 									String lexerName,
    278 									String parserStartRuleName,
    279 									String treeParserStartRuleName,
    280 									String input,
    281 									boolean debug)
    282 	{
    283 		// build the parser
    284 		rawGenerateAndBuildRecognizer(parserGrammarFileName,
    285 									  parserGrammarStr,
    286 									  parserName,
    287 									  lexerName,
    288 									  debug);
    289 
    290 		// build the tree parser
    291 		rawGenerateAndBuildRecognizer(treeParserGrammarFileName,
    292 									  treeParserGrammarStr,
    293 									  treeParserName,
    294 									  lexerName,
    295 									  debug);
    296 
    297 		writeFile(tmpdir, "input", input);
    298 
    299 		boolean parserBuildsTrees =
    300 			parserGrammarStr.indexOf("output=AST")>=0 ||
    301 			parserGrammarStr.indexOf("output = AST")>=0;
    302 		boolean treeParserBuildsTrees =
    303 			treeParserGrammarStr.indexOf("output=AST")>=0 ||
    304 			treeParserGrammarStr.indexOf("output = AST")>=0;
    305 		boolean parserBuildsTemplate =
    306 			parserGrammarStr.indexOf("output=template")>=0 ||
    307 			parserGrammarStr.indexOf("output = template")>=0;
    308 
    309 		return rawExecRecognizer(parserName,
    310 								 treeParserName,
    311 								 lexerName,
    312 								 parserStartRuleName,
    313 								 treeParserStartRuleName,
    314 								 parserBuildsTrees,
    315 								 parserBuildsTemplate,
    316 								 treeParserBuildsTrees,
    317 								 debug);
    318 	}
    319 
    320 	/** Return true if all is well */
    321 	protected boolean rawGenerateAndBuildRecognizer(String grammarFileName,
    322 													String grammarStr,
    323 													String parserName,
    324 													String lexerName,
    325 													boolean debug)
    326 	{
    327 		//System.out.println(grammarStr);
    328 		boolean allIsWell =
    329 			antlr(grammarFileName, grammarFileName, grammarStr, debug);
    330 		if ( lexerName!=null ) {
    331 			boolean ok;
    332 			if ( parserName!=null ) {
    333 				ok = compile(parserName+".java");
    334 				if ( !ok ) { allIsWell = false; }
    335 			}
    336 			ok = compile(lexerName+".java");
    337 			if ( !ok ) { allIsWell = false; }
    338 		}
    339 		else {
    340 			boolean ok = compile(parserName+".java");
    341 			if ( !ok ) { allIsWell = false; }
    342 		}
    343 		return allIsWell;
    344 	}
    345 
    346 	protected String rawExecRecognizer(String parserName,
    347 									   String treeParserName,
    348 									   String lexerName,
    349 									   String parserStartRuleName,
    350 									   String treeParserStartRuleName,
    351 									   boolean parserBuildsTrees,
    352 									   boolean parserBuildsTemplate,
    353 									   boolean treeParserBuildsTrees,
    354 									   boolean debug)
    355 	{
    356         this.stderrDuringParse = null;
    357 		writeRecognizerAndCompile(parserName, treeParserName, lexerName, parserStartRuleName, treeParserStartRuleName, parserBuildsTrees, parserBuildsTemplate, treeParserBuildsTrees, debug);
    358 
    359 		return execRecognizer();
    360 	}
    361 
    362 	public String execRecognizer() {
    363 		try {
    364 			String inputFile = new File(tmpdir, "input").getAbsolutePath();
    365 			String[] args = new String[] {
    366 				"java", "-classpath", tmpdir+pathSep+CLASSPATH,
    367 				"Test", inputFile
    368 			};
    369 			//String cmdLine = "java -classpath "+CLASSPATH+pathSep+tmpdir+" Test " + new File(tmpdir, "input").getAbsolutePath();
    370 			//System.out.println("execParser: "+cmdLine);
    371 			Process process =
    372 				Runtime.getRuntime().exec(args, null, new File(tmpdir));
    373 			StreamVacuum stdoutVacuum = new StreamVacuum(process.getInputStream(), inputFile);
    374 			StreamVacuum stderrVacuum = new StreamVacuum(process.getErrorStream(), inputFile);
    375 			stdoutVacuum.start();
    376 			stderrVacuum.start();
    377 			process.waitFor();
    378 			stdoutVacuum.join();
    379 			stderrVacuum.join();
    380 			String output = null;
    381 			output = stdoutVacuum.toString();
    382 			if ( stderrVacuum.toString().length()>0 ) {
    383 				this.stderrDuringParse = stderrVacuum.toString();
    384 				System.err.println("exec stderrVacuum: "+ stderrVacuum);
    385 			}
    386 			return output;
    387 		}
    388 		catch (Exception e) {
    389 			System.err.println("can't exec recognizer");
    390 			e.printStackTrace(System.err);
    391 		}
    392 		return null;
    393 	}
    394 
    395 	public void writeRecognizerAndCompile(String parserName, String treeParserName, String lexerName, String parserStartRuleName, String treeParserStartRuleName, boolean parserBuildsTrees, boolean parserBuildsTemplate, boolean treeParserBuildsTrees, boolean debug) {
    396 		if ( treeParserBuildsTrees && parserBuildsTrees ) {
    397 			writeTreeAndTreeTestFile(parserName,
    398 									 treeParserName,
    399 									 lexerName,
    400 									 parserStartRuleName,
    401 									 treeParserStartRuleName,
    402 									 debug);
    403 		}
    404 		else if ( parserBuildsTrees ) {
    405 			writeTreeTestFile(parserName,
    406 							  treeParserName,
    407 							  lexerName,
    408 							  parserStartRuleName,
    409 							  treeParserStartRuleName,
    410 							  debug);
    411 		}
    412 		else if ( parserBuildsTemplate ) {
    413 			writeTemplateTestFile(parserName,
    414 								  lexerName,
    415 								  parserStartRuleName,
    416 								  debug);
    417 		}
    418 		else if ( parserName==null ) {
    419 			writeLexerTestFile(lexerName, debug);
    420 		}
    421 		else {
    422 			writeTestFile(parserName,
    423 						  lexerName,
    424 						  parserStartRuleName,
    425 						  debug);
    426 		}
    427 
    428 		compile("Test.java");
    429 	}
    430 
    431 	protected void checkGrammarSemanticsError(ErrorQueue equeue,
    432 											  GrammarSemanticsMessage expectedMessage)
    433 		throws Exception
    434 	{
    435 		/*
    436 				System.out.println(equeue.infos);
    437 				System.out.println(equeue.warnings);
    438 				System.out.println(equeue.errors);
    439 				assertTrue("number of errors mismatch", n, equeue.errors.size());
    440 						   */
    441 		Message foundMsg = null;
    442 		for (int i = 0; i < equeue.errors.size(); i++) {
    443 			Message m = (Message)equeue.errors.get(i);
    444 			if (m.msgID==expectedMessage.msgID ) {
    445 				foundMsg = m;
    446 			}
    447 		}
    448 		assertNotNull("no error; "+expectedMessage.msgID+" expected", foundMsg);
    449 		assertTrue("error is not a GrammarSemanticsMessage",
    450 				   foundMsg instanceof GrammarSemanticsMessage);
    451 		assertEquals(expectedMessage.arg, foundMsg.arg);
    452 		if ( equeue.size()!=1 ) {
    453 			System.err.println(equeue);
    454 		}
    455 	}
    456 
    457 	protected void checkGrammarSemanticsWarning(ErrorQueue equeue,
    458 												GrammarSemanticsMessage expectedMessage)
    459 		throws Exception
    460 	{
    461 		Message foundMsg = null;
    462 		for (int i = 0; i < equeue.warnings.size(); i++) {
    463 			Message m = (Message)equeue.warnings.get(i);
    464 			if (m.msgID==expectedMessage.msgID ) {
    465 				foundMsg = m;
    466 			}
    467 		}
    468 		assertNotNull("no error; "+expectedMessage.msgID+" expected", foundMsg);
    469 		assertTrue("error is not a GrammarSemanticsMessage",
    470 				   foundMsg instanceof GrammarSemanticsMessage);
    471 		assertEquals(expectedMessage.arg, foundMsg.arg);
    472 	}
    473 
    474     protected void checkError(ErrorQueue equeue,
    475                               Message expectedMessage)
    476         throws Exception
    477     {
    478         //System.out.println("errors="+equeue);
    479         Message foundMsg = null;
    480         for (int i = 0; i < equeue.errors.size(); i++) {
    481             Message m = (Message)equeue.errors.get(i);
    482             if (m.msgID==expectedMessage.msgID ) {
    483                 foundMsg = m;
    484             }
    485         }
    486         assertTrue("no error; "+expectedMessage.msgID+" expected", equeue.errors.size()>0);
    487         assertTrue("too many errors; "+equeue.errors, equeue.errors.size()<=1);
    488         assertNotNull("couldn't find expected error: "+expectedMessage.msgID, foundMsg);
    489         /*
    490         assertTrue("error is not a GrammarSemanticsMessage",
    491                    foundMsg instanceof GrammarSemanticsMessage);
    492          */
    493         assertEquals(expectedMessage.arg, foundMsg.arg);
    494         assertEquals(expectedMessage.arg2, foundMsg.arg2);
    495         ErrorManager.resetErrorState(); // wack errors for next test
    496     }
    497 
    498     public static class StreamVacuum implements Runnable {
    499 		StringBuffer buf = new StringBuffer();
    500 		BufferedReader in;
    501 		Thread sucker;
    502 		String inputFile;
    503 		public StreamVacuum(InputStream in, String inputFile) {
    504 			this.in = new BufferedReader( new InputStreamReader(in) );
    505 			this.inputFile = inputFile;
    506 		}
    507 		public void start() {
    508 			sucker = new Thread(this);
    509 			sucker.start();
    510 		}
    511 		public void run() {
    512 			try {
    513 				String line = in.readLine();
    514 				while (line!=null) {
    515 					if (line.startsWith(inputFile))
    516 						line = line.substring(inputFile.length()+1);
    517 					buf.append(line);
    518 					buf.append('\n');
    519 					line = in.readLine();
    520 				}
    521 			}
    522 			catch (IOException ioe) {
    523 				System.err.println("can't read output from process");
    524 			}
    525 		}
    526 		/** wait for the thread to finish */
    527 		public void join() throws InterruptedException {
    528 			sucker.join();
    529 		}
    530 		public String toString() {
    531 			return buf.toString();
    532 		}
    533 	}
    534 
    535     public static class FilteringTokenStream extends CommonTokenStream {
    536         public FilteringTokenStream(TokenSource src) { super(src); }
    537         Set<Integer> hide = new HashSet<Integer>();
    538         protected void sync(int i) {
    539             super.sync(i);
    540             if ( hide.contains(get(i).getType()) ) get(i).setChannel(Token.HIDDEN_CHANNEL);
    541         }
    542         public void setTokenTypeChannel(int ttype, int channel) {
    543             hide.add(ttype);
    544         }
    545     }
    546 
    547 	protected void writeFile(String dir, String fileName, String content) {
    548 		try {
    549 			File f = new File(dir, fileName);
    550 			FileWriter w = new FileWriter(f);
    551 			BufferedWriter bw = new BufferedWriter(w);
    552 			bw.write(content);
    553 			bw.close();
    554 			w.close();
    555 		}
    556 		catch (IOException ioe) {
    557 			System.err.println("can't write file");
    558 			ioe.printStackTrace(System.err);
    559 		}
    560 	}
    561 
    562 	protected void mkdir(String dir) {
    563 		File f = new File(dir);
    564 		f.mkdirs();
    565 	}
    566 
    567 	protected void writeTestFile(String parserName,
    568 								 String lexerName,
    569 								 String parserStartRuleName,
    570 								 boolean debug)
    571 	{
    572 		ST outputFileST = new ST(
    573 			"import org.antlr.runtime.*;\n" +
    574 			"import org.antlr.runtime.tree.*;\n" +
    575 			"import org.antlr.runtime.debug.*;\n" +
    576 			"\n" +
    577 			"class Profiler2 extends Profiler {\n" +
    578 			"    public void terminate() { ; }\n" +
    579 			"}\n"+
    580 			"public class Test {\n" +
    581 			"    public static void main(String[] args) throws Exception {\n" +
    582 			"        CharStream input = new ANTLRFileStream(args[0]);\n" +
    583 			"        <lexerName> lex = new <lexerName>(input);\n" +
    584 			"        CommonTokenStream tokens = new CommonTokenStream(lex);\n" +
    585 			"        <createParser>\n"+
    586 			"        parser.<parserStartRuleName>();\n" +
    587 			"    }\n" +
    588 			"}"
    589 			);
    590 		ST createParserST =
    591 			new ST(
    592 			"        Profiler2 profiler = new Profiler2();\n"+
    593 			"        <parserName> parser = new <parserName>(tokens,profiler);\n" +
    594 			"        profiler.setParser(parser);\n");
    595 		if ( !debug ) {
    596 			createParserST =
    597 				new ST(
    598 				"        <parserName> parser = new <parserName>(tokens);\n");
    599 		}
    600 		outputFileST.add("createParser", createParserST);
    601 		outputFileST.add("parserName", parserName);
    602 		outputFileST.add("lexerName", lexerName);
    603 		outputFileST.add("parserStartRuleName", parserStartRuleName);
    604 		writeFile(tmpdir, "Test.java", outputFileST.render());
    605 	}
    606 
    607 	protected void writeLexerTestFile(String lexerName, boolean debug) {
    608 		ST outputFileST = new ST(
    609 			"import org.antlr.runtime.*;\n" +
    610 			"import org.antlr.runtime.tree.*;\n" +
    611 			"import org.antlr.runtime.debug.*;\n" +
    612 			"\n" +
    613 			"class Profiler2 extends Profiler {\n" +
    614 			"    public void terminate() { ; }\n" +
    615 			"}\n"+
    616 			"public class Test {\n" +
    617 			"    public static void main(String[] args) throws Exception {\n" +
    618 			"        CharStream input = new ANTLRFileStream(args[0]);\n" +
    619 			"        <lexerName> lex = new <lexerName>(input);\n" +
    620 			"        CommonTokenStream tokens = new CommonTokenStream(lex);\n" +
    621 			"        System.out.println(tokens);\n" +
    622 			"    }\n" +
    623 			"}"
    624 			);
    625 		outputFileST.add("lexerName", lexerName);
    626 		writeFile(tmpdir, "Test.java", outputFileST.render());
    627 	}
    628 
    629 	protected void writeTreeTestFile(String parserName,
    630 									 String treeParserName,
    631 									 String lexerName,
    632 									 String parserStartRuleName,
    633 									 String treeParserStartRuleName,
    634 									 boolean debug)
    635 	{
    636 		ST outputFileST = new ST(
    637 			"import org.antlr.runtime.*;\n" +
    638 			"import org.antlr.runtime.tree.*;\n" +
    639 			"import org.antlr.runtime.debug.*;\n" +
    640 			"\n" +
    641 			"class Profiler2 extends Profiler {\n" +
    642 			"    public void terminate() { ; }\n" +
    643 			"}\n"+
    644 			"public class Test {\n" +
    645 			"    public static void main(String[] args) throws Exception {\n" +
    646 			"        CharStream input = new ANTLRFileStream(args[0]);\n" +
    647 			"        <lexerName> lex = new <lexerName>(input);\n" +
    648 			"        TokenRewriteStream tokens = new TokenRewriteStream(lex);\n" +
    649 			"        <createParser>\n"+
    650 			"        <parserName>.<parserStartRuleName>_return r = parser.<parserStartRuleName>();\n" +
    651 			"        <if(!treeParserStartRuleName)>\n" +
    652 			"        if ( r.tree!=null ) {\n" +
    653 			"            System.out.println(((Tree)r.tree).toStringTree());\n" +
    654 			"            ((CommonTree)r.tree).sanityCheckParentAndChildIndexes();\n" +
    655 			"		 }\n" +
    656 			"        <else>\n" +
    657 			"        CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
    658 			"        nodes.setTokenStream(tokens);\n" +
    659 			"        <treeParserName> walker = new <treeParserName>(nodes);\n" +
    660 			"        walker.<treeParserStartRuleName>();\n" +
    661 			"        <endif>\n" +
    662 			"    }\n" +
    663 			"}"
    664 			);
    665 		ST createParserST =
    666 			new ST(
    667 			"        Profiler2 profiler = new Profiler2();\n"+
    668 			"        <parserName> parser = new <parserName>(tokens,profiler);\n" +
    669 			"        profiler.setParser(parser);\n");
    670 		if ( !debug ) {
    671 			createParserST =
    672 				new ST(
    673 				"        <parserName> parser = new <parserName>(tokens);\n");
    674 		}
    675 		outputFileST.add("createParser", createParserST);
    676 		outputFileST.add("parserName", parserName);
    677 		outputFileST.add("treeParserName", treeParserName);
    678 		outputFileST.add("lexerName", lexerName);
    679 		outputFileST.add("parserStartRuleName", parserStartRuleName);
    680 		outputFileST.add("treeParserStartRuleName", treeParserStartRuleName);
    681 		writeFile(tmpdir, "Test.java", outputFileST.render());
    682 	}
    683 
    684 	/** Parser creates trees and so does the tree parser */
    685 	protected void writeTreeAndTreeTestFile(String parserName,
    686 											String treeParserName,
    687 											String lexerName,
    688 											String parserStartRuleName,
    689 											String treeParserStartRuleName,
    690 											boolean debug)
    691 	{
    692 		ST outputFileST = new ST(
    693 			"import org.antlr.runtime.*;\n" +
    694 			"import org.antlr.runtime.tree.*;\n" +
    695 			"import org.antlr.runtime.debug.*;\n" +
    696 			"\n" +
    697 			"class Profiler2 extends Profiler {\n" +
    698 			"    public void terminate() { ; }\n" +
    699 			"}\n"+
    700 			"public class Test {\n" +
    701 			"    public static void main(String[] args) throws Exception {\n" +
    702 			"        CharStream input = new ANTLRFileStream(args[0]);\n" +
    703 			"        <lexerName> lex = new <lexerName>(input);\n" +
    704 			"        TokenRewriteStream tokens = new TokenRewriteStream(lex);\n" +
    705 			"        <createParser>\n"+
    706 			"        <parserName>.<parserStartRuleName>_return r = parser.<parserStartRuleName>();\n" +
    707 			"        ((CommonTree)r.tree).sanityCheckParentAndChildIndexes();\n" +
    708 			"        CommonTreeNodeStream nodes = new CommonTreeNodeStream((Tree)r.tree);\n" +
    709 			"        nodes.setTokenStream(tokens);\n" +
    710 			"        <treeParserName> walker = new <treeParserName>(nodes);\n" +
    711 			"        <treeParserName>.<treeParserStartRuleName>_return r2 = walker.<treeParserStartRuleName>();\n" +
    712 			"		 CommonTree rt = ((CommonTree)r2.tree);\n" +
    713 			"		 if ( rt!=null ) System.out.println(((CommonTree)r2.tree).toStringTree());\n" +
    714 			"    }\n" +
    715 			"}"
    716 			);
    717 		ST createParserST =
    718 			new ST(
    719 			"        Profiler2 profiler = new Profiler2();\n"+
    720 			"        <parserName> parser = new <parserName>(tokens,profiler);\n" +
    721 			"        profiler.setParser(parser);\n");
    722 		if ( !debug ) {
    723 			createParserST =
    724 				new ST(
    725 				"        <parserName> parser = new <parserName>(tokens);\n");
    726 		}
    727 		outputFileST.add("createParser", createParserST);
    728 		outputFileST.add("parserName", parserName);
    729 		outputFileST.add("treeParserName", treeParserName);
    730 		outputFileST.add("lexerName", lexerName);
    731 		outputFileST.add("parserStartRuleName", parserStartRuleName);
    732 		outputFileST.add("treeParserStartRuleName", treeParserStartRuleName);
    733 		writeFile(tmpdir, "Test.java", outputFileST.render());
    734 	}
    735 
    736 	protected void writeTemplateTestFile(String parserName,
    737 										 String lexerName,
    738 										 String parserStartRuleName,
    739 										 boolean debug)
    740 	{
    741 		ST outputFileST = new ST(
    742 			"import org.antlr.runtime.*;\n" +
    743 			"import org.antlr.stringtemplate.*;\n" +
    744 			"import org.antlr.stringtemplate.language.*;\n" +
    745 			"import org.antlr.runtime.debug.*;\n" +
    746 			"import java.io.*;\n" +
    747 			"\n" +
    748 			"class Profiler2 extends Profiler {\n" +
    749 			"    public void terminate() { ; }\n" +
    750 			"}\n"+
    751 			"public class Test {\n" +
    752 			"    static String templates = \"group T; foo(x,y) ::= \\\"\\<x> \\<y>\\\"\";\n" +
    753 			"    static StringTemplateGroup group ="+
    754 			"    		new StringTemplateGroup(new StringReader(templates)," +
    755 			"					AngleBracketTemplateLexer.class);"+
    756 			"    public static void main(String[] args) throws Exception {\n" +
    757 			"        CharStream input = new ANTLRFileStream(args[0]);\n" +
    758 			"        <lexerName> lex = new <lexerName>(input);\n" +
    759 			"        CommonTokenStream tokens = new CommonTokenStream(lex);\n" +
    760 			"        <createParser>\n"+
    761 			"		 parser.setTemplateLib(group);\n"+
    762 			"        <parserName>.<parserStartRuleName>_return r = parser.<parserStartRuleName>();\n" +
    763 			"        if ( r.st!=null )\n" +
    764 			"            System.out.print(r.st.toString());\n" +
    765 			"	 	 else\n" +
    766 			"            System.out.print(\"\");\n" +
    767 			"    }\n" +
    768 			"}"
    769 			);
    770 		ST createParserST =
    771 			new ST(
    772 			"        Profiler2 profiler = new Profiler2();\n"+
    773 			"        <parserName> parser = new <parserName>(tokens,profiler);\n" +
    774 			"        profiler.setParser(parser);\n");
    775 		if ( !debug ) {
    776 			createParserST =
    777 				new ST(
    778 				"        <parserName> parser = new <parserName>(tokens);\n");
    779 		}
    780 		outputFileST.add("createParser", createParserST);
    781 		outputFileST.add("parserName", parserName);
    782 		outputFileST.add("lexerName", lexerName);
    783 		outputFileST.add("parserStartRuleName", parserStartRuleName);
    784 		writeFile(tmpdir, "Test.java", outputFileST.render());
    785 	}
    786 
    787     protected void eraseFiles(final String filesEndingWith) {
    788         File tmpdirF = new File(tmpdir);
    789         String[] files = tmpdirF.list();
    790         for(int i = 0; files!=null && i < files.length; i++) {
    791             if ( files[i].endsWith(filesEndingWith) ) {
    792                 new File(tmpdir+"/"+files[i]).delete();
    793             }
    794         }
    795     }
    796 
    797     protected void eraseFiles() {
    798         File tmpdirF = new File(tmpdir);
    799         String[] files = tmpdirF.list();
    800         for(int i = 0; files!=null && i < files.length; i++) {
    801             new File(tmpdir+"/"+files[i]).delete();
    802         }
    803     }
    804 
    805     protected void eraseTempDir() {
    806         File tmpdirF = new File(tmpdir);
    807         if ( tmpdirF.exists() ) {
    808             eraseFiles();
    809             tmpdirF.delete();
    810         }
    811     }
    812 
    813 	public String getFirstLineOfException() {
    814 		if ( this.stderrDuringParse ==null ) {
    815 			return null;
    816 		}
    817 		String[] lines = this.stderrDuringParse.split("\n");
    818 		String prefix="Exception in thread \"main\" ";
    819 		return lines[0].substring(prefix.length(),lines[0].length());
    820 	}
    821 
    822 	public List realElements(List elements) {
    823 		List n = new ArrayList();
    824 		for (int i = Label.NUM_FAUX_LABELS+Label.MIN_TOKEN_TYPE - 1; i < elements.size(); i++) {
    825 			Object o = (Object) elements.get(i);
    826 			if ( o!=null ) {
    827 				n.add(o);
    828 			}
    829 		}
    830 		return n;
    831 	}
    832 
    833 	public List<String> realElements(Map<String, Integer> elements) {
    834 		List n = new ArrayList();
    835 		Iterator iterator = elements.keySet().iterator();
    836 		while (iterator.hasNext()) {
    837 			String tokenID = (String) iterator.next();
    838 			if ( elements.get(tokenID) >= Label.MIN_TOKEN_TYPE ) {
    839 				n.add(tokenID+"="+elements.get(tokenID));
    840 			}
    841 		}
    842 		Collections.sort(n);
    843 		return n;
    844 	}
    845 
    846     public String sortLinesInString(String s) {
    847         String lines[] = s.split("\n");
    848         Arrays.sort(lines);
    849         List<String> linesL = Arrays.asList(lines);
    850         StringBuffer buf = new StringBuffer();
    851         for (String l : linesL) {
    852             buf.append(l);
    853             buf.append('\n');
    854         }
    855         return buf.toString();
    856     }
    857 
    858     /**
    859      * When looking at a result set that consists of a Map/HashTable
    860      * we cannot rely on the output order, as the hashing algorithm or other aspects
    861      * of the implementation may be different on differnt JDKs or platforms. Hence
    862      * we take the Map, convert the keys to a List, sort them and Stringify the Map, which is a
    863      * bit of a hack, but guarantees that we get the same order on all systems. We assume that
    864      * the keys are strings.
    865      *
    866      * @param m The Map that contains keys we wish to return in sorted order
    867      * @return A string that represents all the keys in sorted order.
    868      */
    869     public String sortMapToString(Map m) {
    870 
    871         System.out.println("Map toString looks like: " + m.toString());
    872         // Pass in crap, and get nothing back
    873         //
    874         if  (m == null) {
    875             return null;
    876         }
    877 
    878         // Sort the keys in the Map
    879         //
    880         TreeMap nset = new TreeMap(m);
    881 
    882         System.out.println("Tree map looks like: " + nset.toString());
    883         return nset.toString();
    884     }
    885 
    886     // override to track errors
    887 
    888     public void assertEquals(String msg, Object a, Object b) { try {Assert.assertEquals(msg,a,b);} catch (Error e) {lastTestFailed=true; throw e;} }
    889     public void assertEquals(Object a, Object b) { try {Assert.assertEquals(a,b);} catch (Error e) {lastTestFailed=true; throw e;} }
    890     public void assertEquals(String msg, long a, long b) { try {Assert.assertEquals(msg,a,b);} catch (Error e) {lastTestFailed=true; throw e;} }
    891     public void assertEquals(long a, long b) { try {Assert.assertEquals(a,b);} catch (Error e) {lastTestFailed=true; throw e;} }
    892 
    893     public void assertTrue(String msg, boolean b) { try {Assert.assertTrue(msg,b);} catch (Error e) {lastTestFailed=true; throw e;} }
    894     public void assertTrue(boolean b) { try {Assert.assertTrue(b);} catch (Error e) {lastTestFailed=true; throw e;} }
    895 
    896     public void assertFalse(String msg, boolean b) { try {Assert.assertFalse(msg,b);} catch (Error e) {lastTestFailed=true; throw e;} }
    897     public void assertFalse(boolean b) { try {Assert.assertFalse(b);} catch (Error e) {lastTestFailed=true; throw e;} }
    898 
    899     public void assertNotNull(String msg, Object p) { try {Assert.assertNotNull(msg, p);} catch (Error e) {lastTestFailed=true; throw e;} }
    900     public void assertNotNull(Object p) { try {Assert.assertNotNull(p);} catch (Error e) {lastTestFailed=true; throw e;} }
    901 
    902     public void assertNull(String msg, Object p) { try {Assert.assertNull(msg, p);} catch (Error e) {lastTestFailed=true; throw e;} }
    903     public void assertNull(Object p) { try {Assert.assertNull(p);} catch (Error e) {lastTestFailed=true; throw e;} }
    904 }
    905