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