Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1943: Support JUnit's @Ignore on test class #1961

3 changes: 3 additions & 0 deletions build.sbt
Expand Up @@ -582,6 +582,7 @@ lazy val tests =
)
.settings(noPublishSettings)
.settings(
nativeConfig ~= (_.withMode(scalanative.build.Mode.releaseFast)),
WojciechMazur marked this conversation as resolved.
Show resolved Hide resolved
// nativeOptimizerReporter := OptimizerReporter.toDirectory(
// crossTarget.value),
// nativeLinkerReporter := LinkerReporter.toFile(
Expand Down Expand Up @@ -616,6 +617,8 @@ lazy val sandbox =
.settings(scalacOptions -= "-Xfatal-warnings")
.settings(noPublishSettings)
.settings(
nativeConfig ~= (_.withMode(scalanative.build.Mode.releaseFast))
WojciechMazur marked this conversation as resolved.
Show resolved Hide resolved

// nativeOptimizerReporter := OptimizerReporter.toDirectory(
// crossTarget.value),
)
Expand Down
Expand Up @@ -53,13 +53,14 @@ class ScalaNativeJUnitPlugin(val global: Global) extends NscPlugin {
}

private object Names {
val beforeClass: TermName = newTermName("beforeClass")
val afterClass: TermName = newTermName("afterClass")
val before: TermName = newTermName("before")
val after: TermName = newTermName("after")
val tests: TermName = newTermName("tests")
val invokeTest: TermName = newTermName("invokeTest")
val newInstance: TermName = newTermName("newInstance")
val beforeClass: TermName = newTermName("beforeClass")
val afterClass: TermName = newTermName("afterClass")
val before: TermName = newTermName("before")
val after: TermName = newTermName("after")
val testMetadata: TermName = newTermName("testMetadata")
val tests: TermName = newTermName("tests")
val invokeTest: TermName = newTermName("invokeTest")
val newInstance: TermName = newTermName("newInstance")

val instance: TermName = newTermName("instance")
val name: TermName = newTermName("name")
Expand All @@ -68,6 +69,9 @@ class ScalaNativeJUnitPlugin(val global: Global) extends NscPlugin {
private lazy val BootstrapperClass =
getRequiredClass("scala.scalanative.junit.Bootstrapper")

private lazy val TestClassMetadataClass =
getRequiredClass("scala.scalanative.junit.TestClassMetadata")

private lazy val TestMetadataClass =
getRequiredClass("scala.scalanative.junit.TestMetadata")

Expand Down Expand Up @@ -140,6 +144,7 @@ class ScalaNativeJUnitPlugin(val global: Global) extends NscPlugin {
JUnitAnnots.AfterClass),
genCallOnParam(bootSym, Names.before, testClass, JUnitAnnots.Before),
genCallOnParam(bootSym, Names.after, testClass, JUnitAnnots.After),
genTestMetadata(bootSym, testClass),
genTests(bootSym, testMethods),
genInvokeTest(bootSym, testClass, testMethods),
genNewInstance(bootSym, testClass)
Expand Down Expand Up @@ -197,8 +202,25 @@ class ScalaNativeJUnitPlugin(val global: Global) extends NscPlugin {
typer.typedDefDef(newDefDef(sym, Block(calls: _*))())
}

private def genTestMetadata(owner: ClassSymbol,
testClass: ClassSymbol): DefDef = {
val sym = owner.newMethodSymbol(Names.testMetadata)

sym.setInfoAndEnter(
MethodType(Nil, typeRef(NoType, TestClassMetadataClass, Nil))
)

val ignored = testClass.hasAnnotation(JUnitAnnots.Ignore)
val isIgnored = Literal(Constant(ignored))

val rhs = New(TestClassMetadataClass, isIgnored)

typer.typedDefDef(newDefDef(sym, rhs)())
}

private def genTests(owner: ClassSymbol, tests: Scope): DefDef = {
val sym = owner.newMethodSymbol(Names.tests)

sym.setInfoAndEnter(
MethodType(Nil,
typeRef(NoType, ArrayClass, List(TestMetadataClass.tpe))))
Expand All @@ -209,10 +231,11 @@ class ScalaNativeJUnitPlugin(val global: Global) extends NscPlugin {
test.getAnnotation(JUnitAnnots.Test).get.args: _*)

val name = Literal(Constant(test.name.toString))
val ignored = Literal(
Constant(test.hasAnnotation(JUnitAnnots.Ignore)))

New(TestMetadataClass, name, ignored, reifiedAnnot)
val testIgnored = test.hasAnnotation(JUnitAnnots.Ignore)
val isIgnored = Literal(Constant(testIgnored))

New(TestMetadataClass, name, isIgnored, reifiedAnnot)
}

val rhs = ArrayValue(TypeTree(TestMetadataClass.tpe), metadata.toList)
Expand Down
Expand Up @@ -21,6 +21,7 @@ trait Bootstrapper {
def before(instance: AnyRef): Unit
def after(instance: AnyRef): Unit

def testMetadata(): TestClassMetadata
WojciechMazur marked this conversation as resolved.
Show resolved Hide resolved
def tests(): Array[TestMetadata]
def invokeTest(instance: AnyRef, name: String): Future[Try[Unit]]

Expand All @@ -39,3 +40,14 @@ final class TestMetadata(
val ignored: Boolean,
val annotation: org.junit.Test
)

/** Scala Native interal JUnit test class metadata
*
* This class is public due to implementation details. Only the junit compiler
* plugin may create instances of it.
*
* Relying on this class directly is unspecified behavior.
* */
WojciechMazur marked this conversation as resolved.
Show resolved Hide resolved
final class TestClassMetadata(
val ignored: Boolean
)
Expand Up @@ -33,29 +33,36 @@ private[junit] final class JUnitTask(val taskDef: TaskDef,
var total = 0

@tailrec
def runTests(tests: List[TestMetadata]): Try[Unit] = {
def runTests(tests: List[TestMetadata],
testClass: TestClassMetadata): Try[Unit] = {
val (nextIgnored, other) = tests.span(_.ignored)

nextIgnored.foreach(t => reporter.reportIgnored(Some(t.name)))
ignored += nextIgnored.size
if (testClass.ignored) {
reporter.reportIgnored(None)
ignored += 1
Success(())
} else {
nextIgnored.foreach(t => reporter.reportIgnored(Some(t.name)))
ignored += nextIgnored.size

other match {
case t :: ts =>
total += 1
other match {
case t :: ts =>
total += 1

val fc = executeTestMethod(bootstrapper, t, reporter)
failed += fc
runTests(ts)
val fc = executeTestMethod(bootstrapper, t, reporter)
failed += fc
runTests(ts, testClass)

case Nil =>
Success(())
case Nil =>
Success(())
}
}
}

val result = runTestLifecycle {
Success(())
} { _ => catchAll(bootstrapper.beforeClass()) } { _ =>
runTests(bootstrapper.tests().toList)
runTests(bootstrapper.tests().toList, bootstrapper.testMetadata())
} { _ => catchAll(bootstrapper.afterClass()) }

val (errors, timeInSeconds) = result
Expand Down
@@ -0,0 +1,5 @@
ldTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
ldTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
ldTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
ldTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
ldTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
ldTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
ldTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
ldTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTest ignored
e3scala.scalanative.junit.IgnoreAllTest
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
ldTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
ldTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
ldTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
ldTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
ldTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
ldTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
ldTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
ldTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,5 @@
liTest run started
liTest scala.scalanative.junit.IgnoreAllTestWithReason ignored
e3scala.scalanative.junit.IgnoreAllTestWithReason
liTest run finished: 0 failed, 1 ignored, 0 total, <TIME>
d
@@ -0,0 +1,16 @@
package scala.scalanative.junit

import org.junit._

import scala.scalanative.junit.utils.JUnitTest

@Ignore
class IgnoreAllTest {
WojciechMazur marked this conversation as resolved.
Show resolved Hide resolved
throw new Error("unreachable")

@Test def multiTest1(): Unit = ()
@Test def multiTest2(): Unit = ()
@Test def multiTest3(): Unit = ()
}

class IgnoreAllTestAssertions extends JUnitTest
@@ -0,0 +1,16 @@
package scala.scalanative.junit

import org.junit._
import scala.scalanative.junit.utils.JUnitTest

@Ignore("ignore reason")
class IgnoreAllTestWithReason {
@Ignore("reason override") @Test def multiTest1(): Unit = ()
@Ignore @Test def multiTest2(): Unit = ()
@Test def multiTest3(): Unit = ()

throw new Error("unreachable")

}

class IgnoreAllTestWithReasonAssertions extends JUnitTest
Expand Up @@ -8,7 +8,7 @@ import org.junit.Ignore
import org.junit.Test
import org.junit.Assert._

@Ignore("tests disabled but ignore on class doesn't work")
@Ignore
class AtomicReferenceTest {

// This test suite is INCOMPLETE (obviously!).
Expand All @@ -21,7 +21,6 @@ class AtomicReferenceTest {
// how to test concurrent and contended access patterns within
// the scope of unit-tests.

@Ignore
@Test def get(): Unit = {

val expected = -1
Expand All @@ -33,7 +32,6 @@ class AtomicReferenceTest {
result == expected)
}

@Ignore
@Test def getAndUpdateUpdateFunction(): Unit = {

val expectedValue = 100
Expand All @@ -58,7 +56,6 @@ class AtomicReferenceTest {
newValue == expectedNewValue)
}

@Ignore
@Test def updateAndGetUpdateFunction(): Unit = {

val initialValue = 100
Expand Down