1 12 package org.eclipse.jdt.junit.launcher; 13 14 import java.io.BufferedWriter ; 15 import java.io.File ; 16 import java.io.FileWriter ; 17 import java.io.IOException ; 18 import java.net.MalformedURLException ; 19 import java.net.URL ; 20 import java.text.MessageFormat ; 21 import java.util.ArrayList ; 22 import java.util.Arrays ; 23 import java.util.HashSet ; 24 import java.util.List ; 25 import java.util.Map ; 26 27 import org.eclipse.core.runtime.Assert; 28 import org.eclipse.core.runtime.CoreException; 29 import org.eclipse.core.runtime.FileLocator; 30 import org.eclipse.core.runtime.IProgressMonitor; 31 import org.eclipse.core.runtime.IStatus; 32 import org.eclipse.core.runtime.NullProgressMonitor; 33 import org.eclipse.core.runtime.Platform; 34 import org.eclipse.core.runtime.Status; 35 import org.eclipse.core.runtime.SubProgressMonitor; 36 37 import org.eclipse.core.variables.VariablesPlugin; 38 39 import org.eclipse.swt.widgets.Display; 40 import org.eclipse.swt.widgets.Shell; 41 42 import org.eclipse.jface.dialogs.MessageDialog; 43 44 import org.eclipse.debug.core.ILaunch; 45 import org.eclipse.debug.core.ILaunchConfiguration; 46 import org.eclipse.debug.core.ILaunchManager; 47 48 import org.eclipse.jdt.core.IJavaElement; 49 import org.eclipse.jdt.core.IJavaProject; 50 import org.eclipse.jdt.core.IMember; 51 import org.eclipse.jdt.core.IMethod; 52 import org.eclipse.jdt.core.IType; 53 import org.eclipse.jdt.core.JavaCore; 54 55 import org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate; 56 import org.eclipse.jdt.launching.ExecutionArguments; 57 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; 58 import org.eclipse.jdt.launching.IVMRunner; 59 import org.eclipse.jdt.launching.SocketUtil; 60 import org.eclipse.jdt.launching.VMRunnerConfiguration; 61 62 import org.eclipse.jdt.internal.junit.Messages; 63 import org.eclipse.jdt.internal.junit.launcher.ITestKind; 64 import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants; 65 import org.eclipse.jdt.internal.junit.launcher.JUnitRuntimeClasspathEntry; 66 import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry; 67 import org.eclipse.jdt.internal.junit.ui.JUnitMessages; 68 import org.eclipse.jdt.internal.junit.ui.JUnitPlugin; 69 import org.eclipse.jdt.internal.junit.util.IJUnitStatusConstants; 70 import org.eclipse.jdt.internal.junit.util.TestSearchEngine; 71 72 import org.osgi.framework.Bundle; 73 74 82 public class JUnitLaunchConfigurationDelegate extends AbstractJavaLaunchConfigurationDelegate { 83 84 private boolean fKeepAlive= false; 85 private int fPort; 86 private IMember[] fTestElements; 87 88 91 public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { 92 if (monitor == null) { 93 monitor = new NullProgressMonitor(); 94 } 95 96 monitor.beginTask(MessageFormat.format("{0}...", new String []{configuration.getName()}), 5); if (monitor.isCanceled()) { 99 return; 100 } 101 102 try { 103 if (mode.equals(JUnitLaunchConfigurationConstants.MODE_RUN_QUIETLY_MODE)) { 104 launch.setAttribute(JUnitLaunchConfigurationConstants.ATTR_NO_DISPLAY, "true"); mode = ILaunchManager.RUN_MODE; 106 } 107 108 monitor.subTask(JUnitMessages.JUnitLaunchConfigurationDelegate_verifying_attriburtes_description); 109 110 try { 111 preLaunchCheck(configuration, launch, new SubProgressMonitor(monitor, 2)); 112 } catch (CoreException e) { 113 if (e.getStatus().getSeverity() == IStatus.CANCEL) { 114 monitor.setCanceled(true); 115 return; 116 } 117 throw e; 118 } 119 if (monitor.isCanceled()) { 121 return; 122 } 123 124 fKeepAlive= mode.equals(ILaunchManager.DEBUG_MODE) && configuration.getAttribute(JUnitLaunchConfigurationConstants.ATTR_KEEPRUNNING, false); 125 fPort= evaluatePort(); 126 launch.setAttribute(JUnitLaunchConfigurationConstants.ATTR_PORT, String.valueOf(fPort)); 127 128 fTestElements= evaluateTests(configuration, new SubProgressMonitor(monitor, 1)); 129 130 String mainTypeName= verifyMainTypeName(configuration); 131 IVMRunner runner= getVMRunner(configuration, mode); 132 133 File workingDir = verifyWorkingDirectory(configuration); 134 String workingDirName = null; 135 if (workingDir != null) { 136 workingDirName= workingDir.getAbsolutePath(); 137 } 138 139 String [] envp= getEnvironment(configuration); 141 142 ArrayList vmArguments= new ArrayList (); 143 ArrayList programArguments= new ArrayList (); 144 collectExecutionArguments(configuration, vmArguments, programArguments); 145 146 Map vmAttributesMap= getVMSpecificAttributesMap(configuration); 148 149 String [] classpath= getClasspath(configuration); 151 152 VMRunnerConfiguration runConfig= new VMRunnerConfiguration(mainTypeName, classpath); 154 runConfig.setVMArguments((String []) vmArguments.toArray(new String [vmArguments.size()])); 155 runConfig.setProgramArguments((String []) programArguments.toArray(new String [programArguments.size()])); 156 runConfig.setEnvironment(envp); 157 runConfig.setWorkingDirectory(workingDirName); 158 runConfig.setVMSpecificAttributesMap(vmAttributesMap); 159 160 runConfig.setBootClassPath(getBootpath(configuration)); 162 163 if (monitor.isCanceled()) { 165 return; 166 } 167 168 monitor.worked(1); 170 171 monitor.subTask(JUnitMessages.JUnitLaunchConfigurationDelegate_create_source_locator_description); 172 setDefaultSourceLocator(launch, configuration); 174 monitor.worked(1); 175 176 runner.run(runConfig, launch, monitor); 178 179 if (monitor.isCanceled()) { 181 return; 182 } 183 } finally { 184 fTestElements= null; 185 monitor.done(); 186 } 187 } 188 189 private int evaluatePort() throws CoreException { 190 int port= SocketUtil.findFreePort(); 191 if (port == -1) { 192 informAndAbort(JUnitMessages.JUnitLaunchConfigurationDelegate_error_no_socket, null, IJavaLaunchConfigurationConstants.ERR_NO_SOCKET_AVAILABLE); 193 } 194 return port; 195 } 196 197 206 protected void preLaunchCheck(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor) throws CoreException { 207 try { 208 IJavaProject javaProject= getJavaProject(configuration); 209 if ((javaProject == null) || !javaProject.exists()) { 210 informAndAbort(JUnitMessages.JUnitLaunchConfigurationDelegate_error_invalidproject, null, IJavaLaunchConfigurationConstants.ERR_NOT_A_JAVA_PROJECT); 211 } 212 if (!TestSearchEngine.hasTestCaseType(javaProject)) { 213 informAndAbort(JUnitMessages.JUnitLaunchConfigurationDelegate_error_junitnotonpath, null, IJUnitStatusConstants.ERR_JUNIT_NOT_ON_PATH); 214 } 215 216 ITestKind testKind= getTestRunnerKind(configuration); 217 boolean isJUnit4Configuration= TestKindRegistry.JUNIT4_TEST_KIND_ID.equals(testKind.getId()); 218 if (isJUnit4Configuration && ! TestSearchEngine.hasTestAnnotation(javaProject)) { 219 informAndAbort(JUnitMessages.JUnitLaunchConfigurationDelegate_error_junit4notonpath, null, IJUnitStatusConstants.ERR_JUNIT_NOT_ON_PATH); 220 } 221 } finally { 222 monitor.done(); 223 } 224 } 225 226 private ITestKind getTestRunnerKind(ILaunchConfiguration configuration) { 227 ITestKind testKind= JUnitLaunchConfigurationConstants.getTestRunnerKind(configuration); 228 if (testKind.isNull()) { 229 testKind= TestKindRegistry.getDefault().getKind(TestKindRegistry.JUNIT3_TEST_KIND_ID); } 231 return testKind; 232 } 233 234 237 public String verifyMainTypeName(ILaunchConfiguration configuration) throws CoreException { 238 return "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"; } 240 241 251 protected IMember[] evaluateTests(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException { 252 IJavaProject javaProject= getJavaProject(configuration); 253 254 IJavaElement testTarget= getTestTarget(configuration, javaProject); 255 String testMethodName= configuration.getAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME, ""); if (testMethodName.length() > 0) { 257 if (testTarget instanceof IType) { 258 return new IMember[] { ((IType) testTarget).getMethod(testMethodName, new String [0]) }; 259 } 260 } 261 HashSet result= new HashSet (); 262 ITestKind testKind= getTestRunnerKind(configuration); 263 testKind.getFinder().findTestsInContainer(testTarget, result, monitor); 264 if (result.isEmpty()) { 265 String msg= Messages.format(JUnitMessages.JUnitLaunchConfigurationDelegate_error_notests_kind, testKind.getDisplayName()); 266 informAndAbort(msg, null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_MAIN_TYPE); 267 } 268 return (IMember[]) result.toArray(new IMember[result.size()]); 269 } 270 271 private void informAndAbort(String message, Throwable exception, int code) throws CoreException { 272 IStatus status= new Status(IStatus.INFO, JUnitPlugin.PLUGIN_ID, code, message, exception); 273 if (showStatusMessage(status)) { 274 throw new CoreException(status); 278 } else { 279 abort(message, exception, code); 283 } 284 } 285 286 294 protected void collectExecutionArguments(ILaunchConfiguration configuration, List vmArguments, List programArguments) throws CoreException { 295 296 String pgmArgs= getProgramArguments(configuration); 298 String vmArgs= getVMArguments(configuration); 299 ExecutionArguments execArgs= new ExecutionArguments(vmArgs, pgmArgs); 300 vmArguments.addAll(Arrays.asList(execArgs.getVMArgumentsArray())); 301 programArguments.addAll(Arrays.asList(execArgs.getProgramArgumentsArray())); 302 303 String testFailureNames= configuration.getAttribute(JUnitLaunchConfigurationConstants.ATTR_FAILURES_NAMES, ""); 305 programArguments.add("-version"); programArguments.add("3"); 308 programArguments.add("-port"); programArguments.add(String.valueOf(fPort)); 310 311 if (fKeepAlive) 312 programArguments.add(0, "-keepalive"); 314 ITestKind testRunnerKind= getTestRunnerKind(configuration); 315 316 programArguments.add("-testLoaderClass"); programArguments.add(testRunnerKind.getLoaderClassName()); 318 programArguments.add("-loaderpluginname"); programArguments.add(testRunnerKind.getLoaderPluginId()); 320 321 IMember[] testElements = fTestElements; 322 323 if (testElements.length == 1) { 325 if (testElements[0] instanceof IMethod) { 326 IMethod method= (IMethod) testElements[0]; 327 programArguments.add("-test"); programArguments.add(method.getDeclaringType().getFullyQualifiedName()+':'+method.getElementName()); 329 } else if (testElements[0] instanceof IType) { 330 IType type= (IType) testElements[0]; 331 programArguments.add("-classNames"); programArguments.add(type.getFullyQualifiedName()); 333 } else { 334 informAndAbort(JUnitMessages.JUnitLaunchConfigurationDelegate_error_wrong_input, null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_MAIN_TYPE); 335 } 336 } else if (testElements.length > 1) { 337 String fileName= createTestNamesFile(testElements); 338 programArguments.add("-testNameFile"); programArguments.add(fileName); 340 } 341 if (testFailureNames.length() > 0) { 342 programArguments.add("-testfailures"); programArguments.add(testFailureNames); 344 } 345 } 346 347 private String createTestNamesFile(IMember[] testElements) throws CoreException { 348 try { 349 File file= File.createTempFile("testNames", ".txt"); file.deleteOnExit(); 351 BufferedWriter bw= null; 352 try { 353 bw= new BufferedWriter (new FileWriter (file)); 354 for (int i= 0; i < testElements.length; i++) { 355 if (testElements[i] instanceof IType) { 356 IType type= (IType) testElements[i]; 357 String testName= type.getFullyQualifiedName(); 358 bw.write(testName); 359 bw.newLine(); 360 } else { 361 informAndAbort(JUnitMessages.JUnitLaunchConfigurationDelegate_error_wrong_input, null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_MAIN_TYPE); 362 } 363 } 364 } finally { 365 if (bw != null) { 366 bw.close(); 367 } 368 } 369 return file.getAbsolutePath(); 370 } catch (IOException e) { 371 throw new CoreException(new Status(IStatus.ERROR, JUnitPlugin.PLUGIN_ID, IStatus.ERROR, "", e)); } 373 } 374 375 378 public String [] getClasspath(ILaunchConfiguration configuration) throws CoreException { 379 String [] cp= super.getClasspath(configuration); 380 381 ITestKind kind= getTestRunnerKind(configuration); 382 List junitEntries = new ClasspathLocalizer(Platform.inDevelopmentMode()).localizeClasspath(kind); 383 384 String [] classPath= new String [cp.length + junitEntries.size()]; 385 Object [] jea= junitEntries.toArray(); 386 System.arraycopy(cp, 0, classPath, 0, cp.length); 387 System.arraycopy(jea, 0, classPath, cp.length, jea.length); 388 return classPath; 389 } 390 391 private static class ClasspathLocalizer { 392 393 private boolean fInDevelopmentMode; 394 395 protected ClasspathLocalizer() { 396 this(false); 397 } 398 399 public ClasspathLocalizer(boolean inDevelopmentMode) { 400 fInDevelopmentMode = inDevelopmentMode; 401 } 402 403 public List localizeClasspath(ITestKind kind) { 404 JUnitRuntimeClasspathEntry[] entries= kind.getClasspathEntries(); 405 List junitEntries= new ArrayList (); 406 407 for (int i= 0; i < entries.length; i++) { 408 try { 409 addEntry(junitEntries, entries[i]); 410 } catch (IOException e) { 411 Assert.isTrue(false, entries[i].getPluginId() + " is available (required JAR)"); } 413 } 414 return junitEntries; 415 } 416 417 private void addEntry(List junitEntries, final JUnitRuntimeClasspathEntry entry) throws IOException , MalformedURLException { 418 String entryString= entryString(entry); 419 if (entryString != null) 420 junitEntries.add(entryString); 421 } 422 423 private String entryString(final JUnitRuntimeClasspathEntry entry) throws IOException , MalformedURLException { 424 if (inDevelopmentMode()) { 425 try { 426 return localURL(entry.developmentModeEntry()); 427 } catch (IOException e3) { 428 } 430 } 431 return localURL(entry); 432 } 433 434 private boolean inDevelopmentMode() { 435 return fInDevelopmentMode; 436 } 437 438 private String localURL(JUnitRuntimeClasspathEntry jar) throws IOException , MalformedURLException { 439 Bundle bundle= JUnitPlugin.getDefault().getBundle(jar.getPluginId()); 440 URL url; 441 if (jar.getPluginRelativePath() == null) 442 url= bundle.getEntry("/"); else 444 url= bundle.getEntry(jar.getPluginRelativePath()); 445 if (url == null) 446 throw new IOException (); 447 return FileLocator.toFileURL(url).getFile(); 448 } 449 } 450 451 private final IJavaElement getTestTarget(ILaunchConfiguration configuration, IJavaProject javaProject) throws CoreException { 452 String containerHandle = configuration.getAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, ""); if (containerHandle.length() != 0) { 454 IJavaElement element= JavaCore.create(containerHandle); 455 if (element == null || !element.exists()) { 456 informAndAbort(JUnitMessages.JUnitLaunchConfigurationDelegate_error_input_element_deosn_not_exist, null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_MAIN_TYPE); 457 } 458 return element; 459 } 460 String testTypeName= configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); if (testTypeName.length() != 0) { 462 testTypeName= performStringSubstitution(testTypeName); 463 IType type= javaProject.findType(testTypeName); 464 if (type != null && type.exists()) { 465 return type; 466 } 467 } 468 informAndAbort(JUnitMessages.JUnitLaunchConfigurationDelegate_input_type_does_not_exist, null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_MAIN_TYPE); 469 return null; } 471 472 private final String performStringSubstitution(String testTypeName) throws CoreException { 473 return VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(testTypeName); 474 } 475 476 private boolean showStatusMessage(final IStatus status) { 477 final boolean[] success= new boolean[] { false }; 478 getDisplay().syncExec( 479 new Runnable () { 480 public void run() { 481 Shell shell= JUnitPlugin.getActiveWorkbenchShell(); 482 if (shell == null) 483 shell= getDisplay().getActiveShell(); 484 if (shell != null) { 485 MessageDialog.openInformation(shell, JUnitMessages.JUnitLaunchConfigurationDelegate_dialog_title, status.getMessage()); 486 success[0]= true; 487 } 488 } 489 } 490 ); 491 return success[0]; 492 } 493 494 private Display getDisplay() { 495 Display display; 496 display= Display.getCurrent(); 497 if (display == null) 498 display= Display.getDefault(); 499 return display; 500 } 501 502 505 protected void abort(String message, Throwable exception, int code) throws CoreException { 506 throw new CoreException(new Status(IStatus.ERROR, JUnitPlugin.PLUGIN_ID, code, message, exception)); 507 } 508 509 } 510 | Popular Tags |