Skip to content

Commit

Permalink
Cannot use scala evaluator with scalatest
Browse files Browse the repository at this point in the history
Scalatest launcher extends standard java launcher both in 'run'
and 'debug' modes. Unfortunately ScalaApplicationLaunchConfigDelegate'
can be used in 'debug' mode only. So there is a need to expose it
for 'run' mode as well. And it allows for extension of this launcher
by other launcher including Scalatest one.

Fix #1002447
  • Loading branch information
wpopielarski committed Jun 2, 2015
1 parent e773514 commit 14c5562
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 49 deletions.
Expand Up @@ -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.
Expand All @@ -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
@@ -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
}
}
Expand Up @@ -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)
}

/**
Expand All @@ -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 = {}
}

}
@@ -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'")
}
}
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>launchDelegate</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.scala-ide.sdt.core.scalabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.scala-ide.sdt.core.scalanature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="scala.application">
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/launchDelegate/src/test/ScalaTest.scala"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<mapAttribute key="org.eclipse.debug.core.preferred_launchers">
<mapEntry key="[debug]" value="scala.application.new"/>
<mapEntry key="[run]" value="scala.application.new"/>
</mapAttribute>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="test.ScalaTest"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="launchDelegate"/>
</launchConfiguration>
@@ -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
}
}
2 changes: 1 addition & 1 deletion org.scala-ide.sdt.debug/plugin.xml
Expand Up @@ -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"
Expand Down
@@ -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

Expand All @@ -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)
}
}

}

0 comments on commit 14c5562

Please sign in to comment.