KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > lexer > demo > LexerRandomTest


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.modules.lexer.demo;
21
22 import java.util.List JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import javax.swing.text.BadLocationException JavaDoc;
26 import javax.swing.text.Document JavaDoc;
27 import javax.swing.text.PlainDocument JavaDoc;
28 import javax.swing.event.DocumentListener JavaDoc;
29 import javax.swing.event.DocumentEvent JavaDoc;
30 import org.netbeans.api.lexer.Language;
31 import org.netbeans.api.lexer.LexerInput;
32 import org.netbeans.api.lexer.TokenUpdater;
33 import org.netbeans.api.lexer.Token;
34 import org.netbeans.api.lexer.Lexer;
35 import org.netbeans.spi.lexer.util.LexerTestDescription;
36 import org.netbeans.spi.lexer.util.LexerUtilities;
37
38 /**
39  * Random test that helps to test lexer correctness.
40  * Document is created and updated by subsequent modifications.
41  * After each modification the token updater updates token elements
42  * of the document and compares them to another token list
43  * created by batch lexing of the entire document.
44  * <BR>If the two token lists do not match it means that the lexer
45  * must be fixed otherwise it would not function well
46  * in the incremental setting.
47  * <BR><CODE>createLexer()</CODE> can be overriden if necessary.
48  *
49  * @author Miloslav Metelka
50  * @version 1.00
51  */

