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 */
28package org.antlr.test;
29
30
31import org.antlr.Tool;
32import org.antlr.analysis.Label;
33import org.antlr.runtime.CommonTokenStream;
34import org.antlr.runtime.Token;
35import org.antlr.runtime.TokenSource;
36import org.stringtemplate.v4.ST;
37import org.stringtemplate.v4.STGroup;
38import org.antlr.tool.ANTLRErrorListener;
39import org.antlr.tool.ErrorManager;
40import org.antlr.tool.GrammarSemanticsMessage;
41import org.antlr.tool.Message;
42import org.junit.After;
43import org.junit.Assert;
44import org.junit.Before;
45
46import javax.tools.*;
47import java.io.*;
48import java.util.*;
49
50
51public 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