1 16 package com.google.gwt.junit; 17 18 import com.google.gwt.core.ext.TreeLogger; 19 import com.google.gwt.core.ext.UnableToCompleteException; 20 import com.google.gwt.dev.BootStrapPlatform; 21 import com.google.gwt.dev.GWTShell; 22 import com.google.gwt.dev.cfg.ModuleDef; 23 import com.google.gwt.dev.cfg.ModuleDefLoader; 24 import com.google.gwt.dev.shell.BrowserWidgetHost; 25 import com.google.gwt.dev.util.log.PrintWriterTreeLogger; 26 import com.google.gwt.junit.benchmarks.BenchmarkReport; 27 import com.google.gwt.junit.client.Benchmark; 28 import com.google.gwt.junit.client.TestResults; 29 import com.google.gwt.junit.client.TimeoutException; 30 import com.google.gwt.junit.client.Trial; 31 import com.google.gwt.junit.remote.BrowserManager; 32 import com.google.gwt.util.tools.ArgHandlerFlag; 33 import com.google.gwt.util.tools.ArgHandlerString; 34 35 import junit.framework.AssertionFailedError; 36 import junit.framework.TestCase; 37 import junit.framework.TestResult; 38 39 import java.io.File ; 40 import java.rmi.Naming ; 41 import java.util.ArrayList ; 42 import java.util.Date ; 43 import java.util.List ; 44 import java.util.regex.Matcher ; 45 import java.util.regex.Pattern ; 46 47 76 public class JUnitShell extends GWTShell { 77 78 85 private class Shutdown implements Runnable { 86 87 public void run() { 88 try { 89 String reportPath = System.getProperty(Benchmark.REPORT_PATH); 90 if (reportPath == null || reportPath.trim().equals("")) { 91 reportPath = System.getProperty("user.dir"); 92 } 93 report.generate(reportPath + File.separator + "report-" 94 + new Date ().getTime() + ".xml"); 95 } catch (Exception e) { 96 e.printStackTrace(); 99 } 100 } 101 } 102 103 106 private static final String PROP_GWT_ARGS = "gwt.args"; 107 108 112 private static final String PROP_JUNIT_HYBRID_MODE = "gwt.hybrid"; 113 114 118 private static final int TEST_BEGIN_TIMEOUT_MILLIS = 60000; 119 120 124 private static JUnitShell unitTestShell; 125 126 static { 127 ModuleDefLoader.forceInherit("com.google.gwt.junit.JUnit"); 128 ModuleDefLoader.setEnableCachingModules(true); 129 } 130 131 139 public static JUnitMessageQueue getMessageQueue() { 140 if (unitTestShell == null) { 141 return null; 142 } 143 return unitTestShell.messageQueue; 144 } 145 146 153 public static BenchmarkReport getReport() { 154 if (unitTestShell == null) { 155 return null; 156 } 157 return unitTestShell.report; 158 } 159 160 165 public static void runTest(String moduleName, TestCase testCase, 166 TestResult testResult) throws UnableToCompleteException { 167 getUnitTestShell().runTestImpl(moduleName, testCase, testResult); 168 } 169 170 174 private static JUnitShell getUnitTestShell() { 175 if (unitTestShell == null) { 176 BootStrapPlatform.go(); 177 JUnitShell shell = new JUnitShell(); 178 String [] args = shell.synthesizeArgs(); 179 if (!shell.processArgs(args)) { 180 throw new RuntimeException ("Invalid shell arguments"); 181 } 182 183 shell.messageQueue = new JUnitMessageQueue(shell.numClients); 184 185 if (!shell.startUp()) { 186 throw new RuntimeException ("Shell failed to start"); 187 } 188 189 shell.report = new BenchmarkReport(shell.getTopLogger()); 190 unitTestShell = shell; 191 192 Runtime.getRuntime().addShutdownHook(new Thread (shell.new Shutdown ())); 193 } 194 195 return unitTestShell; 196 } 197 198 201 private PrintWriterTreeLogger consoleLogger; 202 203 206 private String currentModuleName; 207 208 211 private boolean lastLaunchFailed; 212 213 216 private JUnitMessageQueue messageQueue; 217 218 223 private int numClients = 1; 224 225 228 private BenchmarkReport report; 229 230 233 private RunStyle runStyle = new RunStyleLocalHosted(this); 234 235 239 private long testBeginTimeout; 240 241 244 private String testCaseClassName; 245 246 250 private JUnitShell() { 251 super(true, true); 252 253 registerHandler(new ArgHandlerFlag() { 254 255 public String getPurpose() { 256 return "Causes your test to run in web (compiled) mode (defaults to hosted mode)"; 257 } 258 259 public String getTag() { 260 return "-web"; 261 } 262 263 public boolean setFlag() { 264 runStyle = new RunStyleLocalWeb(JUnitShell.this); 265 return true; 266 } 267 268 }); 269 270 registerHandler(new ArgHandlerString() { 271 272 public String getPurpose() { 273 return "Runs web mode via RMI to a BrowserManagerServer; e.g. rmi://localhost/ie6"; 274 } 275 276 public String getTag() { 277 return "-remoteweb"; 278 } 279 280 public String [] getTagArgs() { 281 return new String [] {"rmiUrl"}; 282 } 283 284 public boolean isUndocumented() { 285 return true; 286 } 287 288 public boolean setString(String str) { 289 try { 290 String [] urls = str.split(","); 291 numClients = urls.length; 292 BrowserManager[] browserManagers = new BrowserManager[numClients]; 293 for (int i = 0; i < numClients; ++i) { 294 browserManagers[i] = (BrowserManager) Naming.lookup(urls[i]); 295 } 296 runStyle = new RunStyleRemoteWeb(JUnitShell.this, browserManagers); 297 } catch (Exception e) { 298 System.err.println("Error connecting to browser manager at " + str); 299 e.printStackTrace(); 300 System.exit(1); 301 return false; 302 } 303 return true; 304 } 305 }); 306 307 registerHandler(new ArgHandlerFlag() { 308 309 public String getPurpose() { 310 return "Causes the log window and browser windows to be displayed; useful for debugging"; 311 } 312 313 public String getTag() { 314 return "-notHeadless"; 315 } 316 317 public boolean setFlag() { 318 setHeadless(false); 319 return true; 320 } 321 }); 322 323 setRunTomcat(true); 324 setHeadless(true); 325 326 if (System.getProperty(PROP_JUNIT_HYBRID_MODE) != null) { 328 runStyle = new RunStyleLocalWeb(this); 329 } 330 } 331 332 public TreeLogger getTopLogger() { 333 if (consoleLogger != null) { 334 return consoleLogger; 335 } else { 336 return super.getTopLogger(); 337 } 338 } 339 340 protected String doGetDefaultLogLevel() { 341 return "WARN"; 342 } 343 344 349 protected ModuleDef doLoadModule(TreeLogger logger, String moduleName) 350 throws UnableToCompleteException { 351 352 ModuleDef module = super.doLoadModule(logger, moduleName); 353 354 if (moduleName.equals(currentModuleName)) { 357 module.clearEntryPoints(); 358 module.addEntryPointTypeName(testCaseClassName); 359 } 360 return module; 361 } 362 363 366 protected boolean doShouldCheckForUpdates() { 367 return false; 368 } 369 370 protected ArgHandlerPort getArgHandlerPort() { 371 return new ArgHandlerPort() { 372 public String [] getDefaultArgs() { 373 return new String [] {"-port", "auto"}; 374 } 375 }; 376 } 377 378 protected void initializeLogger() { 379 if (isHeadless()) { 380 consoleLogger = new PrintWriterTreeLogger(); 381 consoleLogger.setMaxDetail(getLogLevel()); 382 } else { 383 super.initializeLogger(); 384 } 385 } 386 387 391 protected boolean notDone() { 392 if (!messageQueue.haveAllClientsRetrievedCurrentTest() 393 && testBeginTimeout < System.currentTimeMillis()) { 394 throw new TimeoutException( 395 "The browser did not contact the server within " 396 + TEST_BEGIN_TIMEOUT_MILLIS + "ms."); 397 } 398 399 if (messageQueue.hasResult(testCaseClassName)) { 400 return false; 401 } 402 403 return !runStyle.wasInterrupted(); 404 } 405 406 void compileForWebMode(String moduleName) throws UnableToCompleteException { 407 BrowserWidgetHost browserHost = getBrowserHost(); 408 assert (browserHost != null); 409 browserHost.compile(new String [] {moduleName}); 410 } 411 412 415 private void runTestImpl(String moduleName, TestCase testCase, 416 TestResult testResult) throws UnableToCompleteException { 417 418 String newTestCaseClassName = testCase.getClass().getName(); 419 boolean sameTest = newTestCaseClassName.equals(testCaseClassName); 420 if (sameTest && lastLaunchFailed) { 421 throw new UnableToCompleteException(); 422 } 423 424 messageQueue.setNextTestName(newTestCaseClassName, testCase.getName()); 425 426 try { 427 lastLaunchFailed = false; 428 testCaseClassName = newTestCaseClassName; 429 currentModuleName = moduleName; 430 runStyle.maybeLaunchModule(moduleName, !sameTest); 431 } catch (UnableToCompleteException e) { 432 lastLaunchFailed = true; 433 testResult.addError(testCase, e); 434 return; 435 } 436 437 try { 439 testBeginTimeout = System.currentTimeMillis() + TEST_BEGIN_TIMEOUT_MILLIS; 442 pumpEventLoop(); 443 } catch (TimeoutException e) { 444 lastLaunchFailed = true; 445 testResult.addError(testCase, e); 446 return; 447 } 448 449 List results 450 = messageQueue.getResults(testCaseClassName); 451 452 if (results == null) { 453 return; 454 } 455 456 boolean parallelTesting = numClients > 1; 457 458 for (int i = 0; i < results.size(); ++i) { 459 TestResults result = (TestResults) results.get(i); 460 Trial firstTrial = (Trial) result.getTrials().get(0); 461 Throwable exception = firstTrial.getException(); 462 463 if (parallelTesting && exception != null) { 466 String msg = "Remote test failed at " + result.getHost() + " on " 467 + result.getAgent(); 468 if (exception instanceof AssertionFailedError) { 469 AssertionFailedError newException = new AssertionFailedError(msg 470 + "\n" + exception.getMessage()); 471 newException.setStackTrace(exception.getStackTrace()); 472 exception = newException; 473 } else { 474 exception = new RuntimeException (msg, exception); 475 } 476 } 477 478 if (exception instanceof AssertionFailedError) { 480 testResult.addFailure(testCase, (AssertionFailedError) exception); 481 } else if (exception != null) { 482 testResult.addError(testCase, exception); 484 } 485 486 if (testCase instanceof Benchmark) { 487 report.addBenchmarkResults(testCase, result); 488 } 489 } 490 } 491 492 495 private String [] synthesizeArgs() { 496 ArrayList argList = new ArrayList (); 497 498 String args = System.getProperty(PROP_GWT_ARGS); 499 if (args != null) { 500 Pattern pattern = Pattern.compile("[^\\s\"]+|\"[^\"\\\\]*(\\\\.[^\"\\\\]*)*\""); 504 Matcher matcher = pattern.matcher(args); 505 while (matcher.find()) { 506 argList.add(matcher.group()); 507 } 508 } 509 510 return (String []) argList.toArray(new String [argList.size()]); 511 } 512 } 513 | Popular Tags |