52
53 public class LexerRandomTest extends DemoTokenUpdater {
54     
55     private LexerTestDescription td;
56     
57     private int debugLevel;
58
59     public LexerRandomTest(LexerTestDescription td, boolean maintainLookbacks) {
60         super(new PlainDocument JavaDoc(), td.getLanguage(), maintainLookbacks);
61
62         this.td = td;
63         debugLevel = td.getDebugLevel();
64     }
65     
66     public void test() {
67         LexerTestDescription.TestRound[] rounds = td.getTestRounds();
68
69         // Fill in insertItems list
70
List JavaDoc insertItems = new ArrayList JavaDoc();
71         LexerTestDescription.TestChar[] testChars = td.getTestChars();
72         if (testChars != null) {
73             insertItems.addAll(Arrays.asList(testChars));
74         }
75         LexerTestDescription.TestCharInterval[] testCharIntervals = td.getTestCharIntervals();
76         if (testCharIntervals != null) {
77             insertItems.addAll(Arrays.asList(testCharIntervals));
78         }
79         LexerTestDescription.TestString[] testStrings = td.getTestStrings();
80         if (testStrings != null) {
81             insertItems.addAll(Arrays.asList(testStrings));
82         }
83     
84         // Compute total insertItemsRatioSum
85
double insertItemsRatioSum = 0;
86         int insertItemsLength = insertItems.size();
87         for (int i = 0; i < insertItemsLength; i++) {
88             insertItemsRatioSum += getInsertRatio(insertItems.get(i));
89         }
90         
91         int maxDocumentLength = td.getMaxDocumentLength();
92
93         Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
94         System.err.println("Test started ...");
95         long tm = System.currentTimeMillis();
96
97         for (int i = 0; i < rounds.length; i++) {
98             LexerTestDescription.TestRound r = rounds[i];
99             
100             System.out.println("Test round: " + r);
101             
102             int operationCount = r.getOperationCount();
103             double insertRatio = r.getInsertRatio();
104             int maxInsertLength = r.getMaxInsertLength();
105             double removeRatio = r.getRemoveRatio();
106             int maxRemoveLength = r.getMaxRemoveLength();
107
108             double operationRatioSum = r.getInsertRatio() + r.getRemoveRatio();
109
110             // Test string for not yet completed insert or null if no incomplete string
111
String JavaDoc incompleteString = null;
112             int incompleteStringRemainLength = 0;
113             int incompleteStringInsertOffset = 0;
114             
115             // force remove after extra insert due to previous forced insert of incomplete string
116
boolean forceRemove = false;
117             
118             int moduloOperationCount = operationCount / 10;
119             while (--operationCount >= 0) {
120                 double operationRatio = Math.random() * operationRatioSum;
121                 operationRatio -= insertRatio;
122                 if (forceRemove || getDocument().getLength() > maxDocumentLength) {
123                     operationRatio = 0;
124                 }
125
126                 if (operationRatio < 0 || incompleteString != null) { // do insert
127
StringBuffer JavaDoc insertBuffer = new StringBuffer JavaDoc();
128                     int insertLength = (int)(maxInsertLength * Math.random()) + 1;
129                     int insertOffset = (int)((getDocument().getLength() + 1) * Math.random());
130                     if (incompleteString != null && operationRatio >= 0) { // would be remove normally
131
insertLength = Math.min(insertLength, incompleteStringRemainLength);
132                     }
133                     
134                     if (incompleteString != null) {
135                         insertOffset = incompleteStringInsertOffset;
136
137                         int isLen = incompleteString.length();
138                         
139                         if (incompleteStringRemainLength <= insertLength) {
140                             insertLength -= incompleteStringRemainLength;
141                             insertBuffer.append(incompleteString.substring(
142                                 isLen - incompleteStringRemainLength));
143
144                             insertLength -= incompleteStringRemainLength;
145                             incompleteString = null;
146                             incompleteStringRemainLength = 0;
147                             
148                         } else { // incomplete string is longer than insert length
149
insertBuffer.append(incompleteString.substring(
150                                 isLen - incompleteStringRemainLength,
151                                 isLen - incompleteStringRemainLength + insertLength
152                             ));
153
154                             incompleteStringRemainLength -= insertLength;
155                             insertLength = 0;
156                         }
157                     }
158                     
159
160                     while (insertLength > 0) {
161                         double insertItemsRatio = Math.random() * insertItemsRatioSum;
162                         for (int j = 0; j < insertItemsLength; j++) {
163                             Object JavaDoc item = insertItems.get(j);
164                             insertItemsRatio -= getInsertRatio(item);
165                             if (insertItemsRatio < 0) {
166                                 // Perform insert
167
if (item instanceof LexerTestDescription.TestChar) {
168                                     LexerTestDescription.TestChar tc = (LexerTestDescription.TestChar)item;
169                                     insertBuffer.append(tc.getChar());
170                                     insertLength--;
171                                     
172                                 } else if (item instanceof LexerTestDescription.TestCharInterval) {
173                                     LexerTestDescription.TestCharInterval tci
174                                         = (LexerTestDescription.TestCharInterval)item;
175                                     insertBuffer.append((char)(tci.getChar()
176                                         + ((tci.getLastChar() - tci.getChar() + 1) * Math.random())));
177                                     insertLength--;
178                                     
179                                 } else if (item instanceof LexerTestDescription.TestString) {
180                                     LexerTestDescription.TestString ts = (LexerTestDescription.TestString)item;
181                                     String JavaDoc s = ts.getString();
182                                     int sLen = s.length();
183                                     if (sLen <= insertLength) {
184                                         insertBuffer.append(s);
185                                         insertLength -= insertLength;
186                                         
187                                     } else { // sLen > insertLength
188
insertBuffer.append(s.substring(0, insertLength));
189                                         incompleteString = s;
190                                         incompleteStringRemainLength = sLen - insertLength;
191                                         insertLength = 0;
192                                     }
193                                     
194                                 } else { // unsupported
195
throw new IllegalStateException JavaDoc();
196                                 }
197
198                                 break;
199                             }
200                         }
201                     }
202
203                     String JavaDoc text = insertBuffer.toString();
204                     try {
205                         if (debugLevel > 0) {
206                             System.err.print("+Insert");
207
208                             if (debugLevel >= 2) { // debug text
209
System.err.print(" \"" + LexerUtilities.toSource(text) + '"');
210                             }
211
212                             System.err.print(" at offset=" + insertOffset
213                                 + "(" + getDocument().getLength() + "), length="
214                                 + text.length()
215                             );
216                         }
217
218                         getDocument().insertString(insertOffset, text, null);
219                         
220                         if (debugLevel >= 3) { // debug doc text
221
System.err.print(", docText=\"" + LexerUtilities.toSource(getDocText(getDocument())) + "\"");
222                         }
223                         
224                         incompleteStringInsertOffset = insertOffset + text.length();
225                     } catch (BadLocationException JavaDoc e) {
226                         throw new IllegalStateException JavaDoc(e.toString());
227                     }
228
229                 } else { // not insert
230
operationRatio -= removeRatio;
231                     if (operationRatio < 0 || forceRemove) { // do remove
232
forceRemove = false;
233
234                         int removeLength = (int)(maxRemoveLength * Math.random()) + 1;
235                         removeLength = Math.min(removeLength, getDocument().getLength());
236
237                         int removeOffset = (int)((getDocument().getLength() - removeLength + 1) * Math.random());
238                         try {
239                             if (debugLevel > 0) {
240                                 System.err.print("-Remove");
241
242                                 if (debugLevel >= 2) {
243                                     String JavaDoc text = getDocument().getText(removeOffset, removeLength);
244                                     System.err.print(" \"" + LexerUtilities.toSource(text) + '"');
245                                 }
246
247                                 System.err.print(" at offset=" + removeOffset
248                                     + "(" + getDocument().getLength() + "), length=" + removeLength);
249
250                             }
251
252                             getDocument().remove(removeOffset, removeLength);
253
254                             if (debugLevel >= 3) {
255                                 System.err.print(", docText=\"" + LexerUtilities.toSource(getDocText(getDocument())) + "\"");
256                             }
257                         } catch (BadLocationException JavaDoc e) {
258                             throw new IllegalStateException JavaDoc(e.toString());
259                         }
260                     }
261                 }
262
263                 // Test the correctness of tokens produced by algorithm
264
// by true batch lexing with a fresh instance of lexer
265
int tokenIndex = 0; // need to reference if exception thrown
266
try {
267                     ArrayList JavaDoc lbList = new ArrayList JavaDoc();
268                     String JavaDoc docText;
269                     try {
270                         docText = getDocument().getText(0, getDocument().getLength());
271                     } catch (BadLocationException JavaDoc e) {
272                         throw new IllegalStateException JavaDoc(e.toString());
273                     }
274                     LexerInput input = new StringLexerInput(docText);
275                     Lexer lexer = getLanguage().createLexer();
276                     lexer.restart(input, null);
277
278                     int shift = relocate(0);
279                     if (shift != 0) {
280                         throw new IllegalStateException JavaDoc("Invalid relocate shift="
281                             + shift);
282                     }
283
284                     int tokenTotalLength = 0;
285                     int lbOffset = 0;
286                     while (true) {
287                         Token token = lexer.nextToken();
288                         if (token != null) {
289                             Token itToken = next();
290                             checkTokensEqual(itToken, token);
291                             int tokenLength = token.getText().length();
292                             tokenTotalLength += tokenLength;
293
294                             int la = getLookahead();
295                             if (input.getReadLookahead() != la) {
296                                 throw new IllegalStateException JavaDoc("incremental environment lookahead=" + la
297                                     + ", batch lexer lookahead=" + input.getReadLookahead());
298                             }
299
300                             Object JavaDoc state = getState();
301                             Object JavaDoc lexerState = lexer.getState();
302                             if (!((state == null && lexerState == null)
303                                     || (state != null && state.equals(lexerState))
304                             )) {
305                                 throw new IllegalStateException JavaDoc(
306                                     "States do not match incremental environment lexer-state=" + state
307                                     + ", batch lexer state=" + lexerState);
308                             }
309
310                             lbList.add(new Integer JavaDoc(tokenLength));
311                             lbList.add(new Integer JavaDoc(la));
312
313                             while (lbList.size() > 0) {
314                                 int tlen = ((Integer JavaDoc)lbList.get(0)).intValue();
315                                 int tla = ((Integer JavaDoc)lbList.get(1)).intValue();
316                                 if (lbOffset + tlen + tla <= tokenTotalLength) {
317                                     lbOffset += tlen;
318                                     lbList.remove(0); // remove len
319
lbList.remove(0); // remove la
320
} else {
321                                     break;
322                                 }
323                             }
324
325                             int lb = getLookback();
326                             if (lb >= 0) {
327                                 if (lb != lbList.size() / 2) {
328                                     throw new IllegalStateException JavaDoc("iterator-lb="
329                                         + lb
330                                         + ", lexer-lb=" + (lbList.size() / 2)
331                                     );
332                                 }
333                             }
334
335                             tokenIndex++;
336
337                         } else { // no more tokens
338
if (hasNext()) {
339                                 throw new IllegalStateException JavaDoc();
340                             }
341                             if (tokenTotalLength != docText.length()) {
342                                 throw new IllegalStateException JavaDoc();
343                             }
344                             break;
345                         }
346                     }
347
348                     if (debugLevel > 0) {
349                         System.err.println(", " + tokenIndex + " tokens");
350                     }
351
352                     if (operationCount > 0 && (operationCount % moduloOperationCount) == 0) {
353                         System.err.println(operationCount
354                             + " operations remain. docLength=" + getDocument().getLength()
355                             + ", tokenCount=" + tokenIndex
356                         );
357                     }
358
359                 } catch (RuntimeException JavaDoc e) {
360                     try {
361                         System.err.println("\n\nException thrown - document text=\""
362                             + LexerUtilities.toSource(getDocument().getText(
363                                 0, getDocument().getLength()))
364                             + "\"\ntokens:\n" + allTokensToString()
365                             + "tokenIndex=" + tokenIndex);
366
367                     } catch (BadLocationException JavaDoc ex) {
368                         throw new IllegalStateException JavaDoc(ex.toString());
369                     }
370                     throw e; // rethrow
371
}
372
373             } // while (--operationCount >= 0)
374
}
375
376         System.err.println("Test finished in "
377             + (System.currentTimeMillis() - tm) / 1000
378             + " seconds."
379         );
380     }
381     
382     private static double getInsertRatio(Object JavaDoc o) {
383         if (o instanceof LexerTestDescription.TestChar) {
384             return ((LexerTestDescription.TestChar)o).getInsertRatio();
385         } else if (o instanceof LexerTestDescription.TestCharInterval) {
386             return ((LexerTestDescription.TestCharInterval)o).getInsertRatio();
387         } else if (o instanceof LexerTestDescription.TestString) {
388             return ((LexerTestDescription.TestString)o).getInsertRatio();
389         } else {
390             throw new IllegalArgumentException JavaDoc();
391         }
392     }
393     
394     private void dump() {
395         System.err.println("Dump of token iterator\n"
396             + allTokensToString());
397     }
398     
399     private static void checkTokensEqual(Token t1, Token t2) {
400         if (t1.getId() != t2.getId()) {
401             throw new IllegalStateException JavaDoc("t1.id=" + t1.getId()
402                 + ", t2.id=" + t2.getId());
403         }
404         
405         CharSequence JavaDoc t1Text = t1.getText();
406         CharSequence JavaDoc t2Text = t2.getText();
407         if (t1Text.length() != t2Text.length()) {
408             throw new IllegalStateException JavaDoc(
409                 "t1=\"" + LexerUtilities.toSource(t1Text.toString())
410                 + "\", t2=\"" + LexerUtilities.toSource(t2Text.toString())
411                 + '"'
412             );
413         }
414         for (int i = t1Text.length() - 1; i >= 0; i--) {
415             if (t1Text.charAt(i) != t2Text.charAt(i)) {
416                 throw new IllegalStateException JavaDoc();
417             }
418         }
419     }
420     
421     private static String JavaDoc getDocText(Document JavaDoc doc) {
422         try {
423             return doc.getText(0, doc.getLength());
424         } catch (BadLocationException JavaDoc e) {
425             throw new IllegalStateException JavaDoc();
426         }
427     }
428
429     public static void main (String JavaDoc[] args) {
430         try {
431             if (args.length == 0) {
432                 System.err.println("Usage: java " + LexerRandomTest.class.getName ()
433                     + " <test-description-class-name>");
434                 System.exit(1);
435             }
436
437             Class JavaDoc langCls = Class.forName(args[0]);
438             LexerTestDescription td = (LexerTestDescription)langCls.newInstance();
439             
440             new LexerRandomTest(td, false).test();
441
442         } catch (Exception JavaDoc ex) {
443             ex.printStackTrace();
444         }
445     }
446
447 }
448
449
Popular Tags