git clone of logicmail with some fixes/features added
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 504 lines 18 kB view raw
1/*- 2 * Copyright (c) 2010, Derek Konigsberg 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the project nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 * OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package j2meunit.rimui; 33 34import j2meunit.framework.AssertionFailedError; 35import j2meunit.framework.Test; 36import j2meunit.framework.TestCase; 37import j2meunit.framework.TestFailure; 38import j2meunit.framework.TestListener; 39import j2meunit.framework.TestResult; 40import j2meunit.framework.TestSuite; 41import java.util.Enumeration; 42import java.util.Hashtable; 43import java.util.Vector; 44 45import net.rim.device.api.system.Bitmap; 46import net.rim.device.api.system.Characters; 47import net.rim.device.api.ui.Field; 48import net.rim.device.api.ui.Font; 49import net.rim.device.api.ui.Graphics; 50import net.rim.device.api.ui.MenuItem; 51import net.rim.device.api.ui.UiApplication; 52import net.rim.device.api.ui.component.GaugeField; 53import net.rim.device.api.ui.component.LabelField; 54import net.rim.device.api.ui.component.Menu; 55import net.rim.device.api.ui.component.SeparatorField; 56import net.rim.device.api.ui.component.TreeField; 57import net.rim.device.api.ui.component.TreeFieldCallback; 58import net.rim.device.api.ui.container.MainScreen; 59 60/** 61 * J2MEUnit Test Console Screen for the BlackBerry UI. 62 * 63 * @author Derek Konigsberg 64 */ 65public class TestConsoleScreen extends MainScreen implements TestListener { 66 private LabelField titleLabel; 67 private LabelField statusLabel; 68 private LabelField failureLabel; 69 private LabelField errorLabel; 70 private LabelField timeLabel; 71 private GaugeField progressGauge; 72 private TreeField testTreeField; 73 74 private TestSuite mainTestSuite; 75 private Hashtable testTreeItems; 76 private TestResult testResults; 77 private Test selectedTest; 78 private long elapsedTime; 79 80 private Bitmap testInitialBitmap = Bitmap.getBitmapResource("test_initial.png"); 81 private Bitmap testPassedBitmap = Bitmap.getBitmapResource("test_passed.png"); 82 private Bitmap testFailedBitmap = Bitmap.getBitmapResource("test_failed.png"); 83 84 private static class TestTreeItem { 85 public TestTreeItem(Test test) { 86 this.test = test; 87 if(test instanceof TestCase) { 88 name = ((TestCase)test).getName(); 89 } 90 else if(test instanceof TestSuite) { 91 name = ((TestSuite)test).toString(); 92 } 93 else { 94 name = "Test"; 95 } 96 this.hasRun = false; 97 this.hasPassed = true; 98 this.id = 0; 99 } 100 public Test test; 101 public String name; 102 public boolean hasRun; 103 public boolean hasPassed; 104 public int id; 105 } 106 107 /** 108 * Creates a new instance of TestConsoleScreen 109 */ 110 public TestConsoleScreen(String[] testCaseClasses) { 111 initializeFields(); 112 testTreeItems = new Hashtable(); 113 mainTestSuite = createTestSuite(testCaseClasses); 114 elapsedTime = -1; 115 populateTestTree(mainTestSuite, 0); 116 } 117 118 private void initializeFields() { 119 Font labelFont = Font.getDefault().derive(Font.PLAIN, 12); 120 Font treeFont = Font.getDefault().derive(Font.PLAIN, 14); 121 122 titleLabel = new LabelField("J2MEUnit " + j2meunit.util.Version.id()); 123 titleLabel.setFont(labelFont); 124 statusLabel = new LabelField("Status: Idle"); 125 statusLabel.setFont(labelFont); 126 failureLabel = new LabelField("Failures: 0"); 127 failureLabel.setFont(labelFont); 128 errorLabel = new LabelField("Errors: 0"); 129 errorLabel.setFont(labelFont); 130 timeLabel = new LabelField("Time: n/a"); 131 timeLabel.setFont(labelFont); 132 progressGauge = new GaugeField(null, 0, 100, 0, GaugeField.NO_TEXT); 133 progressGauge.setFont(labelFont); 134 135 testTreeField = new TreeField(new TreeFieldCallback() { 136 public void drawTreeItem(TreeField treeField, Graphics graphics, int node, int y, int width, int indent) { 137 testTreeField_DrawTreeItem(treeField, graphics, node, y, width, indent); 138 } 139 }, Field.FOCUSABLE); 140 testTreeField.setEmptyString("No tests", 0); 141 testTreeField.setDefaultExpanded(true); 142 testTreeField.setIndentWidth(20); 143 testTreeField.setFont(treeFont); 144 testTreeField.setRowHeight(treeFont.getHeight() + 2); 145 146 add(titleLabel); 147 add(statusLabel); 148 add(failureLabel); 149 add(errorLabel); 150 add(timeLabel); 151 add(progressGauge); 152 add(new SeparatorField()); 153 add(testTreeField); 154 } 155 156 private void populateTestTree(TestSuite suite, int parentId) { 157 // Get the tests 158 Vector tests = new Vector(); 159 for(Enumeration e = suite.tests(); e.hasMoreElements(); ) { 160 tests.addElement(e.nextElement()); 161 } 162 163 // Iterate backwards so the tree is populated in the correct order 164 int size = tests.size(); 165 for(int i = size - 1; i >= 0; i--) { 166 Test test = (Test)tests.elementAt(i); 167 TestTreeItem item = new TestTreeItem(test); 168 int id = testTreeField.addChildNode(parentId, item); 169 item.id = id; 170 testTreeItems.put(test.toString(), item); 171 if(test instanceof TestSuite) { 172 populateTestTree((TestSuite)test, id); 173 } 174 } 175 } 176 177 /** Standard Escape-key handler */ 178 public boolean keyChar(char key, int status, int time) { 179 boolean retval = false; 180 switch (key) { 181 case 'n': 182 retval = nextSibling(); 183 break; 184 case 'p': 185 retval = prevSibling(); 186 break; 187 case Characters.ENTER: 188 retval = openResultsForCurrentNode(); 189 break; 190 case Characters.ESCAPE: 191 System.exit(1); 192 break; 193 default: 194 retval = super.keyChar(key, status, time); 195 } 196 return retval; 197 } 198 199 private boolean nextSibling() { 200 int id = testTreeField.getCurrentNode(); 201 if(id == -1) { return false; } 202 int nextId = testTreeField.getNextSibling(id); 203 if(nextId == -1) { return false; } 204 205 testTreeField.setCurrentNode(nextId); 206 return true; 207 } 208 209 private boolean prevSibling() { 210 int id = testTreeField.getCurrentNode(); 211 if(id == -1) { return false; } 212 int prevId = testTreeField.getPreviousSibling(id); 213 if(prevId == -1) { return false; } 214 215 testTreeField.setCurrentNode(prevId); 216 return true; 217 } 218 219 private boolean openResultsForCurrentNode() { 220 int node = testTreeField.getCurrentNode(); 221 if(node > 0) { 222 TestTreeItem item = (TestTreeItem)testTreeField.getCookie(node); 223 if(item.hasRun && item.test instanceof TestCase) { 224 showTestResults(); 225 return true; 226 } 227 } 228 return false; 229 } 230 231 private void testTreeField_DrawTreeItem(TreeField treeField, Graphics graphics, int node, int y, int width, int indent) { 232 Object cookie = testTreeField.getCookie(node); 233 234 if(cookie instanceof TestTreeItem) { 235 TestTreeItem item = (TestTreeItem)cookie; 236 int height = testTreeField.getRowHeight(); 237 238 Bitmap iconBitmap = getItemIcon(item); 239 240 graphics.drawBitmap(indent, y, 16, 16, iconBitmap, 0, 0); 241 242 graphics.drawText(item.name, indent + height + 2, y, Graphics.ELLIPSIS, width - height - 2); 243 } 244 } 245 246 private Bitmap getItemIcon(TestTreeItem item) { 247 Bitmap iconBitmap; 248 if(item.hasRun) { 249 if(item.hasPassed) { 250 iconBitmap = testPassedBitmap; 251 } 252 else { 253 iconBitmap = testFailedBitmap; 254 } 255 } 256 else { 257 iconBitmap = testInitialBitmap; 258 } 259 return iconBitmap; 260 } 261 262 private MenuItem resultsItem = new MenuItem("View results", 300100, 1010) { 263 public void run() { 264 showTestResults(); 265 } 266 }; 267 private MenuItem runAllItem = new MenuItem("Run all", 400110, 1020) { 268 public void run() { 269 runAllTests(); 270 } 271 }; 272 private MenuItem runSelectedItem = new MenuItem("Run selected", 400120, 1030) { 273 public void run() { 274 runSelectedTests(); 275 } 276 }; 277 private MenuItem exitItem = new MenuItem("Exit", 60000100, 9000) { 278 public void run() { 279 System.exit(0); 280 } 281 }; 282 283 protected void makeMenu(Menu menu, int instance) { 284 int node = testTreeField.getCurrentNode(); 285 if(node > 0) { 286 TestTreeItem item = (TestTreeItem)testTreeField.getCookie(node); 287 if(item.hasRun && item.test instanceof TestCase) { 288 menu.add(resultsItem); 289 } 290 } 291 menu.add(runAllItem); 292 menu.add(runSelectedItem); 293 menu.add(exitItem); 294 } 295 296 public synchronized void addError(Test test, Throwable throwable) { 297 synchronized(UiApplication.getEventLock()) { 298 errorLabel.setText("Errors: " + testResults.errorCount()); 299 } 300 } 301 302 public synchronized void addFailure(Test test, AssertionFailedError assertionFailedError) { 303 synchronized(UiApplication.getEventLock()) { 304 failureLabel.setText("Failures: " + testResults.failureCount()); 305 } 306 } 307 308 public void endTest(Test test) { 309 synchronized(UiApplication.getEventLock()) { 310 progressGauge.setValue(progressGauge.getValue() + 1); 311 } 312 updateTreeErrors(); 313 updateTestBranch(test); 314 updateTestTree(); 315 } 316 317 public void endTestStep(Test test) { 318 synchronized(UiApplication.getEventLock()) { 319 progressGauge.setValue(progressGauge.getValue() + 1); 320 } 321 updateTreeErrors(); 322 updateTestBranch(test); 323 updateTestTree(); 324 } 325 326 public synchronized void startTest(Test test) { 327 TestTreeItem item = (TestTreeItem)testTreeItems.get(test.toString()); 328 item.hasRun = true; 329 } 330 331 private void updateTestBranch(Test test) { 332 TestTreeItem item = (TestTreeItem)testTreeItems.get(test.toString()); 333 if(item == null) return; 334 boolean hasAllRun = true; 335 boolean hasAllPassed = true; 336 int parentId = testTreeField.getParent(item.id); 337 if(parentId <= 0) return; 338 int node = testTreeField.getFirstChild(parentId); 339 if(node == -1) return; 340 while(node != -1) { 341 item = (TestTreeItem)testTreeField.getCookie(node); 342 if(!item.hasRun) hasAllRun = false; 343 if(!item.hasPassed) hasAllPassed = false; 344 node = testTreeField.getNextSibling(node); 345 } 346 item = (TestTreeItem)testTreeField.getCookie(parentId); 347 item.hasRun = hasAllRun; 348 item.hasPassed = hasAllPassed; 349 350 if(testTreeField.getParent(item.id) >= 0) { 351 updateTestBranch(item.test); 352 } 353 } 354 355 private void updateTreeErrors() { 356 // Update the test data structures 357 TestTreeItem item; 358 Enumeration e; 359 TestFailure failure; 360 for(e = testResults.failures(); e.hasMoreElements(); ) { 361 failure = (TestFailure)e.nextElement(); 362 item = (TestTreeItem)testTreeItems.get(failure.failedTest().toString()); 363 item.hasPassed = false; 364 } 365 for(e = testResults.errors(); e.hasMoreElements(); ) { 366 failure = (TestFailure)e.nextElement(); 367 item = (TestTreeItem)testTreeItems.get(failure.failedTest().toString()); 368 item.hasPassed = false; 369 } 370 } 371 372 private synchronized void updateTestTree() { 373 // Repaint the tree 374 UiApplication.getUiApplication().invokeAndWait(new Runnable() { 375 public void run() { 376 testTreeField.setDirty(true); 377 invalidate(); 378 doPaint(); 379 } 380 }); 381 } 382 383 private void showTestResults() { 384 int node = testTreeField.getCurrentNode(); 385 if(node <= 0) return; 386 TestTreeItem item = (TestTreeItem)testTreeField.getCookie(node); 387 if(!(item.test instanceof TestCase)) return; 388 TestCase testCase = (TestCase)item.test; 389 390 Enumeration e; 391 TestFailure testFailure = null; 392 TestFailure testError = null; 393 394 for(e = testResults.failures(); e.hasMoreElements(); ) { 395 TestFailure failure = (TestFailure)e.nextElement(); 396 if(failure.failedTest() == testCase) { 397 testFailure = failure; 398 break; 399 } 400 } 401 402 for(e = testResults.errors(); e.hasMoreElements(); ) { 403 TestFailure error = (TestFailure)e.nextElement(); 404 if(error.failedTest() == testCase) { 405 testError = error; 406 break; 407 } 408 } 409 410 UiApplication.getUiApplication().pushModalScreen( 411 new TestResultsScreen(testCase, testFailure, testError)); 412 } 413 414 /** 415 * Builds a test suite from all test case classes in a string array. 416 * 417 * @param testCaseClasses A string array containing the test case class names 418 * @return A test suite containing all tests 419 */ 420 protected TestSuite createTestSuite(String[] testCaseClasses) { 421 TestSuite testSuite = new TestSuite(); 422 if (testCaseClasses.length < 1) { 423 return testSuite; 424 } 425 426 for (int i = 0; i < testCaseClasses.length; i++) { 427 try { 428 String className = testCaseClasses[i]; 429 TestCase testCase = 430 (TestCase)Class.forName(className).newInstance(); 431 testSuite.addTest(testCase.suite()); 432 } catch (Throwable t) { 433 System.out.println("Access to TestCase " + testCaseClasses[i] + 434 " failed: " + t.getMessage() + " - " + 435 t.getClass().getName()); 436 } 437 } 438 439 return testSuite; 440 } 441 442 /** 443 * Run all tests in the given test suite. 444 * 445 * @param suite The test suite to run 446 */ 447 protected void doRun(Test suite) { 448 testResults = new TestResult(); 449 testResults.addListener(this); 450 451 long startTime = System.currentTimeMillis(); 452 453 // Mark the suite's tree item 454 TestTreeItem item = (TestTreeItem)testTreeItems.get(suite.toString()); 455 if(item != null) 456 item.hasRun = true; 457 458 // Run the suite 459 suite.run(testResults); 460 461 long endTime = System.currentTimeMillis(); 462 elapsedTime = endTime - startTime; 463 } 464 465 private void runAllTests() { 466 selectedTest = mainTestSuite; 467 runTests(); 468 } 469 470 private void runSelectedTests() { 471 int nodeId = testTreeField.getCurrentNode(); 472 if(nodeId == -1) return; 473 selectedTest = ((TestTreeItem)testTreeField.getCookie(nodeId)).test; 474 runTests(); 475 } 476 477 private void runTests() { 478 statusLabel.setText("Status: Running..."); 479 progressGauge.reset(null, 0, selectedTest.countTestCases(), 0); 480 new Thread() { 481 public void run() { 482 Thread.yield(); 483 try { 484 doRun(selectedTest); 485 updateResults(); 486 } catch (Throwable t) { 487 System.out.println("Exception while running test: " + t); 488 t.printStackTrace(); 489 } 490 } 491 }.start(); 492 } 493 494 private synchronized void updateResults() { 495 UiApplication.getUiApplication().invokeAndWait(new Runnable() { 496 public void run() { 497 statusLabel.setText("Status: Idle"); 498 if(elapsedTime >= 0) { 499 timeLabel.setText("Time: " + elapsedTime + "ms"); 500 } 501 } 502 }); 503 } 504}