1 8 9 package foxtrot.test; 10 11 import java.awt.event.ActionEvent ; 12 import java.awt.event.ActionListener ; 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 16 import javax.swing.JButton ; 17 import javax.swing.JDialog ; 18 import javax.swing.JFrame ; 19 import javax.swing.SwingUtilities ; 20 21 import foxtrot.Job; 22 import foxtrot.Task; 23 import foxtrot.Worker; 24 25 28 public class WorkerTest extends FoxtrotTestCase 29 { 30 public WorkerTest(String s) 31 { 32 super(s); 33 } 34 35 public void testThreads() throws Exception 36 { 37 invokeTest(Worker.getWorkerThread(), new Runnable () 38 { 39 public void run() 40 { 41 Worker.post(new Job() 42 { 43 public Object run() 44 { 45 if (SwingUtilities.isEventDispatchThread()) fail("Must not be in the Event Dispatch Thread"); 47 48 if (Thread.currentThread().getName().indexOf("Foxtrot") < 0) fail("Must be in the Foxtrot Worker Thread"); 50 51 return null; 52 } 53 }); 54 } 55 }, null); 56 } 57 58 public void testBlocking() throws Exception 59 { 60 invokeTest(Worker.getWorkerThread(), new Runnable () 61 { 62 public void run() 63 { 64 final long sleep = 1000; 65 66 long start = System.currentTimeMillis(); 67 Worker.post(new Job() 68 { 69 public Object run() 70 { 71 sleep(sleep); 72 return null; 73 } 74 }); 75 long end = System.currentTimeMillis(); 76 77 long elapsed = end - start; 78 System.out.println("Sleep time is: " + sleep + ", Worker.post() blocked for " + elapsed); 79 80 if (elapsed < sleep) fail("Worker.post() does not block"); 81 } 82 }, null); 83 } 84 85 public void testDequeuing() throws Exception 86 { 87 invokeTest(Worker.getWorkerThread(), new Runnable () 88 { 89 public void run() 90 { 91 final MutableInteger check = new MutableInteger(0); 92 final long sleep = 1000; 93 94 SwingUtilities.invokeLater(new Runnable () 96 { 97 public void run() 98 { 99 check.set(1); 100 } 101 }); 102 103 sleep(2 * sleep); 104 105 if (check.get() != 0) fail(); 107 108 Worker.post(new Job() 109 { 110 public Object run() 111 { 112 sleep(sleep); 113 return null; 114 } 115 }); 116 117 if (check.get() != 1) fail("Event has not been dequeued"); 119 } 120 }, null); 121 } 122 123 public void testTaskException() throws Exception 124 { 125 invokeTest(Worker.getWorkerThread(), new Runnable () 126 { 127 public void run() 128 { 129 try 130 { 131 Worker.post(new Task() 132 { 133 public Object run() throws NumberFormatException 134 { 135 return new NumberFormatException (); 136 } 137 }); 138 } 139 catch (NumberFormatException ignored) 140 { 141 } 142 catch (Throwable x) 143 { 144 fail(); 145 } 146 } 147 }, null); 148 } 149 150 public void testTaskError() throws Exception 151 { 152 invokeTest(Worker.getWorkerThread(), new Runnable () 153 { 154 public void run() 155 { 156 try 157 { 158 Worker.post(new Job() 159 { 160 public Object run() 161 { 162 return new NoClassDefFoundError (); 163 } 164 }); 165 } 166 catch (NoClassDefFoundError ignored) 167 { 168 } 169 catch (Throwable x) 170 { 171 fail(); 172 } 173 } 174 }, null); 175 } 176 177 public void testAWTException() throws Exception 178 { 179 invokeTest(Worker.getWorkerThread(), new Runnable () 180 { 181 public void run() 182 { 183 SwingUtilities.invokeLater(new Runnable () 184 { 185 public void run() 186 { 187 throw new RuntimeException (); 188 } 189 }); 190 191 final long sleep = 1000; 192 long start = System.currentTimeMillis(); 193 Worker.post(new Job() 194 { 195 public Object run() 196 { 197 sleep(sleep); 198 return null; 199 } 200 }); 201 long end = System.currentTimeMillis(); 202 203 long elapsed = end - start; 205 if (elapsed < sleep) fail("Worker.post() does not block in case of AWT exception: expected " + sleep + ", waited " + elapsed); 206 } 207 }, null); 208 } 209 210 public void testAWTError() throws Exception 211 { 212 invokeTest(Worker.getWorkerThread(), new Runnable () 213 { 214 public void run() 215 { 216 SwingUtilities.invokeLater(new Runnable () 217 { 218 public void run() 219 { 220 throw new Error (); 221 } 222 }); 223 224 final long sleep = 1000; 225 long start = System.currentTimeMillis(); 226 Worker.post(new Job() 227 { 228 public Object run() 229 { 230 sleep(sleep); 231 return null; 232 } 233 }); 234 long end = System.currentTimeMillis(); 235 236 long elapsed = end - start; 238 if (elapsed < sleep) fail("Worker.post() does not block in case of AWT error: expected " + sleep + ", waited " + elapsed); 239 } 240 }, null); 241 } 242 243 public void testPostFromTask() throws Exception 244 { 245 invokeTest(Worker.getWorkerThread(), new Runnable () 246 { 247 public void run() 248 { 249 final MutableInteger counter = new MutableInteger(0); 250 251 Worker.post(new Job() 252 { 253 public Object run() 254 { 255 counter.set(counter.get() + 1); 256 257 Worker.post(new Job() 259 { 260 public Object run() 261 { 262 if (counter.get() != 1) fail(); 263 264 counter.set(counter.get() + 1); 265 return null; 266 } 267 }); 268 269 if (counter.get() != 2) fail("Nested Task is not executed immediately"); 270 271 counter.set(counter.get() + 1); 272 273 return null; 274 } 275 }); 276 277 if (counter.get() != 3) fail(); 278 } 279 }, null); 280 } 281 282 public void testTaskReuse() throws Exception 283 { 284 invokeTest(Worker.getWorkerThread(), new Runnable () 285 { 286 public void run() 287 { 288 final MutableInteger count = new MutableInteger(0); 289 290 Job job = new Job() 291 { 292 public Object run() 293 { 294 count.set(count.get() + 1); 295 return null; 296 } 297 }; 298 299 int times = 2; 300 for (int i = 0; i < times; ++i) 301 { 302 Worker.post(job); 303 } 304 305 if (count.get() != times) fail("Task is not reused"); 306 } 307 }, null); 308 } 309 310 public void testPostFromInvokeLater() throws Exception 311 { 312 invokeTest(Worker.getWorkerThread(), new Runnable () 313 { 314 public void run() 315 { 316 int max = 5; 317 MutableInteger counter = new MutableInteger(0); 318 319 long start = System.currentTimeMillis(); 320 321 postFromInvokeLater(counter, max); 322 323 long end = System.currentTimeMillis(); 324 325 long sum = 0; 327 for (int i = 0; i < max; ++i) sum += i + 1; 328 sum *= 1000; 329 330 long epsilon = 100; 331 long elapsed = end - start; 332 if (elapsed > sum + epsilon) fail("Elapsed time is: " + elapsed + ", expected time is: " + sum); 333 if (elapsed < sum - epsilon) fail("Elapsed time is: " + elapsed + ", expected time is: " + sum); 334 } 335 }, null); 336 } 337 338 private void postFromInvokeLater(final MutableInteger counter, final int maxDeep) 339 { 340 final int deep = counter.get() + 1; 341 342 Job job = new Job() 343 { 344 public Object run() 345 { 346 SwingUtilities.invokeLater(new Runnable () 363 { 364 public void run() 365 { 366 counter.set(deep); 367 if (deep < maxDeep) postFromInvokeLater(counter, maxDeep); 368 } 369 }); 370 371 sleep(1000 * deep); 372 373 return null; 374 } 375 }; 376 377 Worker.post(job); 384 } 385 386 public void testTaskQueueing() throws Exception 387 { 388 invokeTest(Worker.getWorkerThread(), new Runnable () 389 { 390 public void run() 391 { 392 final int count = 10; 393 final MutableInteger counter = new MutableInteger(0); 394 395 Worker.post(new Job() 401 { 402 public Object run() 403 { 404 for (int i = 0; i < 10; ++i) 405 { 406 SwingUtilities.invokeLater(new Runnable () 407 { 408 public void run() 409 { 410 Worker.post(new Job() 411 { 412 public Object run() 413 { 414 counter.set(counter.get() + 1); 415 return null; 416 } 417 }); 418 } 419 }); 420 } 421 422 sleep(1000); 424 425 return null; 426 } 427 }); 428 429 sleep(1000); 431 432 assertEquals(count, counter.get()); 433 } 434 }, null); 435 } 436 437 public void testPerformance() throws Exception 438 { 439 invokeTest(Worker.getWorkerThread(), new Runnable () 440 { 441 public void run() 442 { 443 JButton button = new JButton (); 444 int count = 100; 445 final long sleep = 100; 446 447 ActionListener listener = new ActionListener () 448 { 449 public void actionPerformed(ActionEvent e) 450 { 451 Worker.post(new Job() 452 { 453 public Object run() 454 { 455 sleep(sleep); 456 return null; 457 } 458 }); 459 } 460 }; 461 button.addActionListener(listener); 462 463 long start = System.currentTimeMillis(); 464 for (int i = 0; i < count; ++i) button.doClick(); 465 long end = System.currentTimeMillis(); 466 long workerElapsed = end - start; 467 System.out.println("Worker.post(Job) performance: " + count + " calls in " + workerElapsed + " ms"); 468 469 button.removeActionListener(listener); 470 471 listener = new ActionListener () 472 { 473 public void actionPerformed(ActionEvent e) 474 { 475 sleep(sleep); 476 } 477 }; 478 button.addActionListener(listener); 479 480 start = System.currentTimeMillis(); 481 for (int i = 0; i < count; ++i) 482 { 483 button.doClick(); 484 } 485 end = System.currentTimeMillis(); 486 long plainElapsed = end - start; 487 System.out.println("Plain Listener performance: " + count + " calls in " + plainElapsed + " ms"); 488 489 int perthousand = 1; 490 if ((workerElapsed - plainElapsed) * 1000 > plainElapsed * perthousand) fail(); 491 } 492 }, null); 493 } 494 495 public void testPumpSequencedEvents() throws Exception 496 { 497 invokeTest(Worker.getWorkerThread(), new Runnable () 498 { 499 public void run() 500 { 501 final JDialog dialog = new JDialog ((JFrame )null, true); 502 503 SwingUtilities.invokeLater(new Runnable () 504 { 505 public void run() 506 { 507 dialog.setVisible(false); 508 } 509 }); 510 511 dialog.setVisible(true); 512 513 final MutableInteger pumped = new MutableInteger(0); 514 SwingUtilities.invokeLater(new Runnable () 515 { 516 public void run() 517 { 518 pumped.set(pumped.get() + 1); 519 } 520 }); 521 522 Worker.post(new Job() 523 { 524 public Object run() 525 { 526 sleep(1000); 527 return null; 528 } 529 }); 530 531 if (pumped.get() != 1) fail(); 533 } 534 }, null); 535 } 536 537 public void testMemoryLeaks() throws Exception 538 { 539 invokeTest(Worker.getWorkerThread(), new Runnable () 540 { 541 public void run() 542 { 543 ArrayList list = new ArrayList (); 544 545 int times = 1024; 546 for (int i = 0; i < times; ++i) 547 { 548 try 549 { 550 Job job = new FatJob(); 551 list.add(job); 552 Worker.post(job); 553 } 554 catch (OutOfMemoryError x) 555 { 556 list.clear(); 557 break; 558 } 559 } 560 561 int j = 0; 563 for (; j < times; ++j) 564 { 565 Job job = new FatJob(); 566 Worker.post(job); 567 } 568 569 if (j < times) fail(); 570 } 571 }, null); 572 } 573 574 private static class FatJob extends Job 575 { 576 private byte[] fatty = new byte[1024 * 1024]; 578 579 public Object run() 580 { 581 Arrays.fill(fatty, (byte)31); 582 return null; 583 } 584 } 585 } 586 | Popular Tags |