1 43 44 package de.susebox.jtopas; 45 46 import java.util.Iterator ; 50 import java.util.Random ; 51 import java.util.Map ; 52 import java.util.HashMap ; 53 import java.util.Collections ; 54 55 import junit.framework.Test; 56 import junit.framework.TestCase; 57 import junit.framework.TestSuite; 58 import junit.framework.Assert; 59 60 import de.susebox.java.lang.ExtRuntimeException; 61 import de.susebox.jtopas.spi.DataProvider; 62 import de.susebox.jtopas.spi.KeywordHandler; 63 import de.susebox.jtopas.spi.SequenceHandler; 64 import de.susebox.jtopas.spi.PatternHandler; 65 import de.susebox.jtopas.spi.WhitespaceHandler; 66 import de.susebox.jtopas.spi.SeparatorHandler; 67 68 import de.susebox.TestUtilities; 69 70 74 82 public class TestMultithreadTokenizerProperties 83 extends TestCase 84 implements TokenizerPropertyListener, DataProvider { 85 86 90 93 public static void main(String [] args) { 94 String [] tests = { TestMultithreadTokenizerProperties.class.getName() }; 95 96 TestUtilities.run(tests, args); 97 } 98 99 100 104 110 public static Test suite() { 111 TestSuite suite = new TestSuite(TestMultithreadTokenizerProperties.class.getName()); 112 113 suite.addTest(new TestMultithreadTokenizerProperties("testParallelModification")); 114 return suite; 115 } 116 117 118 122 126 public TestMultithreadTokenizerProperties(String test) { 127 super(test); 128 } 129 130 131 135 139 protected void setUp() throws Exception { 140 _properties = new StandardTokenizerProperties(); 141 _properties.addTokenizerPropertyListener(this); 142 _eventRecord = new HashMap (101); 143 } 145 146 147 151 protected void tearDown() throws Exception {} 152 153 154 158 161 public void testParallelModification() throws Throwable { 162 System.out.println("Number of threads: " + _numberOfThreads); 163 System.out.println("Test duration (s): " + _duration); 164 165 Random random = new Random (); 166 StringBuffer [] active = new StringBuffer [_numberOfThreads]; 167 String [] last = new String [_numberOfThreads]; 168 Runner[] runner = new Runner[_numberOfThreads]; 169 Thread [] thread = new Thread [_numberOfThreads]; 170 long start = System.currentTimeMillis(); 171 172 for (int index = 0; index < _numberOfThreads; ++index) { 174 active[index] = new StringBuffer ("0"); 175 runner[index] = new Runner(this, random.nextInt(_testProperties.length - 1), 2, active[index]); 176 thread[index] = new Thread (runner[index]); 177 } 178 179 try { 181 for (int index = 0; index < _numberOfThreads; ++index) { 182 thread[index].start(); 183 } 184 185 while (System.currentTimeMillis() - start < _duration * 1000) { 186 synchronized(this) { 187 try { 188 wait(3000); 189 } catch (InterruptedException ex) {} 190 } 191 192 for (int index = 0; index < _numberOfThreads; ++index) { 194 System.out.println(System.currentTimeMillis() + ": Activity at runner " + index + ": " + active[index]); 195 last[index] = active[index].toString(); 196 } 197 } 198 199 for (int index = 0; index < _numberOfThreads; ++index) { 201 runner[index].stop(); 202 } 203 Thread.sleep(5000); 204 205 206 for (int index = 0; index < _numberOfThreads; ++index) { 208 String activity = active[index].toString(); 209 210 assertTrue("No good activity at runner " + index + ": " + activity, 211 new Integer (activity).intValue() > (600 / _numberOfThreads) * _duration); 212 } 213 214 } finally { 215 for (int index = 0; index < _numberOfThreads; ++index) { 216 thread[index] = null; 217 } 218 } 219 } 220 221 222 226 232 public void propertyChanged(TokenizerPropertyEvent event) { 233 TokenizerProperty prop = event.getProperty(); 234 String name = Thread.currentThread().getName(); 235 236 switch (event.getType()) { 237 case TokenizerPropertyEvent.PROPERTY_MODIFIED: 238 assertTrue("Modified non-existing property " + prop, _eventRecord.containsKey(prop)); 239 assertTrue("Property does not exist: " + prop, _properties.propertyExists(prop)); 240 break; 241 242 case TokenizerPropertyEvent.PROPERTY_ADDED: 243 assertTrue("Added existing property " + prop, _eventRecord.put(prop, prop) == null); 244 assertTrue("Property does not exist: " + prop, _properties.propertyExists(prop)); 245 break; 246 247 case TokenizerPropertyEvent.PROPERTY_REMOVED: 248 assertTrue("Removed not added property " + prop, _eventRecord.remove(prop) != null); 249 assertTrue("Property still exists: " + prop, ! _properties.propertyExists(prop)); 250 break; 251 } 252 } 253 254 259 public char[] getData() { 260 return _currData; 261 } 262 263 269 public char[] getDataCopy() { 270 char[] dst = new char[_currDataLength]; 271 272 System.arraycopy(_currData, _currStartPos, dst, 0, _currDataLength); 273 return dst; 274 } 275 276 283 public int getLength() { 284 return _currDataLength; 285 } 286 287 292 public int getStartPosition() { 293 return _currStartPos; 294 } 295 296 302 public char getCharAt(int index) { 303 return _currData[_currStartPos + index]; 304 } 305 306 307 protected static int _numberOfThreads = 20; 311 protected static int _duration = 60; 312 313 protected static final TokenizerProperty[] _testProperties = { 314 new TokenizerProperty(Token.KEYWORD, new String [] { "k1" } ), 315 new TokenizerProperty(Token.STRING, new String [] { "\"", "\"", "\\" } ), 316 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { ">>>" }, new Object () ), 317 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { ">>" } ), 318 new TokenizerProperty(Token.KEYWORD, new String [] { "k2" }, new Object (), Flags.F_NO_CASE), 319 new TokenizerProperty(Token.KEYWORD, new String [] { "k3" }, new Object (), Flags.F_NO_CASE), 320 new TokenizerProperty(Token.LINE_COMMENT, new String [] { "//" } ), 321 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "<<" }, new Object () ), 322 new TokenizerProperty(Token.BLOCK_COMMENT, new String [] { "/**", "*/" }, new Object ()), 323 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "+=" } ), 324 new TokenizerProperty(Token.KEYWORD, new String [] { "H1" }, null, Flags.F_NO_CASE), 325 new TokenizerProperty(Token.KEYWORD, new String [] { "H2" }, null, Flags.F_NO_CASE), 326 new TokenizerProperty(Token.KEYWORD, new String [] { "H3" }, null, Flags.F_NO_CASE), 327 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "-=" }, new Object () ), 328 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "*=" } ), 329 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "**=" } ), 330 new TokenizerProperty(Token.LINE_COMMENT, new String [] { "#" }, new Object () ), 331 new TokenizerProperty(Token.LINE_COMMENT, new String [] { "rem" }, null, Flags.F_NO_CASE), 332 new TokenizerProperty(Token.BLOCK_COMMENT, new String [] { "/*", "*/" } ), 333 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "++" } ), 334 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "+++" }, new Object () ), 335 new TokenizerProperty(Token.BLOCK_COMMENT, new String [] { "{{", "}}" }, new Object ()), 336 new TokenizerProperty(Token.BLOCK_COMMENT, new String [] { "[startBlockComment]", "[endBlockComment]" }, null, Flags.F_NO_CASE), 337 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "**" } ), 338 new TokenizerProperty(Token.BLOCK_COMMENT, new String [] { "<!--", "-->" } ), 339 new TokenizerProperty(Token.STRING, new String [] { "'", "'", "\\" } ), 340 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { ":=" } ), 341 new TokenizerProperty(Token.PATTERN, new String [] { "[+\\-]?[0-9]+\\.?[0-9]*" }, new Object ()), 342 new TokenizerProperty(Token.KEYWORD, new String [] { "if" }, new Object () ), 343 new TokenizerProperty(Token.KEYWORD, new String [] { "then" }, new Object () ), 344 new TokenizerProperty(Token.PATTERN, new String [] { "[A-Z_][A-Z0-9_]*" }, new Object (), Flags.F_NO_CASE), 345 new TokenizerProperty(Token.KEYWORD, new String [] { "while" }, new Object () ), 346 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "!=" }, new Object ()), 347 new TokenizerProperty(Token.KEYWORD, new String [] { "loop" }, new Object () ), 348 new TokenizerProperty(Token.KEYWORD, new String [] { "class" }, new Object () ), 349 new TokenizerProperty(Token.KEYWORD, new String [] { "interface" }, new Object () ), 350 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "<>" }, new Object ()), 351 new TokenizerProperty(Token.LINE_COMMENT, new String [] { "--" }, new Object () ), 352 new TokenizerProperty(Token.KEYWORD, new String [] { "synchronized" }, new Object () ), 353 new TokenizerProperty(Token.KEYWORD, new String [] { "final" } ), 354 new TokenizerProperty(Token.KEYWORD, new String [] { "implements" } ), 355 new TokenizerProperty(Token.KEYWORD, new String [] { "int" } ), 356 new TokenizerProperty(Token.STRING, new String [] { "''", "''", "''" }, new Object () ), 357 new TokenizerProperty(Token.KEYWORD, new String [] { "boolean" } ), 358 new TokenizerProperty(Token.KEYWORD, new String [] { "void" } ), 359 new TokenizerProperty(Token.KEYWORD, new String [] { "do" } ), 360 new TokenizerProperty(Token.KEYWORD, new String [] { "HREF" }, null, Flags.F_NO_CASE), 361 new TokenizerProperty(Token.KEYWORD, new String [] { "FONT" }, null, Flags.F_NO_CASE), 362 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "." } ), 363 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "{" } ), 364 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "}" } ), 365 new TokenizerProperty(Token.KEYWORD, new String [] { "import" } ), 366 new TokenizerProperty(Token.KEYWORD, new String [] { "package" } ), 367 new TokenizerProperty(Token.KEYWORD, new String [] { "static" } ), 368 new TokenizerProperty(Token.KEYWORD, new String [] { "try" }, new Object () ), 369 new TokenizerProperty(Token.KEYWORD, new String [] { "catch" }, new Object () ), 370 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "/" } ), 371 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "/=" } ), 372 new TokenizerProperty(Token.KEYWORD, new String [] { "table" }, null, Flags.F_NO_CASE), 373 new TokenizerProperty(Token.KEYWORD, new String [] { "span" }, null, Flags.F_NO_CASE), 374 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "[" } ), 375 new TokenizerProperty(Token.KEYWORD, new String [] { "layer" }, null, Flags.F_NO_CASE), 376 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "]" } ), 377 new TokenizerProperty(Token.KEYWORD, new String [] { "STYLE" }, null, Flags.F_NO_CASE), 378 new TokenizerProperty(Token.KEYWORD, new String [] { "image" }, null, Flags.F_NO_CASE), 379 new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String [] { "+" } ) 380 }; 381 382 383 protected Map _eventRecord = null; 387 protected TokenizerProperties _properties = null; 388 private char[] _currData = new char[8192]; 389 private int _currStartPos = 0; 390 private int _currDataLength = 0; 391 392 393 397 400 class Runner implements Runnable { 401 402 407 public Runner(TestMultithreadTokenizerProperties parent, int start, int step, StringBuffer activity) { 408 _parent = parent; 409 _start = start; 410 _activity = activity; 411 if ((_step = step) < 1) { 412 _step = 1; 413 } 414 } 415 416 427 public void run() { 428 Thread thread = Thread.currentThread(); 429 String name = thread.getName(); 430 int counter = _start; 431 432 try { 433 while (Thread.currentThread() == thread && ! _stop) { 434 synchronized(this) { 435 long start = System.currentTimeMillis(); 436 int index = counter % _parent._testProperties.length; 437 TokenizerProperty prop = _parent._testProperties[index]; 438 439 if (_parent._properties.propertyExists(prop)) { 442 _parent._properties.removeProperty(prop); 443 } else { 444 _parent._properties.addProperty(prop); 445 } 446 447 long duration = System.currentTimeMillis() - start; 449 if (duration > 5000) { 450 _parent.assertTrue(name + ": waited too long: " + duration, false); 451 break; 452 } 453 454 counter += _step; 456 457 long value = Long.parseLong(_activity.toString()); 459 _activity.setLength(0); 460 _activity.append(value + 1); 461 462 try { 464 wait(1); 465 } catch (InterruptedException ex) {} 466 } 467 } 468 } catch (Throwable t) { 469 t.printStackTrace(); 470 } 471 System.out.println(name + ": exiting. Activity: " + _activity); 472 } 473 474 477 public void stop() { 478 synchronized(this) { 479 _stop = true; 480 } 481 } 482 483 484 private TestMultithreadTokenizerProperties _parent = null; 488 private int _start = 0; 489 private int _step = 0; 490 private boolean _stop = false; 491 private StringBuffer _activity = null; 492 } 493 } 494 495 | Popular Tags |