1 19 20 package org.netbeans.lib.lexer.test; 21 22 import java.util.ArrayList ; 23 import java.util.List ; 24 import java.util.Random ; 25 import javax.swing.text.Document ; 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 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 random; 49 50 private Document doc; 51 52 private int opId; 53 54 private int maxDocLength; 55 56 private List <SnapshotDescription> snapshots = new ArrayList <SnapshotDescription>(); 57 58 public TestRandomModify() { 59 this(0); 60 } 61 62 public TestRandomModify(long seed) { 63 this.doc = new javax.swing.text.PlainDocument (); 64 65 this.random = new Random (); 66 if (seed == 0) { 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 81 public void setDebugOperation(boolean debugOperation) { 82 this.debugOperation = debugOperation; 83 } 84 85 public boolean isDebugHierarchy() { 86 return debugHierarchy; 87 } 88 89 93 public void setDebugHierarchy(boolean debugHierarchy) { 94 this.debugHierarchy = debugHierarchy; 95 } 96 97 public boolean isDebugDocumentText() { 98 return debugDocumentText; 99 } 100 101 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 { 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 { 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 { insertText(""); } 144 145 } else if ((r -= descriptor.insertTextRatio()) < 0) { 146 String text = descriptor.randomTextProvider().randomText(random(), 147 descriptor.insertTextMaxLength()); 148 insertText(text); 149 150 } else if ((r -= descriptor.insertFixedTextRatio()) < 0) { 151 String 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 text) throws Exception { 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 sb = new StringBuilder (); 179 String 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 text) throws Exception { 204 int offset = random().nextInt(document().getLength() + 1); 205 insertText(offset, text); 206 } 207 208 protected void insertTextNotify(int offset, String text) throws Exception { 209 } 210 211 public void removeText(int offset, int length) throws Exception { 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 sb = new StringBuilder (); 222 String 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 { 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 { 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 { 252 } 253 254 public void createSnapshot() throws Exception { 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 { 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 { 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 opIdString() { 292 String s = String.valueOf(opId()); 293 while (s.length() < 3) { 294 s = " " + s; 295 } 296 return "[" + s + "]"; 297 } 298 299 public final Random random() { 300 return random; 301 } 302 303 public final Document document() { 304 return doc; 305 } 306 307 public void clearDocument() throws Exception { 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 { 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 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 |