xref: /aosp_15_r20/external/antlr/gunit/src/main/java/org/antlr/gunit/swingui/model/TestSuiteFactory.java (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1 /*
2  [The "BSD licence"]
3  Copyright (c) 2009 Shaoting Cai
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.gunit.swingui.model;
29 
30 import org.antlr.gunit.swingui.parsers.ANTLRv3Lexer;
31 import org.antlr.gunit.swingui.parsers.ANTLRv3Parser;
32 import org.antlr.gunit.swingui.parsers.StGUnitLexer;
33 import org.antlr.gunit.swingui.parsers.StGUnitParser;
34 import org.antlr.gunit.swingui.runner.TestSuiteAdapter;
35 import org.antlr.runtime.ANTLRReaderStream;
36 import org.antlr.runtime.CommonTokenStream;
37 import org.antlr.stringtemplate.StringTemplate;
38 import org.antlr.stringtemplate.StringTemplateGroup;
39 
40 import java.io.*;
41 import java.util.ArrayList;
42 import java.util.List;
43 
44 public class TestSuiteFactory {
45 
46     private static String TEMPLATE_FILE = "org/antlr/gunit/swingui/gunit.stg";
47     private static StringTemplateGroup templates;
48     public static final String TEST_SUITE_EXT = ".gunit";
49     public static final String GRAMMAR_EXT = ".g";
50 
51     static  {
52         ClassLoader loader = TestSuiteFactory.class.getClassLoader();
53         InputStream in = loader.getResourceAsStream(TEMPLATE_FILE);
54         if ( in == null ) {
55             throw new RuntimeException("internal error: Can't find templates "+TEMPLATE_FILE);
56         }
57         Reader rd = new InputStreamReader(in);
58         templates = new StringTemplateGroup(rd);
59     }
60 
61     /**
62      * Factory method: create a testsuite from ANTLR grammar.  Save the test
63      * suite file in the same directory of the grammar file.
64      * @param grammarFile ANTLRv3 grammar file.
65      * @return test suite object
66      */
createTestSuite(File grammarFile)67     public static TestSuite createTestSuite(File grammarFile) {
68         if(grammarFile != null && grammarFile.exists() && grammarFile.isFile()) {
69 
70             final String fileName = grammarFile.getName();
71             final String grammarName = fileName.substring(0, fileName.lastIndexOf('.'));
72             final String grammarDir = grammarFile.getParent();
73             final File testFile = new File(grammarDir + File.separator + grammarName + TEST_SUITE_EXT);
74 
75             final TestSuite result = new TestSuite(grammarName, testFile);
76             result.rules = loadRulesFromGrammar(grammarFile);
77 
78             if(saveTestSuite(result)) {
79                 return result;
80             } else {
81                 throw new RuntimeException("Can't save test suite file.");
82             }
83         } else {
84             throw new RuntimeException("Invalid grammar file.");
85         }
86     }
87 
88 
89     /* Load rules from an ANTLR grammar file. */
loadRulesFromGrammar(File grammarFile)90     private static List<Rule> loadRulesFromGrammar(File grammarFile) {
91 
92         // get all the rule names
93         final List<String> ruleNames = new ArrayList<String>();
94         try {
95             final Reader reader = new BufferedReader(new FileReader(grammarFile));
96             final ANTLRv3Lexer lexer = new ANTLRv3Lexer(new ANTLRReaderStream(reader));
97             final CommonTokenStream tokens = new CommonTokenStream(lexer);
98             final ANTLRv3Parser parser = new ANTLRv3Parser(tokens);
99             parser.rules = ruleNames;
100             parser.grammarDef();
101             reader.close();
102         } catch (Exception e) {
103             e.printStackTrace();
104         }
105 
106         // convert to rule object
107         final List<Rule> ruleList = new ArrayList<Rule>();
108         for(String str: ruleNames) {
109             ruleList.add(new Rule(str));
110         }
111 
112         return ruleList;
113     }
114 
115     /* Save testsuite to *.gunit file. */
saveTestSuite(TestSuite testSuite)116     public static boolean saveTestSuite(TestSuite testSuite) {
117         final String data = getScript(testSuite);
118         try {
119             FileWriter fw = new FileWriter(testSuite.getTestSuiteFile());
120             fw.write(data);
121             fw.flush();
122             fw.close();
123         } catch (IOException e) {
124             e.printStackTrace();
125             return false;
126         }
127         return true;
128     }
129 
130     /**
131      * Get the text script from the testSuite.
132      * @param testSuite
133      * @return test script
134      */
getScript(TestSuite testSuite)135     public static String getScript(TestSuite testSuite) {
136         if(testSuite == null) return null;
137         StringTemplate gUnitScript = templates.getInstanceOf("gUnitFile");
138         gUnitScript.setAttribute("testSuite", testSuite);
139 
140         return gUnitScript.toString();
141     }
142 
143     /**
144      * From textual script to program model.
145      * @param file testsuite file (.gunit)
146      * @return test suite object
147      */
loadTestSuite(File file)148     public static TestSuite loadTestSuite(File file) {
149         if ( file.getName().endsWith(GRAMMAR_EXT) ) {
150             throw new RuntimeException(file.getName()+" is a grammar file not a gunit file");
151         }
152         // check grammar file
153         final File grammarFile = getGrammarFile(file);
154         if(grammarFile == null)
155             throw new RuntimeException("Can't find grammar file associated with gunit file: "+file.getAbsoluteFile());
156 
157         TestSuite result = new TestSuite("", file);
158 
159         // read in test suite
160         try {
161             final Reader reader = new BufferedReader(new FileReader(file));
162             final StGUnitLexer lexer = new StGUnitLexer(new ANTLRReaderStream(reader));
163             final CommonTokenStream tokens = new CommonTokenStream(lexer);
164             final StGUnitParser parser = new StGUnitParser(tokens);
165             final TestSuiteAdapter adapter = new TestSuiteAdapter(result);
166             parser.adapter = adapter;
167             parser.gUnitDef();
168             result.setTokens(tokens);
169             reader.close();
170         } catch (Exception ex) {
171             throw new RuntimeException("Error reading test suite file.\n" + ex.getMessage());
172         }
173 
174         // load un-tested rules from grammar
175         final List<Rule> completeRuleList = loadRulesFromGrammar(grammarFile);
176         for(Rule rule: completeRuleList) {
177             if(!result.hasRule(rule)) {
178                 result.addRule(rule);
179                 //System.out.println("Add rule:" + rule);
180             }
181         }
182 
183         return result;
184     }
185 
186     /**
187      * Get the grammar file of the testsuite file in the same directory.
188      * @param testsuiteFile
189      * @return grammar file or null
190      */
getGrammarFile(File testsuiteFile)191     private static File getGrammarFile(File testsuiteFile) {
192         String sTestFile;
193         try {
194             sTestFile = testsuiteFile.getCanonicalPath();
195         }
196         catch (IOException e) {
197             return null;
198         }
199         // Try Foo.g from Foo.gunit
200         String fname =
201             sTestFile.substring(0, sTestFile.lastIndexOf('.')) + GRAMMAR_EXT;
202         File fileGrammar = new File(fname);
203         if(fileGrammar.exists() && fileGrammar.isFile()) return fileGrammar;
204         // Try FooParser.g from Foo.gunit
205         fname = sTestFile.substring(0, sTestFile.lastIndexOf('.'))+"Parser"+GRAMMAR_EXT;
206         if(fileGrammar.exists() && fileGrammar.isFile()) return fileGrammar;
207         return fileGrammar;
208     }
209 }
210