KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > lexer > test > TestRandomModify


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;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Random JavaDoc;
25 import javax.swing.text.Document JavaDoc;
26 import org.netbeans.api.lexer.Language;
27 import org.netbeans.api.lexer.TokenHierarchy;
28 import org.netbeans.api.lexer.TokenId;
29 import org.netbeans.lib.editor.util.CharSequenceUtilities;
30
31
32 /**
33  * Test lexer implementation for correctness by doing random
34  * inserts/removals of random characters.
35  *
36  * @author mmetelka
37  */

38 public class TestRandomModify {
39
40     private boolean debugOperation;
41
42     private boolean debugHierarchy;
43
44     private boolean debugDocumentText;
45     
46     private boolean skipLexerConsistencyCheck;
47     
48     private Random JavaDoc random;
49     
50     private Document JavaDoc doc;
51     
52     private int opId;
53     
54     private int maxDocLength;
55     
56     private List JavaDoc<SnapshotDescription> snapshots = new ArrayList JavaDoc<SnapshotDescription>();
57
58     public TestRandomModify() {
59         this(0);
60     }
61     
62     public TestRandomModify(long seed) {
63         this.doc = new javax.swing.text.PlainDocument JavaDoc();
64
65         this.random = new Random JavaDoc();
66         if (seed == 0) { // Use currentTimeMillis() (btw nanoTime() in 1.5 instead)
67
seed = System.currentTimeMillis();
68         }
69         System.err.println("TestRandomModify with SEED=" + seed + "L");
70         random.setSeed(seed);
71     }
72     
73     public boolean isDebugOperation() {
74         return debugOperation;
75     }
76     
77     /**
78      * Set whether info about each operation being performed in token hierarchy
79      * should be dumped to system err after each operation.
80      */

81     public void setDebugOperation(boolean debugOperation) {
82         this.debugOperation = debugOperation;
83     }
84
85     public boolean isDebugHierarchy() {
86         return debugHierarchy;
87     }
88     
89     /**
90      * Set whether complete text of the modified document
91      * should be dumped to system err after each operation.
92      */

93     public void setDebugHierarchy(boolean debugHierarchy) {
94         this.debugHierarchy = debugHierarchy;
95     }
96
97     public boolean isDebugDocumentText() {
98         return debugDocumentText;
99     }
100     
101     /**
102      * Set whether contents of the token hierarchy being tested
103      * should be dumped to system err after each operation.
104      */

105     public void setDebugDocumentText(boolean debugDocumentText) {
106         this.debugDocumentText = debugDocumentText;
107     }
108     
109     public boolean isSkipLexerConsistencyCheck() {
110         return skipLexerConsistencyCheck;
111     }
112     
113     public void setSkipLexerConsistencyCheck(boolean skipLexerConsistencyCheck) {
114         this.skipLexerConsistencyCheck = skipLexerConsistencyCheck;
115     }
116
117     public void test(RandomModifyDescriptor[] randomModifyDescriptors) throws Exception JavaDoc {
118         for (int i = 0; i < randomModifyDescriptors.length; i++) {
119             RandomModifyDescriptor descriptor = randomModifyDescriptors[i];
120             int debugOpFragment = Math.max(descriptor.opCount() / 5, 100);
121             int nextDebugOp = debugOpFragment - 1;
122             for (int op = 0; op < descriptor.opCount(); op++) {
123                 opId++;
124                 double r = random().nextDouble() * descriptor.ratioSum();
125                 action(r, descriptor);
126                 if (op == nextDebugOp) {
127                     nextDebugOp = Math.min(nextDebugOp + debugOpFragment, descriptor.opCount() - 1);
128                     System.err.println(String.valueOf(op+1) + " of " + descriptor.opCount() + " operations finished.");
129                 }
130             }
131         }
132         
133         System.err.println("Maximum document length: " + maxDocLength());
134     }
135     
136     protected double action(double r, RandomModifyDescriptor descriptor) throws Exception JavaDoc {
137         if ((r -= descriptor.insertCharRatio()) < 0) {
138             if (descriptor.randomTextProvider().randomCharAvailable()) {
139                 char ch = descriptor.randomTextProvider().randomChar(random());
140                 insertText(String.valueOf(ch));
141             } else { // random char not available
142
insertText(""); // possibly debug the operation
143
}
144
145         } else if ((r -= descriptor.insertTextRatio()) < 0) {
146             String JavaDoc text = descriptor.randomTextProvider().randomText(random(),
147                     descriptor.insertTextMaxLength());
148             insertText(text);
149
150         } else if ((r -= descriptor.insertFixedTextRatio()) < 0) {
151             String JavaDoc fixedText = descriptor.randomTextProvider().randomFixedText(random());
152             insertText(fixedText);
153
154         } else if ((r -= descriptor.removeCharRatio()) < 0) {
155             removeText(1);
156
157         } else if ((r -= descriptor.removeTextRatio()) < 0) {
158             int length = random().nextInt(descriptor.removeTextMaxLength());
159             removeText(length);
160
161         } else if ((r -= descriptor.createSnapshotRatio()) < 0) {
162             createSnapshot();
163             
164         } else if ((r -= descriptor.destroySnapshotRatio()) < 0) {
165             destroySnapshot();
166         }
167         return r;
168     }
169     
170     public void insertText(int offset, String JavaDoc text) throws Exception JavaDoc {
171         if (text.length() > 0) {
172             if (isDebugOperation()) {
173                 System.err.println(opIdString() + " INSERT(" + offset +
174                         ", " + text.length() +"): \""
175                         + CharSequenceUtilities.debugText(text) +"\""
176                 );
177                 if (isDebugDocumentText()) {
178                     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
179                     String JavaDoc beforeOffsetText = CharSequenceUtilities.debugText(doc.getText(0, offset));
180                     for (int i = 0; i < beforeOffsetText.length(); i++) {
181                         sb.append('-');
182                     }
183                     sb.append("\\ \"");
184                     CharSequenceUtilities.debugText(sb, text);
185                     sb.append("\"\n\"");
186                     sb.append(beforeOffsetText).append(CharSequenceUtilities.debugText(
187                             doc.getText(offset, doc.getLength() - offset))).append('"');
188                     System.err.println(sb.toString());
189                 }
190             }
191             document().insertString(offset, text, null);
192             insertTextNotify(offset, text);
193             maxDocLength = Math.max(document().getLength(), maxDocLength);
194             checkConsistency();
195
196         } else {
197             if (isDebugOperation()) {
198                 System.err.println(opIdString() + " INSERT cannot be done (text=\"\")");
199             }
200         }
201     }
202     
203     public void insertText(String JavaDoc text) throws Exception JavaDoc {
204         int offset = random().nextInt(document().getLength() + 1);
205         insertText(offset, text);
206     }
207     
208     protected void insertTextNotify(int offset, String JavaDoc text) throws Exception JavaDoc {
209     }
210
211     public void removeText(int offset, int length) throws Exception JavaDoc {
212         if (length > 0) {
213             if (isDebugOperation()) {
214                 System.err.println(opIdString() + " REMOVE(" + offset
215                         + ", " + length + "): \""
216                         + CharSequenceUtilities.debugText(document().getText(offset, length))
217                         + "\""
218                 );
219             }
220             if (isDebugDocumentText()) {
221                 StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
222                 String JavaDoc beforeOffsetText = CharSequenceUtilities.debugText(doc.getText(0, offset));
223                 for (int i = 0; i <= beforeOffsetText.length(); i++) {
224                     sb.append('-');
225                 }
226                 for (int i = 0; i < length; i++) {
227                     sb.append('x');
228                 }
229                 sb.append("\n\"");
230                 sb.append(beforeOffsetText).append(CharSequenceUtilities.debugText(
231                         doc.getText(offset, doc.getLength() - offset))).append('"');
232                 System.err.println(sb.toString());
233             }
234             document().remove(offset, length);
235             removeTextNotify(offset, length);
236             checkConsistency();
237
238         } else { // No operation
239
if (isDebugOperation()) {
240                 System.err.println(opIdString() + " REMOVE cannot be done (length=0)");
241             }
242         }
243     }
244     
245     public void removeText(int length) throws Exception JavaDoc {
246         length = Math.min(document().getLength(), length);
247         int offset = random().nextInt(document().getLength() - length + 1);
248         removeText(offset, length);
249     }
250     
251     protected void removeTextNotify(int offset, int length) throws Exception JavaDoc {
252     }
253     
254     public void createSnapshot() throws Exception JavaDoc {
255         junit.framework.TestCase.fail();
256         TokenHierarchy hi = TokenHierarchy.get(doc);
257         TokenHierarchy snapshot = hi.createSnapshot();
258         Language<? extends TokenId> language = (Language<? extends TokenId>)
259                 doc.getProperty(Language.class);
260         TokenHierarchy batchMirror = TokenHierarchy.create(doc.getText(0, doc.getLength()), language);
261         snapshots.add(new SnapshotDescription(snapshot, batchMirror));
262         if (isDebugOperation()) {
263             System.err.println(opIdString() + " CREATED SNAPSHOT. "
264                     + snapshots.size() + " snapshots.");
265         }
266         checkConsistency();
267     }
268     
269     public void destroySnapshot() throws Exception JavaDoc {
270         junit.framework.TestCase.fail();
271         if (snapshots.size() > 0) {
272             int index = random().nextInt(snapshots.size());
273             snapshots.remove(index);
274             if (isDebugOperation()) {
275                 System.err.println(opIdString() + " DESTROYED SNAPSHOT. "
276                         + snapshots.size() + " snapshots.");
277             }
278             checkConsistency();
279
280         } else { // no snapshots
281
if (isDebugOperation()) {
282                 System.err.println(opIdString() + " DESTROY SNAPSHOT cannot be done - no snapshots.");
283             }
284         }
285     }
286
287     public final int opId() {
288         return opId;
289     }
290     
291     public final String JavaDoc opIdString() {
292         String JavaDoc s = String.valueOf(opId());
293         while (s.length() < 3) {
294             s = " " + s;
295         }
296         return "[" + s + "]";
297     }
298         
299     public final Random JavaDoc random() {
300         return random;
301     }
302     
303     public final Document JavaDoc document() {
304         return doc;
305     }
306     
307     public void clearDocument() throws Exception JavaDoc {
308         doc.remove(0, doc.getLength());
309     }
310     
311     public final Language<? extends TokenId> language() {
312         return (Language<? extends TokenId>)doc.getProperty(Language.class);
313     }
314     
315     public final void setLanguage(Language<? extends TokenId> language) {
316         doc.putProperty(Language.class, language);
317     }
318     
319     public final int maxDocLength() {
320         return maxDocLength;
321     }
322
323     protected void checkConsistency() throws Exception JavaDoc {
324         if (!isSkipLexerConsistencyCheck()) {
325             if (isDebugHierarchy()) {
326                 TokenHierarchy<?> hi = TokenHierarchy.get(doc);
327                 if (hi != null) {
328                     System.err.println("DEBUG hierarchy:\n" + hi.tokenSequence());
329                 }
330             }
331
332             LexerTestUtilities.incCheck(doc, false);
333             
334             for (int i = 0; i < snapshots.size(); i++) {
335                 SnapshotDescription sd = snapshots.get(i);
336                 TokenHierarchy<?> bm = sd.batchMirror();
337                 TokenHierarchy<?> s = sd.snapshot();
338                 if (isDebugOperation()) {
339                     System.err.println("Comparing snapshot " + i + " of " + snapshots.size());
340                 }
341                 // Check snapshot without comparing lookaheads and states
342
LexerTestUtilities.assertTokenSequencesEqual(bm.tokenSequence(), bm,
343                         s.tokenSequence(), s, false);
344             }
345         }
346     }
347     
348     private static final class SnapshotDescription {
349         
350         private final TokenHierarchy<?> snapshot;
351         
352         private final TokenHierarchy<?> batchMirror;
353         
354         public SnapshotDescription(TokenHierarchy snapshot, TokenHierarchy batchMirror) {
355             this.snapshot = snapshot;
356             this.batchMirror = batchMirror;
357         }
358         
359         public TokenHierarchy snapshot() {
360             return snapshot;
361         }
362         
363         public TokenHierarchy batchMirror() {
364             return batchMirror;
365         }
366
367     }
368
369 }
370
Popular Tags