KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > PlainDocumentCompatibilityRandomTest


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-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.editor;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Random JavaDoc;
25 import javax.swing.event.DocumentEvent JavaDoc;
26 import javax.swing.event.DocumentListener JavaDoc;
27 import javax.swing.text.BadLocationException JavaDoc;
28 import javax.swing.text.Document JavaDoc;
29 import javax.swing.text.Element JavaDoc;
30 import javax.swing.text.PlainDocument JavaDoc;
31 import javax.swing.text.Position JavaDoc;
32 import javax.swing.undo.UndoManager JavaDoc;
33 import junit.framework.TestCase;
34
35 /**
36  * Test compatibility of the editor's document implementation
37  * with the PlainDocument.
38  *
39  * @author mmetelka
40  */

41 public class PlainDocumentCompatibilityRandomTest extends TestCase
42 implements DocumentListener JavaDoc {
43     
44     private static final boolean debug = false;
45     private static final boolean debugLines = false;
46     
47     private static final int OP_COUNT_1 = 10000;
48     private static final int INSERT_RATIO_1 = 100;
49     private static final int INSERT_MAX_LENGTH_1 = 10;
50     private static final float INSERT_NL_RATIO_1 = 0.5f;
51     private static final int REMOVE_RATIO_1 = 70;
52     private static final int REMOVE_MAX_LENGTH_1 = 10;
53     // [TODO] Reset to zero temporarily
54
// as the current document content has certain specifics for positions undo
55
private static final int CREATE_POSITION_RATIO_1 = 0;
56     private static final int RELEASE_POSITION_RATIO_1 = 20;
57     private static final int UNDO_RATIO_1 = 30;
58     private static final int UNDO_MAX_COUNT_1 = 5;
59     private static final int REDO_RATIO_1 = 30;
60     private static final int REDO_MAX_COUNT_1 = 5;
61     
62     private static final int OP_COUNT_2 = 10000;
63     private static final int INSERT_RATIO_2 = 70;
64     private static final int INSERT_MAX_LENGTH_2 = 10;
65     private static final float INSERT_NL_RATIO_2 = 0.2f;
66     private static final int REMOVE_RATIO_2 = 100;
67     private static final int REMOVE_MAX_LENGTH_2 = 10;
68     // [TODO] Reset to zero temporarily
69
// as the current document content has certain specifics for positions undo
70
private static final int CREATE_POSITION_RATIO_2 = 0;
71     private static final int RELEASE_POSITION_RATIO_2 = 40;
72     private static final int UNDO_RATIO_2 = 30;
73     private static final int UNDO_MAX_COUNT_2 = 5;
74     private static final int REDO_RATIO_2 = 30;
75     private static final int REDO_MAX_COUNT_2 = 5;
76
77     private PlainDocument JavaDoc masterDoc;
78     
79     private BaseDocument testDoc;
80     
81     private DocumentEvent JavaDoc masterEvent;
82     
83     private List JavaDoc masterPositions = new ArrayList JavaDoc();
84     
85     private List JavaDoc testPositions = new ArrayList JavaDoc();
86     
87     private UndoManager JavaDoc masterUndoManager = new UndoManager JavaDoc();
88     
89     private UndoManager JavaDoc testUndoManager = new UndoManager JavaDoc();
90     
91     public PlainDocumentCompatibilityRandomTest(String JavaDoc testName) {
92         super(testName);
93     }
94     
95     public void test() {
96         testFresh(0);
97     }
98
99     public void testFresh(long seed) {
100         if (seed == 0) {
101             seed = System.currentTimeMillis();
102             System.err.println("Chosen SEED=" + seed);
103         }
104         Random JavaDoc random = new Random JavaDoc(seed);
105
106         
107         if (debug) {
108             System.err.println("TESTING with SEED=" + seed);
109         }
110
111         masterDoc = new PlainDocument JavaDoc();
112         testDoc = new BaseDocument(BaseKit.class, false);
113         
114         // Atach document listener
115
masterDoc.addDocumentListener(this);
116         testDoc.addDocumentListener(this);
117         
118         // Attach undoable listeners
119
masterDoc.addUndoableEditListener(masterUndoManager);
120         testDoc.addUndoableEditListener(testUndoManager);
121         
122         testRound(random, OP_COUNT_1,
123             INSERT_RATIO_1, INSERT_MAX_LENGTH_1, INSERT_NL_RATIO_1,
124             REMOVE_RATIO_1, REMOVE_MAX_LENGTH_1,
125             CREATE_POSITION_RATIO_1, RELEASE_POSITION_RATIO_1,
126             UNDO_RATIO_1, UNDO_MAX_COUNT_1,
127             REDO_RATIO_1, REDO_MAX_COUNT_1
128         );
129
130         testRound(random, OP_COUNT_2,
131             INSERT_RATIO_2, INSERT_MAX_LENGTH_2, INSERT_NL_RATIO_2,
132             REMOVE_RATIO_2, REMOVE_MAX_LENGTH_2,
133             CREATE_POSITION_RATIO_2, RELEASE_POSITION_RATIO_2,
134             UNDO_RATIO_2, UNDO_MAX_COUNT_2,
135             REDO_RATIO_2, REDO_MAX_COUNT_2
136         );
137         
138         // Detach undo managers
139
masterDoc.removeUndoableEditListener(masterUndoManager);
140         testDoc.removeUndoableEditListener(testUndoManager);
141         
142         // Clear undo managers
143
masterUndoManager.discardAllEdits();
144         testUndoManager.discardAllEdits();
145         
146         // Remove document listeners
147
masterDoc.removeDocumentListener(this);
148         testDoc.removeDocumentListener(this);
149     }
150     
151     private void testRound(Random JavaDoc random, int opCount,
152     int insertRatio, int insertMaxLength, float insertNlRatio,
153     int removeRatio, int removeMaxLength,
154     int createPositionRatio, int releasePositionRatio,
155     int undoRatio, int undoMaxCount,
156     int redoRatio, int redoMaxCount) {
157         
158         int ratioSum = insertRatio + removeRatio
159             + createPositionRatio + releasePositionRatio
160             + undoRatio + redoRatio;
161         
162         for (int op = 0; op < opCount; op++) {
163             double r = random.nextDouble() * ratioSum;
164             int docLength = masterDoc.getLength();
165             
166             if (debugLines) {
167                 System.err.println("LINES:\n" + linesToString());
168             }
169             
170             if ((r -= insertRatio) < 0) {
171                 int offset = (int)((docLength + 1) * random.nextDouble());
172                 int length = (int)(insertMaxLength * random.nextDouble());
173                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
174                 StringBuffer JavaDoc debugSb = debug ? new StringBuffer JavaDoc() : null;
175
176                 for (int i = length - 1; i >= 0; i--) {
177                     char ch;
178                     if (random.nextDouble() < insertNlRatio) { // insert '\n'
179
ch = '\n';
180                         if (debug) {
181                             debugSb.append("\\n");
182                         }
183
184                     } else { // insert regular char
185
ch = (char)('a' + (int)(26 * random.nextDouble()));
186                         if (debug) {
187                             debugSb.append(ch);
188                         }
189                     }
190                     sb.append(ch);
191                 }
192                 if (debug) {
193                     debugOp(op, "insertString(" + offset + ", \"" + debugSb + "\")");
194                 }
195
196                 try {
197                     masterDoc.insertString(offset, sb.toString(), null);
198                     testDoc.insertString(offset, sb.toString(), null);
199                     // Reset undoable events merging
200
testDoc.resetUndoMerge();
201                 } catch (BadLocationException JavaDoc e) {
202                     throw new RuntimeException JavaDoc(e);
203                 }
204
205                 
206             } else if ((r -= removeRatio) < 0) {
207                 int offset = (int)((docLength + 1) * random.nextDouble());
208                 int length = (int)(removeMaxLength * random.nextDouble());
209                 length = Math.min(length, docLength - offset);
210
211                 if (debug) {
212                     debugOp(op, "remove(" + offset + ", " + length + ")");
213                 }
214
215                 try {
216                     masterDoc.remove(offset, length);
217                     testDoc.remove(offset, length);
218                     // Reset undoable events merging
219
testDoc.resetUndoMerge();
220                 } catch (BadLocationException JavaDoc e) {
221                     throw new RuntimeException JavaDoc(e);
222                 }
223
224             } else if ((r -= createPositionRatio) < 0) {
225                 // Allow position at docLength + 1
226
int offset = (int)((docLength + 2) * random.nextDouble());
227
228                 if (debug) {
229                     debugOp(op, "createPosition(" + offset + ")");
230                 }
231                 try {
232                     masterPositions.add(masterDoc.createPosition(offset));
233                     testPositions.add(testDoc.createPosition(offset));
234                 } catch (BadLocationException JavaDoc e) {
235                     throw new RuntimeException JavaDoc(e);
236                 }
237
238                 
239             } else if ((r -= releasePositionRatio) < 0) {
240                 int masterPositionsCount = masterPositions.size();
241                 if (masterPositionsCount > 0) {
242                     int index = (int)(masterPositionsCount * random.nextDouble());
243     
244                     if (debug) {
245                         debugOp(op, "release position at index=" + index);
246                     }
247
248                     masterPositions.remove(index);
249                     testPositions.remove(index);
250                 }
251
252             } else if ((r -= undoRatio) < 0) {
253                 int undoCount = (int)(undoMaxCount * random.nextDouble());
254
255                 if (debug) {
256                     debugOp(op, "undo(" + undoCount + ")");
257                 }
258                 
259                 while (undoCount > 0) {
260                     undoCount--;
261                     if (masterUndoManager.canUndo()) {
262                         masterUndoManager.undo();
263                         testUndoManager.undo();
264                         if (undoCount > 0) {
265                             checkConsistency(); // Check consistency after each undo
266
}
267                     }
268                 }
269
270             } else if ((r -= redoRatio) < 0) {
271                 int redoCount = (int)(redoMaxCount * random.nextDouble());
272
273                 if (debug) {
274                     debugOp(op, "redo(" + redoCount + ")");
275                 }
276                 
277                 while (redoCount > 0) {
278                     redoCount--;
279                     if (masterUndoManager.canRedo()) {
280                         masterUndoManager.redo();
281                         testUndoManager.redo();
282                         if (redoCount > 0) {
283                             checkConsistency(); // Check consistency after each redo
284
}
285                     }
286                 }
287             }
288
289             checkConsistency();
290         }
291         
292     }
293         
294     private void debugOp(int op, String JavaDoc s) {
295         System.err.println("op: " + op + ", " + s);
296     }
297     
298     private void checkConsistency() {
299         try {
300             int docLength = masterDoc.getLength();
301             assertEquals(docLength, testDoc.getLength());
302
303             String JavaDoc masterText = masterDoc.getText(0, docLength);
304             String JavaDoc testText = testDoc.getText(0, docLength);
305             assertEquals(masterText, testText);
306
307             Element JavaDoc lineRoot = masterDoc.getDefaultRootElement();
308             Element JavaDoc testLineRoot = testDoc.getDefaultRootElement();
309             int lineCount = lineRoot.getElementCount();
310             if (lineCount != testLineRoot.getElementCount()) {
311                 fail("Line count " + testLineRoot.getElementCount()
312                     + " != " + lineCount);
313             }
314             // Compare line boundaries
315
for (int i = 0; i < lineCount; i++) {
316                 Element JavaDoc masterLine = lineRoot.getElement(i);
317                 Element JavaDoc testLine = testLineRoot.getElement(i);
318                 if (masterLine.getStartOffset() != testLine.getStartOffset()) {
319                     fail("Start of line " + i + ": Offset " + testLine.getStartOffset()
320                         + " != " + masterLine.getStartOffset());
321                 }
322                 if (masterLine.getEndOffset() != testLine.getEndOffset()) {
323                     fail("End of line " + i + ": Offset " + testLine.getEndOffset()
324                         + " != " + masterLine.getEndOffset());
325                 }
326             }
327
328             int positionCount = masterPositions.size();
329             for (int i = 0; i < positionCount; i++) {
330                 Position JavaDoc masterPos = (Position JavaDoc)masterPositions.get(i);
331                 Position JavaDoc testPos = (Position JavaDoc)testPositions.get(i);
332                 if (masterPos.getOffset() != testPos.getOffset()) {
333                     fail("Tested position " + (i + 1) + " of " + positionCount
334                         + ": " + testPos.getOffset()
335                         + " != " + masterPos.getOffset());
336                 }
337             }
338         } catch (BadLocationException JavaDoc e) {
339             throw new RuntimeException JavaDoc(e);
340         }
341     }
342
343     private String JavaDoc linesToString() {
344         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
345         Element JavaDoc masterLineRoot = masterDoc.getDefaultRootElement();
346         Element JavaDoc testLineRoot = testDoc.getDefaultRootElement();
347         int masterLineCount = masterLineRoot.getElementCount();
348         int testLineCount = testLineRoot.getElementCount();
349         int lineCount = Math.max(masterLineCount, testLineCount);
350         sb.append("Line count=" + lineCount + "\n");
351         for (int i = 0; i < lineCount; i++) {
352             if (i < testLineCount) {
353                 Element JavaDoc line = testLineRoot.getElement(i);
354                 sb.append("[" + i + "]: <" + line.getStartOffset() + ", " + line.getEndOffset() + "> ");
355             } else {
356                 sb.append(" <!NONE!> ");
357             }
358
359             if (i < masterLineCount) {
360                 Element JavaDoc line = masterLineRoot.getElement(i);
361                 sb.append("[" + i + "]: <" + line.getStartOffset() + ", " + line.getEndOffset() + ">\n");
362             } else {
363                 sb.append(" <!NONE!>\n");
364             }
365         }
366         return sb.toString();
367     }
368     
369     private void checkEventsEqual(DocumentEvent JavaDoc testEvent) {
370         if (masterEvent.getOffset() != testEvent.getOffset()) {
371             fail("masterEvent.getOffset()=" + masterEvent.getOffset()
372                 + " != testEvent.getOffset()=" + testEvent.getOffset());
373         }
374         if (masterEvent.getLength() != testEvent.getLength()) {
375             fail("masterEvent.getLength()=" + masterEvent.getLength()
376                 + " != testEvent.getLength()=" + testEvent.getLength());
377         }
378         if (masterEvent.getType() != testEvent.getType()) {
379             fail("masterEvent.getType()=" + masterEvent.getType()
380                 + " != testEvent.getType()=" + testEvent.getType());
381         }
382         DocumentEvent.ElementChange JavaDoc masterChange = masterEvent.getChange(masterDoc.getDefaultRootElement());
383         DocumentEvent.ElementChange JavaDoc testChange = testEvent.getChange(testDoc.getDefaultRootElement());
384         checkElementChangesEqual(masterChange, testChange);
385     }
386     
387     private void checkElementChangesEqual(DocumentEvent.ElementChange JavaDoc masterChange,
388     DocumentEvent.ElementChange JavaDoc testChange) {
389         
390         if (masterChange == null && testChange == null) { // no line changes
391
return;
392         }
393         
394         if (masterChange == null && testChange != null) {
395             fail("masterChange is null");
396         }
397         if (masterChange != null && testChange == null) {
398             fail("testChange is null");
399         }
400         
401         // Both changes are not null
402
int masterIndex = masterChange.getIndex();
403         int testIndex = testChange.getIndex();
404         if (masterIndex != testIndex) {
405             fail("masterIndex=" + masterIndex + " != testIndex=" + testIndex);
406         }
407         Element JavaDoc[] masterAdded = masterChange.getChildrenAdded();
408         Element JavaDoc[] testAdded = testChange.getChildrenAdded();
409         if (masterAdded.length != testAdded.length) {
410             fail("masterAdded.length=" + masterAdded.length
411                 + "!= testAdded.length=" + testAdded.length);
412         }
413         Element JavaDoc[] masterRemoved = masterChange.getChildrenRemoved();
414         Element JavaDoc[] testRemoved = testChange.getChildrenRemoved();
415         if (masterRemoved.length != testRemoved.length) {
416             fail("masterRemoved.length=" + masterRemoved.length
417                 + "!= testRemoved.length=" + testRemoved.length);
418         }
419         for (int i = 0; i < masterAdded.length; i++) {
420             Element JavaDoc masterElem = masterAdded[i];
421             Element JavaDoc testElem = testAdded[i];
422             checkElementOffsetsEqual(masterElem, testElem);
423         }
424         for (int i = 0; i < masterRemoved.length; i++) {
425             Element JavaDoc masterElem = masterRemoved[i];
426             Element JavaDoc testElem = testRemoved[i];
427             checkElementOffsetsEqual(masterElem, testElem);
428         }
429     }
430     
431     private void checkElementOffsetsEqual(Element JavaDoc masterElem, Element JavaDoc testElem) {
432         if (masterElem.getStartOffset() != testElem.getStartOffset()) {
433             fail("masterElem.getStartOffset()=" + masterElem.getStartOffset()
434                 + " != testElem.getStartOffset()=" + testElem.getStartOffset());
435         }
436         if (masterElem.getEndOffset() != testElem.getEndOffset()) {
437             fail("masterElem.getEndOffset()=" + masterElem.getEndOffset()
438                 + " != testElem.getEndOffset()=" + testElem.getEndOffset());
439         }
440     }
441     
442     private void processEvent(DocumentEvent JavaDoc evt) {
443         // testDoc operations must always be done after the master ones.
444
Document JavaDoc doc = evt.getDocument();
445         if (doc == masterDoc) {
446             masterEvent = evt;
447         } else if (doc == testDoc) {
448             checkEventsEqual(evt);
449             masterEvent = null;
450         } else {
451             fail("Unknown document.");
452         }
453     }
454
455     public void insertUpdate(DocumentEvent JavaDoc e) {
456         processEvent(e);
457     }
458
459     public void removeUpdate(DocumentEvent JavaDoc e) {
460         processEvent(e);
461     }
462
463     public void changedUpdate(DocumentEvent JavaDoc e) {
464     }
465
466     
467 }
468
Popular Tags