-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
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 { | ||
|
||
class Report(messages: List[Message], ictx: Context) { | ||
def expect(f: (Context, List[Message]) => Unit): Unit = { | ||
f(ictx, messages) | ||
} | ||
|
||
def expectNoErrors: Unit = this.isInstanceOf[FailedReport] | ||
} | ||
|
||
class FailedReport 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 FailedReport | ||
else { | ||
val xs = buffer.reverse.toList | ||
buffer.clear() | ||
|
||
val ctx = capturedContext | ||
capturedContext = null | ||
|
||
new Report(xs, ctx) | ||
} | ||
} | ||
|
||
ctx = freshReporter(ctx) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would move the mutation stuff at the very top of the trait. BTW could you make it a class instead? (it feels wrong to have class → trait → class inheritance) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe |
||
|
||
private def freshReporter(ctx: Context) = | ||
ctx.fresh.setReporter(new CapturingReporter) | ||
|
||
def checkMessages(source: String): Report = { | ||
checkCompile("frontend", source) { (_,ictx) => () } | ||
val rep = ctx.reporter.asInstanceOf[CapturingReporter].toReport | ||
ctx = freshReporter(ctx) | ||
rep | ||
} | ||
|
||
def messageCount(expected: Int, messages: List[Message]): Unit = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
assertEquals( | ||
expected, | ||
messages.length | ||
) | ||
} |
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 | ||
messageCount(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") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean
asInstanceOf
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, but I should probably rename
FailedReport
=>EmptyReport
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then I don't understand the statement, this computes a
Boolean
and converts it toUnit
regardless of it's value?