1 13 package org.eclipse.jdt.internal.junit.model; 14 15 import java.io.BufferedReader ; 16 import java.io.IOException ; 17 import java.io.InputStreamReader ; 18 import java.io.OutputStreamWriter ; 19 import java.io.PrintWriter ; 20 import java.io.UnsupportedEncodingException ; 21 import java.net.ServerSocket ; 22 import java.net.Socket ; 23 import java.net.SocketException ; 24 25 import org.eclipse.core.runtime.ISafeRunnable; 26 import org.eclipse.core.runtime.SafeRunner; 27 28 import org.eclipse.jdt.internal.junit.runner.MessageIds; 29 import org.eclipse.jdt.internal.junit.ui.JUnitPlugin; 30 31 35 public class RemoteTestRunnerClient { 36 public abstract class ListenerSafeRunnable implements ISafeRunnable { 37 public void handleException(Throwable exception) { 38 JUnitPlugin.log(exception); 39 } 40 } 41 44 abstract class ProcessingState { 45 abstract ProcessingState readMessage(String message); 46 } 47 48 class DefaultProcessingState extends ProcessingState { 49 ProcessingState readMessage(String message) { 50 if (message.startsWith(MessageIds.TRACE_START)) { 51 fFailedTrace.setLength(0); 52 return fTraceState; 53 } 54 if (message.startsWith(MessageIds.EXPECTED_START)) { 55 fExpectedResult.setLength(0); 56 return fExpectedState; 57 } 58 if (message.startsWith(MessageIds.ACTUAL_START)) { 59 fActualResult.setLength(0); 60 return fActualState; 61 } 62 if (message.startsWith(MessageIds.RTRACE_START)) { 63 fFailedRerunTrace.setLength(0); 64 return fRerunState; 65 } 66 String arg= message.substring(MessageIds.MSG_HEADER_LENGTH); 67 if (message.startsWith(MessageIds.TEST_RUN_START)) { 68 int count= 0; 71 int v= arg.indexOf(' '); 72 if (v == -1) { 73 fVersion= "v1"; count= Integer.parseInt(arg); 75 } else { 76 fVersion= arg.substring(v+1); 77 String sc= arg.substring(0, v); 78 count= Integer.parseInt(sc); 79 } 80 notifyTestRunStarted(count); 81 return this; 82 } 83 if (message.startsWith(MessageIds.TEST_START)) { 84 notifyTestStarted(arg); 85 return this; 86 } 87 if (message.startsWith(MessageIds.TEST_END)) { 88 notifyTestEnded(arg); 89 return this; 90 } 91 if (message.startsWith(MessageIds.TEST_ERROR)) { 92 extractFailure(arg, ITestRunListener2.STATUS_ERROR); 93 return this; 94 } 95 if (message.startsWith(MessageIds.TEST_FAILED)) { 96 extractFailure(arg, ITestRunListener2.STATUS_FAILURE); 97 return this; 98 } 99 if (message.startsWith(MessageIds.TEST_RUN_END)) { 100 long elapsedTime = Long.parseLong(arg); 101 testRunEnded(elapsedTime); 102 return this; 103 } 104 if (message.startsWith(MessageIds.TEST_STOPPED)) { 105 long elapsedTime = Long.parseLong(arg); 106 notifyTestRunStopped(elapsedTime); 107 shutDown(); 108 return this; 109 } 110 if (message.startsWith(MessageIds.TEST_TREE)) { 111 notifyTestTreeEntry(arg); 112 return this; 113 } 114 if (message.startsWith(MessageIds.TEST_RERAN)) { 115 if (hasTestId()) 116 scanReranMessage(arg); 117 else 118 scanOldReranMessage(arg); 119 return this; 120 } 121 return this; 122 } 123 } 124 125 129 class AppendingProcessingState extends ProcessingState { 130 private final StringBuffer fBuffer; 131 private String fEndString; 132 133 AppendingProcessingState(StringBuffer buffer, String endString) { 134 this.fBuffer= buffer; 135 this.fEndString = endString; 136 } 137 138 ProcessingState readMessage(String message) { 139 if (message.startsWith(fEndString)) { 140 entireStringRead(); 141 return fDefaultState; 142 } 143 fBuffer.append(message); 144 fBuffer.append('\n'); 145 return this; 146 } 147 148 151 void entireStringRead() { 152 } 153 } 154 155 class TraceProcessingState extends AppendingProcessingState { 156 TraceProcessingState() { 157 super(fFailedTrace, MessageIds.TRACE_END); 158 } 159 160 void entireStringRead() { 161 notifyTestFailed(); 162 fExpectedResult.setLength(0); 163 fActualResult.setLength(0); 164 } 165 166 ProcessingState readMessage(String message) { 167 if (message.startsWith(MessageIds.TRACE_END)) { 168 notifyTestFailed(); 169 fFailedTrace.setLength(0); 170 fActualResult.setLength(0); 171 fExpectedResult.setLength(0); 172 return fDefaultState; 173 } 174 fFailedTrace.append(message).append('\n'); 175 return this; 176 } 177 } 178 179 182 private final StringBuffer fFailedTrace = new StringBuffer (); 183 186 private final StringBuffer fExpectedResult = new StringBuffer (); 187 190 private final StringBuffer fActualResult = new StringBuffer (); 191 194 private final StringBuffer fFailedRerunTrace = new StringBuffer (); 195 196 197 ProcessingState fDefaultState= new DefaultProcessingState(); 198 ProcessingState fTraceState= new TraceProcessingState(); 199 ProcessingState fExpectedState= new AppendingProcessingState(fExpectedResult, MessageIds.EXPECTED_END); 200 ProcessingState fActualState= new AppendingProcessingState(fActualResult, MessageIds.ACTUAL_END); 201 ProcessingState fRerunState= new AppendingProcessingState(fFailedRerunTrace, MessageIds.RTRACE_END); 202 ProcessingState fCurrentState= fDefaultState; 203 204 207 private ITestRunListener2[] fListeners; 208 209 212 private ServerSocket fServerSocket; 213 private Socket fSocket; 214 private int fPort= -1; 215 private PrintWriter fWriter; 216 private BufferedReader fBufferedReader; 217 220 private String fVersion; 221 224 private String fFailedTest; 225 228 private String fFailedTestId; 229 232 private int fFailureKind; 233 234 private boolean fDebug= false; 235 236 239 private class ServerConnection extends Thread { 240 int fServerPort; 241 242 public ServerConnection(int port) { 243 super("ServerConnection"); fServerPort= port; 245 } 246 247 public void run() { 248 try { 249 if (fDebug) 250 System.out.println("Creating server socket "+fServerPort); fServerSocket= new ServerSocket (fServerPort); 252 fSocket= fServerSocket.accept(); 253 try { 254 fBufferedReader= new BufferedReader (new InputStreamReader (fSocket.getInputStream(), "UTF-8")); } catch (UnsupportedEncodingException e) { 256 fBufferedReader= new BufferedReader (new InputStreamReader (fSocket.getInputStream())); 257 } 258 try { 259 fWriter= new PrintWriter (new OutputStreamWriter (fSocket.getOutputStream(), "UTF-8"), true); } catch (UnsupportedEncodingException e1) { 261 fWriter= new PrintWriter (new OutputStreamWriter (fSocket.getOutputStream()), true); 262 } 263 String message; 264 while(fBufferedReader != null && (message= readMessage(fBufferedReader)) != null) 265 receiveMessage(message); 266 } catch (SocketException e) { 267 notifyTestRunTerminated(); 268 } catch (IOException e) { 269 JUnitPlugin.log(e); 270 } 272 shutDown(); 273 } 274 } 275 276 283 public synchronized void startListening(ITestRunListener2[] listeners, int port) { 284 fListeners= listeners; 285 fPort= port; 286 ServerConnection connection= new ServerConnection(port); 287 connection.start(); 288 } 289 290 293 public synchronized void stopTest() { 294 if (isRunning()) { 295 fWriter.println(MessageIds.TEST_STOP); 296 fWriter.flush(); 297 } 298 } 299 300 public synchronized void stopWaiting() { 301 if (fServerSocket != null && ! fServerSocket.isClosed() && fSocket == null) { 302 shutDown(); } 304 } 305 306 private synchronized void shutDown() { 307 if (fDebug) 308 System.out.println("shutdown "+fPort); 310 if (fWriter != null) { 311 fWriter.close(); 312 fWriter= null; 313 } 314 try { 315 if (fBufferedReader != null) { 316 fBufferedReader.close(); 317 fBufferedReader= null; 318 } 319 } catch(IOException e) { 320 } 321 try { 322 if (fSocket != null) { 323 fSocket.close(); 324 fSocket= null; 325 } 326 } catch(IOException e) { 327 } 328 try{ 329 if (fServerSocket != null) { 330 fServerSocket.close(); 331 fServerSocket= null; 332 } 333 } catch(IOException e) { 334 } 335 } 336 337 public boolean isRunning() { 338 return fSocket != null; 339 } 340 341 private String readMessage(BufferedReader in) throws IOException { 342 return in.readLine(); 343 } 344 345 private void receiveMessage(String message) { 346 fCurrentState= fCurrentState.readMessage(message); 347 } 348 349 private void scanOldReranMessage(String arg) { 350 int c= arg.indexOf(" "); int t= arg.indexOf(" ", c+1); String className= arg.substring(0, c); 356 String testName= arg.substring(c+1, t); 357 String status= arg.substring(t+1); 358 String testId = className+testName; 359 notifyTestReran(testId, className, testName, status); 360 } 361 362 private void scanReranMessage(String arg) { 363 int i= arg.indexOf(' '); 366 int c= arg.indexOf(' ', i+1); 367 int t= arg.indexOf(' ', c+1); 368 String testId= arg.substring(0, i); 369 String className= arg.substring(i+1, c); 370 String testName= arg.substring(c+1, t); 371 String status= arg.substring(t+1); 372 notifyTestReran(testId, className, testName, status); 373 } 374 375 private void notifyTestReran(String testId, String className, String testName, String status) { 376 int statusCode= ITestRunListener2.STATUS_OK; 377 if (status.equals("FAILURE")) statusCode= ITestRunListener2.STATUS_FAILURE; 379 else if (status.equals("ERROR")) statusCode= ITestRunListener2.STATUS_ERROR; 381 382 String trace= ""; if (statusCode != ITestRunListener2.STATUS_OK) 384 trace = fFailedRerunTrace.toString(); 385 notifyTestReran(testId, className, testName, statusCode, trace); 387 } 388 389 private void extractFailure(String arg, int status) { 390 String s[]= extractTestId(arg); 391 fFailedTestId= s[0]; 392 fFailedTest= s[1]; 393 fFailureKind= status; 394 } 395 396 400 String [] extractTestId(String arg) { 401 String [] result= new String [2]; 402 if (!hasTestId()) { 403 result[0]= arg; result[1]= arg; 405 return result; 406 } 407 int i= arg.indexOf(','); 408 result[0]= arg.substring(0, i); 409 result[1]= arg.substring(i+1, arg.length()); 410 return result; 411 } 412 413 private boolean hasTestId() { 414 if (fVersion == null) return true; 416 return fVersion.equals("v2"); } 418 419 private void notifyTestReran(final String testId, final String className, final String testName, final int statusCode, final String trace) { 420 for (int i= 0; i < fListeners.length; i++) { 421 final ITestRunListener2 listener= fListeners[i]; 422 SafeRunner.run(new ListenerSafeRunnable() { 423 public void run() { 424 listener.testReran(testId, 425 className, testName, statusCode, trace, 426 fExpectedResult.toString(), fActualResult.toString()); 427 } 428 }); 429 } 430 } 431 432 private void notifyTestTreeEntry(final String treeEntry) { 433 for (int i= 0; i < fListeners.length; i++) { 434 ITestRunListener2 listener= fListeners[i]; 435 if (!hasTestId()) 436 listener.testTreeEntry(fakeTestId(treeEntry)); 437 else 438 listener.testTreeEntry(treeEntry); 439 } 440 } 441 442 private String fakeTestId(String treeEntry) { 443 int index0= treeEntry.indexOf(','); 445 String testName= treeEntry.substring(0, index0).trim(); 446 return testName+","+treeEntry; } 448 449 private void notifyTestRunStopped(final long elapsedTime) { 450 if (JUnitPlugin.isStopped()) 451 return; 452 for (int i= 0; i < fListeners.length; i++) { 453 final ITestRunListener2 listener= fListeners[i]; 454 SafeRunner.run(new ListenerSafeRunnable() { 455 public void run() { 456 listener.testRunStopped(elapsedTime); 457 } 458 }); 459 } 460 } 461 462 private void testRunEnded(final long elapsedTime) { 463 if (JUnitPlugin.isStopped()) 464 return; 465 for (int i= 0; i < fListeners.length; i++) { 466 final ITestRunListener2 listener= fListeners[i]; 467 SafeRunner.run(new ListenerSafeRunnable() { 468 public void run() { 469 listener.testRunEnded(elapsedTime); 470 } 471 }); 472 } 473 } 474 475 private void notifyTestEnded(final String test) { 476 if (JUnitPlugin.isStopped()) 477 return; 478 for (int i= 0; i < fListeners.length; i++) { 479 final ITestRunListener2 listener= fListeners[i]; 480 SafeRunner.run(new ListenerSafeRunnable() { 481 public void run() { 482 String s[]= extractTestId(test); 483 listener.testEnded(s[0], s[1]); 484 } 485 }); 486 } 487 } 488 489 private void notifyTestStarted(final String test) { 490 if (JUnitPlugin.isStopped()) 491 return; 492 for (int i= 0; i < fListeners.length; i++) { 493 final ITestRunListener2 listener= fListeners[i]; 494 SafeRunner.run(new ListenerSafeRunnable() { 495 public void run() { 496 String s[]= extractTestId(test); 497 listener.testStarted(s[0], s[1]); 498 } 499 }); 500 } 501 } 502 503 private void notifyTestRunStarted(final int count) { 504 if (JUnitPlugin.isStopped()) 505 return; 506 for (int i= 0; i < fListeners.length; i++) { 507 final ITestRunListener2 listener= fListeners[i]; 508 SafeRunner.run(new ListenerSafeRunnable() { 509 public void run() { 510 listener.testRunStarted(count); 511 } 512 }); 513 } 514 } 515 516 private void notifyTestFailed() { 517 if (JUnitPlugin.isStopped()) 518 return; 519 for (int i= 0; i < fListeners.length; i++) { 520 final ITestRunListener2 listener= fListeners[i]; 521 SafeRunner.run(new ListenerSafeRunnable() { 522 public void run() { 523 listener.testFailed(fFailureKind, fFailedTestId, 524 fFailedTest, fFailedTrace.toString(), fExpectedResult.toString(), fActualResult.toString()); 525 } 526 }); 527 } 528 } 529 530 private void notifyTestRunTerminated() { 531 if (JUnitPlugin.isStopped()) 533 return; 534 for (int i= 0; i < fListeners.length; i++) { 535 final ITestRunListener2 listener= fListeners[i]; 536 SafeRunner.run(new ListenerSafeRunnable() { 537 public void run() { 538 listener.testRunTerminated(); 539 } 540 }); 541 } 542 } 543 544 public void rerunTest(String testId, String className, String testName) { 545 if (isRunning()) { 546 fActualResult.setLength(0); 547 fExpectedResult.setLength(0); 548 fWriter.println(MessageIds.TEST_RERUN+testId+" "+className+" "+testName); fWriter.flush(); 550 } 551 } 552 } 553 | Popular Tags |