diff --git a/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/ScalaDebugTestSuite.scala b/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/ScalaDebugTestSuite.scala index 690dcb8537..59487affdb 100644 --- a/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/ScalaDebugTestSuite.scala +++ b/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/ScalaDebugTestSuite.scala @@ -17,6 +17,7 @@ import org.scalaide.debug.internal.model.ScalaDebugTargetTest import org.scalaide.debug.internal.model.ScalaStackFrameTest import org.scalaide.debug.internal.model.ScalaThreadTest import org.scalaide.debug.internal.model.ScalaValueTest +import org.scalaide.debug.internal.launching.ScalaApplicationLaunchConfigurationDelegateTest /** * Junit test suite for the Scala debugger. @@ -40,6 +41,7 @@ import org.scalaide.debug.internal.model.ScalaValueTest classOf[ScalaDebugBreakpointTest], classOf[ScalaDebugCacheTest], classOf[StackFrameVariableOfTreeFinderTest], - classOf[HotCodeReplaceTest] + classOf[HotCodeReplaceTest], + classOf[ScalaApplicationLaunchConfigurationDelegateTest] )) class ScalaDebugTestSuite diff --git a/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/LaunchUtils.scala b/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/LaunchUtils.scala new file mode 100644 index 0000000000..68b2a3e9af --- /dev/null +++ b/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/LaunchUtils.scala @@ -0,0 +1,56 @@ +package org.scalaide.debug.internal.launching + +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +import org.eclipse.core.resources.IProject +import org.eclipse.core.resources.IncrementalProjectBuilder +import org.eclipse.core.runtime.NullProgressMonitor +import org.eclipse.debug.core.DebugPlugin +import org.eclipse.debug.core.ILaunch +import org.eclipse.debug.core.ILaunchConfiguration +import org.eclipse.debug.core.ILaunchesListener2 + +/** + * Used for launching application. + */ +trait LaunchUtils { + /** Points to launch configuration file. */ + val launchConfigurationName: String + + private val DefaultMonitor = new NullProgressMonitor + + /** Create a launch listener for launchTerminated events on a launch of the given launchConfiguration. */ + def onLaunchTerminates(f: () => Unit) = new ILaunchesListener2() { + override def launchesTerminated(launches: Array[ILaunch]): Unit = { + if (launches.exists(_.getLaunchConfiguration.getName == launchConfigurationName)) { + f() + } + } + override def launchesAdded(launches: Array[ILaunch]): Unit = {} + override def launchesRemoved(launches: Array[ILaunch]): Unit = {} + override def launchesChanged(launches: Array[ILaunch]): Unit = {} + } + + /** Cleans and incrementally builds projects */ + def cleanBuild(projects: IProject*): Unit = projects.foreach { project => + project.build(IncrementalProjectBuilder.CLEAN_BUILD, DefaultMonitor) + project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, DefaultMonitor) + } + + private def launchConfiguration(project: IProject): ILaunchConfiguration = + DebugPlugin.getDefault.getLaunchManager.getLaunchConfiguration(project.getFile(launchConfigurationName + ".launch")) + + def whenApplicationWasLaunchedFor(project: IProject, inMode: String)(then: => Unit): Unit = { + val latch = new CountDownLatch(1) + DebugPlugin.getDefault.getLaunchManager.addLaunchListener(onLaunchTerminates(latch.countDown)) + val lc = launchConfiguration(project) + val launch = lc.launch(inMode, DefaultMonitor) + val timeout = if (launch.canTerminate) 10 else 60 + latch.await(timeout, TimeUnit.SECONDS) + if (launch.canTerminate && !launch.isTerminated) { + throw new IllegalStateException(s"launch did not terminate in ${timeout}s") + } + then + } +} \ No newline at end of file diff --git a/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/LibraryJarInBootstrapTest.scala b/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/LibraryJarInBootstrapTest.scala index 26f2daab65..870a637716 100644 --- a/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/LibraryJarInBootstrapTest.scala +++ b/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/LibraryJarInBootstrapTest.scala @@ -26,14 +26,13 @@ import LibraryJarInBootstrapTest.project object LibraryJarInBootstrapTest extends TestProjectSetup("launching-1000919", bundleName = "org.scala-ide.sdt.debug.tests") -class LibraryJarInBootstrapTest { - +class LibraryJarInBootstrapTest extends LaunchUtils { import LibraryJarInBootstrapTest._ + override val launchConfigurationName = "t1000919.ScalaTest" @Before def initializeTests(): Unit = { - project.underlying.build(IncrementalProjectBuilder.CLEAN_BUILD, new NullProgressMonitor) - project.underlying.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, new NullProgressMonitor) + cleanBuild(project.underlying) } /** @@ -44,49 +43,21 @@ class LibraryJarInBootstrapTest { @Ignore(SdtTestConstants.TestRequiresGuiSupport) @Test def checkTestIsCorrectlyExecutedWhenLibraryJarAfterJRE(): Unit = { - - val launchConfigurationName = "t1000919.ScalaTest" - - val latch = new CountDownLatch(1) - - DebugPlugin.getDefault().getLaunchManager.addLaunchListener(onLaunchTerminates(launchConfigurationName, latch.countDown)) - - // launch the saved launch configuration - val launchConfiguration = DebugPlugin.getDefault.getLaunchManager.getLaunchConfiguration(file(launchConfigurationName + ".launch")) - val launch = launchConfiguration.launch(ILaunchManager.RUN_MODE, null) - - // wait for the launch to terminate - latch.await(10, TimeUnit.SECONDS) - assertTrue("launch did not terminate in 10s", launch.isTerminated) - - // check the result - // refresh the project to be able to see the new file - project.underlying.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor) - val resultFile = file("t1000919.result") - assertTrue("No result file, the launched test likely failed to run", resultFile.exists) - - // check the content - val source = Source.fromInputStream(resultFile.getContents)(Codec.UTF8) - try { - assertEquals("Wrong result file content", "t1000919 success", source.mkString) - } finally { - source.close - } - - } - - /** - * Create a launch listener for launchTerminated events on a launch of the given launchConfiguration. - */ - private def onLaunchTerminates(launchConfigurationName: String, f: () => Unit) = new ILaunchesListener2() { - override def launchesTerminated(launches: Array[ILaunch]): Unit = { - if (launches.exists(_.getLaunchConfiguration.getName == launchConfigurationName)) { - f() + whenApplicationWasLaunchedFor(project.underlying, inMode = ILaunchManager.RUN_MODE) { + // check the result + // refresh the project to be able to see the new file + project.underlying.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor) + val resultFile = file("t1000919.result") + assertTrue("No result file, the launched test likely failed to run", resultFile.exists) + + // check the content + val source = Source.fromInputStream(resultFile.getContents)(Codec.UTF8) + try { + assertEquals("Wrong result file content", "t1000919 success", source.mkString) + } finally { + source.close } } - override def launchesAdded(launches: Array[ILaunch]): Unit = {} - override def launchesRemoved(launches: Array[ILaunch]): Unit = {} - override def launchesChanged(launches: Array[ILaunch]): Unit = {} } } diff --git a/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/ScalaApplicationLaunchConfigurationDelegateTest.scala b/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/ScalaApplicationLaunchConfigurationDelegateTest.scala new file mode 100644 index 0000000000..685e84565b --- /dev/null +++ b/org.scala-ide.sdt.debug.tests/src/org/scalaide/debug/internal/launching/ScalaApplicationLaunchConfigurationDelegateTest.scala @@ -0,0 +1,54 @@ +package org.scalaide.debug.internal.launching + +import scala.io.Codec +import scala.io.Source +import scala.util.control.Exception.allCatch + +import org.eclipse.core.resources.IResource +import org.eclipse.core.runtime.NullProgressMonitor +import org.eclipse.debug.core.ILaunchManager +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.scalaide.core.testsetup.IProjectHelpers +import org.scalaide.core.testsetup.TestProjectSetup + +import ScalaApplicationLaunchConfigurationDelegateTest.file +import ScalaApplicationLaunchConfigurationDelegateTest.project + +object ScalaApplicationLaunchConfigurationDelegateTest + extends TestProjectSetup("launchDelegate", bundleName = "org.scala-ide.sdt.debug.tests") + +class ScalaApplicationLaunchConfigurationDelegateTest extends LaunchUtils with IProjectHelpers { + import ScalaApplicationLaunchConfigurationDelegateTest._ + override val launchConfigurationName = "launchDelegate" + + @Before def setup(): Unit = { + cleanBuild(project) + } + + @Test def shouldLaunchTestInRunMode(): Unit = { + whenApplicationWasLaunchedFor(project, ILaunchManager.RUN_MODE) { + assertSideEffect(ILaunchManager.RUN_MODE) + } + } + + @Test def shouldLaunchTestInDebugMode(): Unit = { + whenApplicationWasLaunchedFor(project, ILaunchManager.DEBUG_MODE) { + assertSideEffect(ILaunchManager.DEBUG_MODE) + } + } + + private def assertSideEffect(inMode: String) = { + project.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor) + val resultFile = file("launchDelegate.result") + if (resultFile.exists) { + val source = Source.fromInputStream(resultFile.getContents)(Codec.UTF8) + import scala.util.control.Exception._ + val actual = allCatch.andFinally(source.close) opt source.mkString + Assert.assertEquals("Wrong result file content", "success", actual.getOrElse("failure")) + } else { + Assert.fail(s"result file not found in mode '$inMode'") + } + } +} \ No newline at end of file diff --git a/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/.classpath b/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/.classpath new file mode 100644 index 0000000000..eb88dd1aa4 --- /dev/null +++ b/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/.project b/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/.project new file mode 100644 index 0000000000..1b82315c06 --- /dev/null +++ b/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/.project @@ -0,0 +1,18 @@ + + + launchDelegate + + + + + + org.scala-ide.sdt.core.scalabuilder + + + + + + org.scala-ide.sdt.core.scalanature + org.eclipse.jdt.core.javanature + + diff --git a/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/launchDelegate.launch b/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/launchDelegate.launch new file mode 100644 index 0000000000..e83d575011 --- /dev/null +++ b/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/launchDelegate.launch @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/src/test/ScalaTest.scala b/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/src/test/ScalaTest.scala new file mode 100644 index 0000000000..5c00259c38 --- /dev/null +++ b/org.scala-ide.sdt.debug.tests/test-workspace/launchDelegate/src/test/ScalaTest.scala @@ -0,0 +1,18 @@ +package test + +import org.junit.Test +import java.io.FileWriter + +object ScalaTest { + def main(args: Array[String]): Unit = { + (new ScalaTest).foo() + } +} + +class ScalaTest { + def foo(): Unit = { + val writer = new FileWriter("launchDelegate.result") + writer.write("success") + writer.close + } +} \ No newline at end of file diff --git a/org.scala-ide.sdt.debug/plugin.xml b/org.scala-ide.sdt.debug/plugin.xml index 020a3de758..9f1a8e0dff 100644 --- a/org.scala-ide.sdt.debug/plugin.xml +++ b/org.scala-ide.sdt.debug/plugin.xml @@ -28,7 +28,7 @@ delegate="org.scalaide.debug.internal.launching.ScalaApplicationLaunchConfigurationDelegate" delegateDescription="The Scala JVM Launcher supports debugging of local Scala using the new Scala debugger" id="scala.application.new" - modes="debug" + modes="debug, run" name="Scala Application (new debugger)" sourceLocatorId="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector" sourcePathComputerId="org.eclipse.jdt.launching.sourceLookup.javaSourcePathComputer" diff --git a/org.scala-ide.sdt.debug/src/org/scalaide/debug/internal/launching/ScalaApplicationLaunchConfigurationDelegate.scala b/org.scala-ide.sdt.debug/src/org/scalaide/debug/internal/launching/ScalaApplicationLaunchConfigurationDelegate.scala index c6d48c845f..ee030f3828 100644 --- a/org.scala-ide.sdt.debug/src/org/scalaide/debug/internal/launching/ScalaApplicationLaunchConfigurationDelegate.scala +++ b/org.scala-ide.sdt.debug/src/org/scalaide/debug/internal/launching/ScalaApplicationLaunchConfigurationDelegate.scala @@ -1,6 +1,7 @@ package org.scalaide.debug.internal.launching import org.eclipse.debug.core.ILaunchConfiguration +import org.eclipse.debug.core.ILaunchManager import org.eclipse.jdt.launching.IVMRunner import org.scalaide.core.internal.launching.ScalaLaunchDelegate @@ -10,8 +11,12 @@ import org.scalaide.core.internal.launching.ScalaLaunchDelegate class ScalaApplicationLaunchConfigurationDelegate extends ScalaLaunchDelegate { override def getVMRunner(configuration: ILaunchConfiguration, mode: String): IVMRunner = { - val vm = verifyVMInstall(configuration) - new StandardVMScalaDebugger(vm) + if (ILaunchManager.DEBUG_MODE == mode) { + val vm = verifyVMInstall(configuration) + new StandardVMScalaDebugger(vm) + } else { + super.getVMRunner(configuration, mode) + } } } \ No newline at end of file