Skip to content

Fix #1965: add proper testing infrastructure for reporting tests #1966

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/DottyTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import dotc.Compiler

import dotc.core.Phases.Phase

class DottyTest extends ContextEscapeDetection{
trait DottyTest extends ContextEscapeDetection {

dotc.parsing.Scanners // initialize keywords

Expand Down
4 changes: 2 additions & 2 deletions compiler/test/dotty/tools/DottyTypeStealer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import dotc.core.Contexts.Context
import dotc.core.Decorators._
import dotc.core.Types.Type

object DottyTypeStealer {
object DottyTypeStealer extends DottyTest {
def stealType(source: String, typeStrings: String*): (Context, List[Type]) = {
val dummyName = "x_x_x"
val vals = typeStrings.zipWithIndex.map{case (s, x)=> s"val ${dummyName}$x: $s = ???"}.mkString("\n")
val gatheredSource = s" ${source}\n object A$dummyName {$vals}"
var scontext : Context = null
var tp: List[Type] = null
new DottyTest().checkCompile("frontend",gatheredSource) {
checkCompile("frontend",gatheredSource) {
(tree, context) =>
implicit val ctx = context
val findValDef: (List[ValDef], tpd.Tree) => List[ValDef] =
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/dotc/parsing/DocstringTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ trait DocstringTest extends DottyTest {

def checkFrontend(source: String)(docAssert: PartialFunction[Tree[Untyped], Unit]) = {
checkCompile("frontend", source) { (_, ctx) =>
implicit val c = ctx
implicit val c: Context = ctx
(docAssert orElse defaultAssertion)(ctx.compilationUnit.untpdTree)
}
}
Expand Down
72 changes: 72 additions & 0 deletions compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package dotty.tools
package dotc
package reporting

import diagnostic._
import core.Contexts.Context

import scala.collection.mutable

import org.junit.Assert._

trait ErrorMessagesTest extends DottyTest {

ctx = freshReporter(ctx)

private def freshReporter(ctx: Context) =
ctx.fresh.setReporter(new CapturingReporter)


class Report(messages: List[Message], ictx: Context) {
def expect(f: (Context, List[Message]) => Unit): Unit = {
f(ictx, messages)
}

def expectNoErrors: Unit =
assert(this.isInstanceOf[EmptyReport], "errors found when not expected")
}

class EmptyReport extends Report(Nil, null) {
override def expect(f: (Context, List[Message]) => Unit) =
fail("""|
|Couldn't capture errors from compiled sources, this can happen if
|there are no errors or the compiler crashes.""".stripMargin)
}

class CapturingReporter extends Reporter
with UniqueMessagePositions with HideNonSensicalMessages {
private[this] val buffer = new mutable.ListBuffer[Message]
private[this] var capturedContext: Context = _

def doReport(m: MessageContainer)(implicit ctx: Context) = {
capturedContext = ctx
buffer append m.contained
}

def toReport: Report =
if (capturedContext eq null)
new EmptyReport
else {
val xs = buffer.reverse.toList
buffer.clear()

val ctx = capturedContext
capturedContext = null

new Report(xs, ctx)
}
}

def checkMessages(source: String): Report = {
checkCompile("frontend", source) { (_,ictx) => () }
val rep = ctx.reporter.asInstanceOf[CapturingReporter].toReport
ctx = freshReporter(ctx)
rep
}

def assertMessageCount(expected: Int, messages: List[Message]): Unit =
assertEquals(
expected,
messages.length
)
}
45 changes: 45 additions & 0 deletions compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dotty.tools
package dotc
package reporting

import core.Contexts.Context
import diagnostic.messages._

import org.junit.Assert._
import org.junit.Test

class ErrorMessagesTests extends ErrorMessagesTest {
// In the case where there are no errors, we can do "expectNoErrors" in the
// `Report`
@Test def noErrors =
checkMessages("""class Foo""")
.expectNoErrors

@Test def typeMismatch =
checkMessages {
"""
|object Foo {
| def bar: String = 1
|}
""".stripMargin
}
.expect { (ictx, messages) =>
implicit val ctx: Context = ictx
val defn = ictx.definitions

// Assert that we only got one error message
assertMessageCount(1, messages)

// Pattern match out the expected error
val TypeMismatch(found, expected, _, _) :: Nil = messages

// The type of the right hand side will actually be the constant 1,
// therefore we check if it "derivesFrom" `IntClass`
assert(found.derivesFrom(defn.IntClass), s"found was: $found")

// The expected type is `scala.String` which we dealias to
// `java.lang.String` and compare with `=:=` to `defn.StringType` which
// is a type reference to `java.lang.String`
assert(expected.dealias =:= defn.StringType, s"expected was: $expected")
}
}