Skip to content

Commit 9cd51b9

Browse files
wip neg tests
1 parent 5160d34 commit 9cd51b9

File tree

1 file changed

+43
-132
lines changed

1 file changed

+43
-132
lines changed

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

Lines changed: 43 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
181181
}
182182

183183
private trait CompilationLogic { this: Test =>
184-
def compileTestSource(testSource: TestSource): List[TestReporter] =
184+
final def compileTestSource(testSource: TestSource): List[TestReporter] =
185185
testSource match {
186186
case testSource @ JointCompilationSource(name, files, flags, outDir, fromTasty, decompilation) =>
187187
val reporter =
@@ -193,27 +193,36 @@ trait ParallelTesting extends RunnerOrchestration { self =>
193193
testSource.compilationGroups.map(files => compile(files, flags, false, outDir)) // TODO? only `compile` option?
194194
}
195195

196-
def onSuccess(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable): Unit = ()
197-
def onFailure(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable): Unit = {
198-
echo(s" Compilation failed for: '${testSource.title}' ")
199-
reporters.filter(reporterFailed).foreach(logger.logReporterContents)
200-
logBuildInstructions(testSource, reporters)
201-
}
202-
203-
def countErrorsAndWarnings(reporters: Seq[TestReporter]): (Int, Int) =
196+
final def countErrorsAndWarnings(reporters: Seq[TestReporter]): (Int, Int) =
204197
reporters.foldLeft((0, 0)) { case ((err, warn), r) => (err + r.errorCount, warn + r.warningCount) }
205198

206-
def countErrors (reporters: Seq[TestReporter]) = countErrorsAndWarnings(reporters)._1
207-
def countWarnings(reporters: Seq[TestReporter]) = countErrorsAndWarnings(reporters)._2
208-
def reporterFailed(r: TestReporter) = r.compilerCrashed || r.errorCount > 0
199+
final def countErrors (reporters: Seq[TestReporter]) = countErrorsAndWarnings(reporters)._1
200+
final def countWarnings(reporters: Seq[TestReporter]) = countErrorsAndWarnings(reporters)._2
201+
final def reporterFailed(r: TestReporter) = r.compilerCrashed || r.errorCount > 0
209202

210-
protected def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable { self =>
203+
final def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable { self =>
211204
def checkTestSource(): Unit = tryCompile(testSource) {
212205
val reporters = compileTestSource(testSource)
213-
if (!reporters.exists(reporterFailed)) onSuccess(testSource, reporters, self)
214-
else onFailure(testSource, reporters, self)
206+
onComplete(testSource, reporters, self)
207+
registerCompletion()
215208
}
216209
}
210+
211+
final def onComplete(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable): Unit =
212+
testFailed(testSource, reporters).fold(
213+
onSuccess(testSource, reporters, logger )
214+
, msg => onFailure(testSource, reporters, logger, Option(msg).filter(_.nonEmpty)) )
215+
216+
def testFailed(testSource: TestSource, reporters: Seq[TestReporter]): Option[String] =
217+
Option(reporters.exists(reporterFailed)).map(_ => s"Compilation failed for: '${testSource.title}'")
218+
219+
def onSuccess(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable): Unit = ()
220+
def onFailure(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable, message: Option[String]): Unit = {
221+
message.foreach(echo)
222+
reporters.filter(reporterFailed).foreach(logger.logReporterContents)
223+
logBuildInstructions(testSource, reporters)
224+
failTestSource(testSource)
225+
}
217226
}
218227

219228
/** Each `Test` takes the `testSources` and performs the compilation and assertions
@@ -296,7 +305,6 @@ trait ParallelTesting extends RunnerOrchestration { self =>
296305
val (errCount, warnCount) = countErrorsAndWarnings(reporters)
297306
val errorMsg = testSource.buildInstructions(errCount, warnCount)
298307
addFailureInstruction(errorMsg)
299-
failTestSource(testSource)
300308
}
301309
protected def logBuildInstructions(reporter: TestReporter, testSource: TestSource, err: Int, war: Int) = {
302310
val errorMsg = testSource.buildInstructions(reporter.errorCount, reporter.warningCount)
@@ -645,126 +653,29 @@ trait ParallelTesting extends RunnerOrchestration { self =>
645653

646654
private final class NegTest(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean)(implicit summaryReport: SummaryReporting)
647655
extends Test(testSources, times, threadLimit, suppressAllOutput) {
648-
override protected def encapsulatedCompilation(testSource: TestSource) = new LoggedRunnable {
649-
def checkTestSource(): Unit = tryCompile(testSource) {
650-
// In neg-tests we allow two types of error annotations,
651-
// "nopos-error" which doesn't care about position and "error" which
652-
// has to be annotated on the correct line number.
653-
//
654-
// We collect these in a map `"file:row" -> numberOfErrors`, for
655-
// nopos errors we save them in `"file" -> numberOfNoPosErrors`
656-
def getErrorMapAndExpectedCount(files: Array[JFile]): (HashMap[String, Integer], Int) = {
657-
val errorMap = new HashMap[String, Integer]()
658-
var expectedErrors = 0
659-
files.filter(_.getName.endsWith(".scala")).foreach { file =>
660-
Source.fromFile(file, "UTF-8").getLines().zipWithIndex.foreach { case (line, lineNbr) =>
661-
val errors = line.sliding("// error".length).count(_.mkString == "// error")
662-
if (errors > 0)
663-
errorMap.put(s"${file.getAbsolutePath}:${lineNbr}", errors)
664-
665-
val noposErrors = line.sliding("// nopos-error".length).count(_.mkString == "// nopos-error")
666-
if (noposErrors > 0) {
667-
val nopos = errorMap.get("nopos")
668-
val existing: Integer = if (nopos eq null) 0 else nopos
669-
errorMap.put("nopos", noposErrors + existing)
670-
}
671-
672-
expectedErrors += noposErrors + errors
673-
}
674-
}
675-
676-
(errorMap, expectedErrors)
677-
}
678-
679-
def getMissingExpectedErrors(errorMap: HashMap[String, Integer], reporterErrors: Iterator[MessageContainer]) = !reporterErrors.forall { error =>
680-
val key = if (error.pos.exists) {
681-
val fileName = error.pos.source.file.toString
682-
s"$fileName:${error.pos.line}"
683-
684-
} else "nopos"
685-
686-
val errors = errorMap.get(key)
687-
688-
if (errors ne null) {
689-
if (errors == 1) errorMap.remove(key)
690-
else errorMap.put(key, errors - 1)
691-
true
692-
}
693-
else {
694-
echo(s"Error reported in ${error.pos.source}, but no annotation found")
695-
false
696-
}
697-
}
698-
699-
def fail(msg: String): Unit = {
700-
echo(msg)
701-
failTestSource(testSource)
702-
}
703-
704-
def reporterOutputLines(reporters: List[TestReporter]): List[String] = {
705-
reporters.flatMap(_.allErrors).sortBy(_.pos.source.toString).flatMap { error =>
706-
(error.pos.span.toString + " in " + error.pos.source.file.name) :: error.getMessage().linesIterator.toList
707-
}
708-
}
709-
def checkFileTest(sourceName: String, checkFile: JFile, actual: List[String]) = {
710-
val expexted = Source.fromFile(checkFile, "UTF-8").getLines().toList
711-
for (msg <- diffMessage(sourceName, actual, expexted)) {
712-
fail(msg)
713-
dumpOutputToFile(checkFile, actual)
714-
}
715-
}
716-
717-
val (compilerCrashed, expectedErrors, actualErrors, hasMissingAnnotations, errorMap) = testSource match {
718-
case testSource @ JointCompilationSource(_, files, flags, outDir, fromTasty, decompilation) =>
719-
val sourceFiles = testSource.sourceFiles
720-
val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(sourceFiles)
721-
val reporter = compile(sourceFiles, flags, true, outDir)
722-
val actualErrors = reporter.errorCount
723-
files.foreach { file =>
724-
if (!file.isDirectory) {
725-
val checkFile = new JFile(file.getAbsolutePath.replaceFirst("\\.scala$", ".check"))
726-
if (checkFile.exists)
727-
checkFileTest(testSource.title, checkFile, reporterOutputLines(reporter :: Nil))
728-
}
729-
}
730-
if (reporter.compilerCrashed || actualErrors > 0)
731-
logReporterContents(reporter)
732-
733-
(reporter.compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, reporter.errors), errorMap)
734-
735-
case testSource @ SeparateCompilationSource(_, dir, flags, outDir) => {
736-
val compilationGroups = testSource.compilationGroups
737-
val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(compilationGroups.toArray.flatten)
738-
val reporters = compilationGroups.map(compile(_, flags, true, outDir))
739-
val compilerCrashed = reporters.exists(_.compilerCrashed)
740-
val actualErrors = reporters.foldLeft(0)(_ + _.errorCount)
741-
val errors = reporters.iterator.flatMap(_.errors)
742-
743-
if (actualErrors > 0)
744-
reporters.foreach(logReporterContents)
656+
override def testFailed(reporters: Seq[TestReporter]): Option[() => Unit] = {
657+
val compilerCrashed = reporters.exists(_.compilerCrashed)
658+
val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(testSource.sourceFiles)
659+
val actualErrors = reporters.foldLeft(0)(_ + _.errorCount)
660+
661+
if (compilerCrashed ) Some(s"Compiler crashed when compiling: ${testSource.title}" )
662+
else if (actualErrors == 0 ) Some(s"\nNo errors found when compiling neg test $testSource" )
663+
else if (expectedErrors != actualErrors) Some(s"\nWrong number of errors encountered when compiling $testSource, expected: $expectedErrors, actual: $actualErrors")
664+
else if (hasMissingAnnotations() ) Some(s"\nErrors found on incorrect row numbers when compiling $testSource" )
665+
else if (!errorMap.isEmpty ) Some(s"\nExpected error(s) have {<error position>=<unreported error>}: $errorMap" )
666+
else None
667+
}
745668

746-
val checkFile = new JFile(dir.getAbsolutePath + ".check")
747-
if (checkFile.exists)
748-
checkFileTest(testSource.title, checkFile, reporterOutputLines(reporters))
749-
750-
(compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, errors), errorMap)
751-
}
752-
}
669+
def files: List[JFile] = testSource match {
670+
case ts: JointCompilationSource =>
671+
files.filter(f => !f.isDirectory).map { f =>
672+
new JFile(f.getAbsolutePath.replaceFirst("\\.scala$", ".check")) }
753673

674+
case ts: SeparateCompilationSource =>
675+
}
754676

755-
if (compilerCrashed)
756-
fail(s"Compiler crashed when compiling: ${testSource.title}")
757-
else if (actualErrors == 0)
758-
fail(s"\nNo errors found when compiling neg test $testSource")
759-
else if (expectedErrors != actualErrors)
760-
fail(s"\nWrong number of errors encountered when compiling $testSource, expected: $expectedErrors, actual: $actualErrors")
761-
else if (hasMissingAnnotations())
762-
fail(s"\nErrors found on incorrect row numbers when compiling $testSource")
763-
else if (!errorMap.isEmpty)
764-
fail(s"\nExpected error(s) have {<error position>=<unreported error>}: $errorMap")
677+
override def onSuccess(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable): Unit = {
765678

766-
registerCompletion()
767-
}
768679
}
769680
}
770681

0 commit comments

Comments
 (0)