KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > lexer > test > dump > TokenDumpCheck


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.lib.lexer.test.dump;
21
22 import java.io.File JavaDoc;
23 import java.io.FileNotFoundException JavaDoc;
24 import java.io.FileReader JavaDoc;
25 import java.io.FileWriter JavaDoc;
26 import java.nio.CharBuffer JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.List JavaDoc;
30 import org.netbeans.api.lexer.Language;
31 import org.netbeans.api.lexer.Token;
32 import org.netbeans.api.lexer.TokenHierarchy;
33 import org.netbeans.api.lexer.TokenHierarchy;
34 import org.netbeans.api.lexer.TokenId;
35 import org.netbeans.api.lexer.TokenSequence;
36 import org.netbeans.api.lexer.TokenUtilities;
37 import org.netbeans.junit.NbTestCase;
38 import org.netbeans.lib.editor.util.CharSequenceUtilities;
39 import org.netbeans.lib.lexer.batch.BatchTokenList;
40 import org.netbeans.lib.lexer.test.LexerTestUtilities;
41
42 /**
43  * Check whether generated token dump corresponds to the one read from a file.
44  *
45  * @author mmetelka
46  */

47 public final class TokenDumpCheck {
48     
49     public static void checkTokenDump(NbTestCase test, String JavaDoc relFilePath,
50     Language<? extends TokenId> language) throws Exception JavaDoc {
51         // Request lookaheads and states maintaining
52
boolean origMaintainLAState = BatchTokenList.isMaintainLAState();
53         BatchTokenList.setMaintainLAState(true);
54         try {
55             File JavaDoc wholeInputFile = new File JavaDoc(test.getDataDir(), relFilePath);
56             if (!wholeInputFile.exists()) {
57                 NbTestCase.fail("File " + wholeInputFile + " not found.");
58             }
59             String JavaDoc wholeInput = readFile(test, wholeInputFile);
60             // Scan for EOF markers and create multiple char sequences
61
TokenHierarchy<?> hi = TokenHierarchy.create(wholeInput, TokenDumpTokenId.language());
62             TokenSequence<TokenDumpTokenId> ts = hi.tokenSequence(TokenDumpTokenId.language());
63             boolean afterEOF = true; // Ignore newlines when after eof
64
boolean newline = false;
65             int textStartIndex = 0;
66             List JavaDoc<String JavaDoc> inputs = new ArrayList JavaDoc<String JavaDoc>();
67             List JavaDoc<String JavaDoc> testNames = new ArrayList JavaDoc<String JavaDoc>();
68             // Estimate 4 subtests equally long
69
StringBuilder JavaDoc inputBuffer = new StringBuilder JavaDoc(wholeInput.length() / 4);
70             String JavaDoc testName = "<Unnamed test>";
71             while (ts.moveNext()) {
72                 Token<TokenDumpTokenId> token = ts.token();
73                 switch (token.id()) {
74                     case NEWLINE:
75                         if (newline) { // Was empty line
76
inputBuffer.append('\n');
77                         }
78                         if (!afterEOF) {
79                             newline = true;
80                         }
81                         break;
82
83                     case TEST_NAME:
84                         testName = token.text().toString();
85                         ts.moveNext(); // skip newline (might be false for EOF)
86
newline = false;
87                         break;
88
89                     case EOF_VIRTUAL:
90                         // All except newline-eof_mark-newline
91
ts.moveNext(); // skip newline (might be false for EOF)
92
newline = false;
93                         inputs.add(inputBuffer.toString());
94                         inputBuffer.setLength(0);
95                         testNames.add(testName);
96                         testName = "<Unnamed test>";
97                         afterEOF = true;
98                         break;
99
100                     case TEXT:
101                         if (newline) {
102                             inputBuffer.append('\n');
103                             newline = false;
104                         }
105                         inputBuffer.append(token.text());
106                         afterEOF = false;
107                         break;
108
109                     default:
110                         if (TokenDumpTokenId.isCharLiteral(token.id())) {
111                             Character JavaDoc ch = (Character JavaDoc)token.getProperty(TokenDumpTokenId.UNICODE_CHAR_TOKEN_PROPERTY);
112                             assert (ch != null);
113                             inputBuffer.append(ch);
114                         } else {
115                             throw new IllegalStateException JavaDoc("Unknown token id=" + token.id());
116                         }
117                         ts.moveNext(); // skip newline (might be false for EOF)
118
newline = false;
119                         afterEOF = false;
120                         
121                 }
122             }
123             inputs.add(inputBuffer.toString());
124             testNames.add(testName);
125
126             // Check whether token dump file exists
127
// Try to remove "/build/" from the dump file name if it exists.
128
// Otherwise give a warning.
129
File JavaDoc tokenDescInputFile = new File JavaDoc(test.getDataDir(), relFilePath + ".tokens.txt");
130             String JavaDoc tokenDescInputFilePath = tokenDescInputFile.getAbsolutePath();
131             boolean replaced = false;
132             if (tokenDescInputFilePath.indexOf("/build/test/") != -1) {
133                 tokenDescInputFilePath = tokenDescInputFilePath.replace("/build/test/", "/test/");
134                 replaced = true;
135             }
136             if (!replaced && tokenDescInputFilePath.indexOf("/test/work/sys/") != -1) {
137                 tokenDescInputFilePath = tokenDescInputFilePath.replace("/test/work/sys/", "/test/unit/");
138                 replaced = true;
139             }
140             if (!replaced) {
141                 System.err.println("Warning: Attempt to use tokens dump file " +
142                         "from sources instead of the generated test files failed.\n" +
143                         "Patterns '/build/test/' or '/test/work/sys/' not found in " + tokenDescInputFilePath
144                 );
145             }
146             tokenDescInputFile = new File JavaDoc(tokenDescInputFilePath);
147             
148             String JavaDoc tokenDescInput = null;
149             if (tokenDescInputFile.exists()) {
150                 tokenDescInput = readFile(test, tokenDescInputFile);
151             }
152             TokenDescCompare tdc = new TokenDescCompare(tokenDescInput, tokenDescInputFile);
153
154             // Check individual token descriptions
155
StringBuilder JavaDoc tokenDesc = new StringBuilder JavaDoc(40);
156             for (int i = 0; i < inputs.size(); i++) {
157                 String JavaDoc input = inputs.get(i);
158                 testName = testNames.get(i);
159                 tdc.setTestName(testName);
160                 TokenHierarchy<?> langHi = TokenHierarchy.create(input, language);
161                 TokenSequence<? extends TokenId> langTS = langHi.tokenSequence();
162                 tdc.compareLine(testName, -1);
163                 while (langTS.moveNext()) {
164                     // Debug the token
165
Token<? extends TokenId> token = langTS.token();
166                     tokenDesc.append(token.id().name());
167                     int spaceCount = 14 - token.id().name().length();
168                     while (--spaceCount >= 0) {
169                         tokenDesc.append(' ');
170                     }
171                     tokenDesc.append(" \"");
172                     tokenDesc.append(TokenUtilities.debugText(token.text()));
173                     tokenDesc.append('"');
174                     int lookahead = LexerTestUtilities.lookahead(langTS);
175                     if (lookahead > 0) {
176                         tokenDesc.append(", la=");
177                         tokenDesc.append(lookahead);
178                     }
179                     Object JavaDoc state = LexerTestUtilities.state(langTS);
180                     if (state != null) {
181                         tokenDesc.append(", st=");
182                         tokenDesc.append(state);
183                     }
184                     tdc.compareLine(tokenDesc, langTS.index());
185                     tokenDesc.setLength(0);
186                 }
187                 tdc.compareLine("----- EOF -----\n", -1);
188             }
189             tdc.finish(); // Write token desc file if necessary
190

191         } finally {
192             BatchTokenList.setMaintainLAState(origMaintainLAState);
193         }
194     }
195     
196     private static String JavaDoc readFile(NbTestCase test, File JavaDoc f) throws Exception JavaDoc {
197         FileReader JavaDoc r = new FileReader JavaDoc(f);
198         int fileLen = (int)f.length();
199         CharBuffer JavaDoc cb = CharBuffer.allocate(fileLen);
200         r.read(cb);
201         cb.rewind();
202         return cb.toString();
203     }
204     
205     private static final class TokenDescCompare implements CharSequence JavaDoc {
206         
207         private String JavaDoc input;
208         
209         private int inputIndex;
210         
211         private int textLength;
212         
213         private StringBuilder JavaDoc output;
214         
215         private File JavaDoc outputFile;
216         
217         private int[] lineBoundsIndexes = new int[2 * 3]; // last three lines [start,end]
218

219         private String JavaDoc testName;
220         
221         TokenDescCompare(String JavaDoc input, File JavaDoc outputFile) {
222             this.input = input;
223             this.outputFile = outputFile;
224             Arrays.fill(lineBoundsIndexes, -1);
225             if (input == null)
226                 output = new StringBuilder JavaDoc(100);
227         }
228         
229         public void compareLine(CharSequence JavaDoc text, int tokenIndex) {
230             if (input != null) {
231                 textLength = text.length();
232                 if (input.length() - inputIndex < textLength || !TokenUtilities.equals(text, this)) {
233                     StringBuilder JavaDoc msg = new StringBuilder JavaDoc(100);
234                     msg.append("\nDump file ");
235                     msg.append(outputFile);
236                     msg.append(":\n");
237                     msg.append(testName);
238                     msg.append(":\n");
239                     if (tokenIndex >= 0) {
240                         msg.append("Invalid token description in dump file (tokenIndex=");
241                         msg.append(tokenIndex);
242                         msg.append("):");
243                     } else {
244                         msg.append("Invalid text in dump file:");
245                     }
246                     msg.append("\n ");
247                     msg.append(input.subSequence(inputIndex, findEOL(inputIndex)));
248                     msg.append("\nExpected:\n ");
249                     msg.append(text);
250                     msg.append("\nPrevious context:\n");
251                     for (int i = 0; i < lineBoundsIndexes.length; i += 2) {
252                         int start = lineBoundsIndexes[i];
253                         if (start != -1) {
254                             msg.append(" ");
255                             msg.append(input.subSequence(start, lineBoundsIndexes[i + 1]));
256                             msg.append('\n');
257                         }
258                     }
259                     NbTestCase.fail(msg.toString());
260                     
261                 }
262                 System.arraycopy(lineBoundsIndexes, 2, lineBoundsIndexes, 0, lineBoundsIndexes.length - 2);
263                 lineBoundsIndexes[lineBoundsIndexes.length - 2] = inputIndex;
264                 inputIndex += textLength;
265                 lineBoundsIndexes[lineBoundsIndexes.length - 1] = inputIndex;
266                 inputIndex = skipEOL(inputIndex);
267
268             } else {
269                 output.append(text);
270                 String JavaDoc ls = (String JavaDoc) System.getProperty("line.separator"); // NOI18N
271
output.append(ls);
272             }
273         }
274         
275         public void finish() throws Exception JavaDoc {
276             if (input == null) {
277                 if (!outputFile.createNewFile()) {
278                     NbTestCase.fail("Cannot create file " + outputFile);
279                 }
280                 FileWriter JavaDoc fw = new FileWriter JavaDoc(outputFile);
281                 try {
282                     fw.write(output.toString());
283                 } finally {
284                     fw.close();
285                 }
286                 NbTestCase.fail("Created tokens dump file " + outputFile + "\nPlease re-run the test.");
287
288             } else {
289                 if (inputIndex < input.length()) {
290                     NbTestCase.fail("Some text left unread:" + input.substring(inputIndex));
291                 }
292             }
293         }
294         
295         public void setTestName(String JavaDoc testName) {
296             this.testName = testName;
297         }
298
299         public char charAt(int index) {
300             CharSequenceUtilities.checkIndexValid(index, length());
301             return input.charAt(inputIndex + index);
302         }
303
304         public int length() {
305             return textLength;
306         }
307
308         public CharSequence JavaDoc subSequence(int start, int end) {
309             CharSequenceUtilities.checkIndexesValid(this, start, end);
310             return input.substring(inputIndex + start, inputIndex + end);
311         }
312         
313         private int findEOL(int start) {
314             while (start < input.length()) {
315                 switch (input.charAt(start)) {
316                     case '\r':
317                     case '\n':
318                         return start;
319                 }
320                 start++;
321             }
322             return start;
323         }
324         
325         private int skipEOL(int index) {
326             if (index < input.length()) {
327                 index++; // skip separator char
328
if (input.charAt(index - 1) == '\r')
329                     if (index < input.length() && input.charAt(index) == '\n')
330                         index++; // CRLF
331
}
332             return index;
333         }
334                     
335     }
336     
337 }
338
Popular Tags