@@ -6,22 +6,21 @@ import java.io.{ File => JFile }
66import java .text .SimpleDateFormat
77import java .util .HashMap
88import java .nio .file .StandardCopyOption .REPLACE_EXISTING
9- import java .nio .file .{ Files , Path , Paths , NoSuchFileException }
10- import java .util .concurrent .{ Executors => JExecutors , TimeUnit , TimeoutException }
9+ import java .nio .file .{ Files , NoSuchFileException , Path , Paths }
10+ import java .util .concurrent .{ TimeUnit , TimeoutException , Executors => JExecutors }
1111
1212import scala .io .Source
1313import scala .util .control .NonFatal
1414import scala .util .Try
1515import scala .collection .mutable
1616import scala .util .matching .Regex
1717import scala .util .Random
18-
1918import dotc .core .Contexts ._
20- import dotc .reporting .{ Reporter , TestReporter }
19+ import dotc .reporting .{ Reporter , StoredTestReporter , TestReporter }
2120import dotc .reporting .diagnostic .MessageContainer
2221import dotc .interfaces .Diagnostic .ERROR
2322import dotc .util .DiffUtil
24- import dotc .{ Driver , Compiler }
23+ import dotc .{ Compiler , Driver }
2524
2625/** A parallel testing suite whose goal is to integrate nicely with JUnit
2726 *
@@ -47,7 +46,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
4746 /** A test source whose files or directory of files is to be compiled
4847 * in a specific way defined by the `Test`
4948 */
50- private sealed trait TestSource { self =>
49+ sealed trait TestSource { self =>
5150 def name : String
5251 def outDir : JFile
5352 def flags : TestFlags
@@ -128,7 +127,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
128127 /** A group of files that may all be compiled together, with the same flags
129128 * and output directory
130129 */
131- private final case class JointCompilationSource (
130+ final case class JointCompilationSource (
132131 name : String ,
133132 files : Array [JFile ],
134133 flags : TestFlags ,
@@ -142,7 +141,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
142141 /** A test source whose files will be compiled separately according to their
143142 * suffix `_X`
144143 */
145- private final case class SeparateCompilationSource (
144+ final case class SeparateCompilationSource (
146145 name : String ,
147146 dir : JFile ,
148147 flags : TestFlags ,
@@ -175,7 +174,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
175174 /** Each `Test` takes the `testSources` and performs the compilation and assertions
176175 * according to the implementing class "neg", "run" or "pos".
177176 */
178- private abstract class Test (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )(implicit val summaryReport : SummaryReporting ) { test =>
177+ private abstract class Test (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean , checkCompileOutput : Boolean = false )(implicit val summaryReport : SummaryReporting ) { test =>
179178
180179 import summaryReport ._
181180
@@ -360,9 +359,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
360359 else None
361360 } else None
362361
362+ val logLevel = if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR
363363 val reporter =
364- TestReporter .reporter(realStdout, logLevel =
365- if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR )
364+ if (checkCompileOutput)
365+ TestReporter .storedReporter(realStdout, logLevel = logLevel)
366+ else
367+ TestReporter .reporter(realStdout, logLevel = logLevel)
366368
367369 val driver =
368370 if (times == 1 ) new Driver
@@ -440,10 +442,28 @@ trait ParallelTesting extends RunnerOrchestration { self =>
440442
441443 this
442444 }
445+
446+ protected def verifyCompileOutput (source : TestSource , checkFile : JFile , reporter : StoredTestReporter ): Unit = {
447+ reporter.writer.flush()
448+ val checkLines = Source .fromFile(checkFile).getLines().mkString(" \n " )
449+ val outputLines = reporter.writer.toString.trim.replaceAll(" \\ s+\n " , " \n " )
450+
451+ if (outputLines != checkLines) {
452+ val msg = s " Output from ' ${source.title}' did not match check file ' ${checkFile.getName}'. "
453+ println(" ===============================" )
454+ println(" expected: \n " + checkLines)
455+ println(" actual: \n " + outputLines)
456+ println(" ===============================" )
457+
458+ echo(msg)
459+ addFailureInstruction(msg)
460+ failTestSource(source)
461+ }
462+ }
443463 }
444464
445- private final class PosTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )(implicit summaryReport : SummaryReporting )
446- extends Test (testSources, times, threadLimit, suppressAllOutput) {
465+ private final class PosTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean , checkCompileOutput : Boolean = false )(implicit summaryReport : SummaryReporting )
466+ extends Test (testSources, times, threadLimit, suppressAllOutput, checkCompileOutput ) {
447467 protected def encapsulatedCompilation (testSource : TestSource ) = new LoggedRunnable {
448468 def checkTestSource (): Unit = tryCompile(testSource) {
449469 testSource match {
@@ -475,6 +495,14 @@ trait ParallelTesting extends RunnerOrchestration { self =>
475495 reporters.foreach(logReporterContents)
476496 logBuildInstructions(reporters.head, testSource, errorCount, warningCount)
477497 }
498+
499+ // verify compilation check file
500+ (1 to testSource.compilationGroups.length).foreach { index =>
501+ val checkFile = new JFile (dir.getAbsolutePath.reverse.dropWhile(_ == '/' ).reverse + " /" + index + " .check" )
502+
503+ if (checkFile.exists && checkCompileOutput)
504+ verifyCompileOutput(testSource, checkFile, reporters(index).asInstanceOf [StoredTestReporter ])
505+ }
478506 }
479507 }
480508 }
@@ -599,8 +627,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
599627 }
600628 }
601629
602- private final class NegTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )(implicit summaryReport : SummaryReporting )
603- extends Test (testSources, times, threadLimit, suppressAllOutput) {
630+ private final class NegTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean , checkCompileOutput : Boolean = false )(implicit summaryReport : SummaryReporting )
631+ extends Test (testSources, times, threadLimit, suppressAllOutput, checkCompileOutput ) {
604632 protected def encapsulatedCompilation (testSource : TestSource ) = new LoggedRunnable {
605633 def checkTestSource (): Unit = tryCompile(testSource) {
606634 // In neg-tests we allow two types of error annotations,
@@ -678,6 +706,14 @@ trait ParallelTesting extends RunnerOrchestration { self =>
678706 if (actualErrors > 0 )
679707 reporters.foreach(logReporterContents)
680708
709+ // Compilation check file: for testing plugins
710+ (1 to testSource.compilationGroups.length).foreach { index =>
711+ val checkFile = new JFile (dir.getAbsolutePath.reverse.dropWhile(_ == '/' ).reverse + " /" + index + " .check" )
712+
713+ if (checkFile.exists && checkCompileOutput)
714+ verifyCompileOutput(testSource, checkFile, reporters(index).asInstanceOf [StoredTestReporter ])
715+ }
716+
681717 (compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, errors), errorMap)
682718 }
683719 }
@@ -825,10 +861,10 @@ trait ParallelTesting extends RunnerOrchestration { self =>
825861 ) {
826862 import org .junit .Assert .fail
827863
828- private [ ParallelTesting ] def this (target : TestSource ) =
864+ def this (target : TestSource ) =
829865 this (List (target), 1 , true , None , false , false )
830866
831- private [ ParallelTesting ] def this (targets : List [TestSource ]) =
867+ def this (targets : List [TestSource ]) =
832868 this (targets, 1 , true , None , false , false )
833869
834870 /** Compose test targets from `this` with `other`
@@ -857,8 +893,10 @@ trait ParallelTesting extends RunnerOrchestration { self =>
857893 * compilation without generating errors and that they do not crash the
858894 * compiler
859895 */
860- def checkCompile ()(implicit summaryReport : SummaryReporting ): this .type = {
861- val test = new PosTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
896+ def checkCompile (checkCompileOutput : Boolean = false )(implicit summaryReport : SummaryReporting ): this .type = {
897+ val test = new PosTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput, checkCompileOutput).executeTestSuite()
898+
899+ cleanup()
862900
863901 if (! shouldFail && test.didFail) {
864902 fail(s " Expected no errors when compiling, failed for the following reason(s): \n ${ reasonsForFailure(test) }" )
@@ -867,15 +905,17 @@ trait ParallelTesting extends RunnerOrchestration { self =>
867905 fail(" Pos test should have failed, but didn't" )
868906 }
869907
870- cleanup()
908+ this
871909 }
872910
873911 /** Creates a "neg" test run, which makes sure that each test generates the
874912 * correct amount of errors at the correct positions. It also makes sure
875913 * that none of these tests crash the compiler
876914 */
877- def checkExpectedErrors ()(implicit summaryReport : SummaryReporting ): this .type = {
878- val test = new NegTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
915+ def checkExpectedErrors (checkCompileOutput : Boolean = false )(implicit summaryReport : SummaryReporting ): this .type = {
916+ val test = new NegTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput, checkCompileOutput).executeTestSuite()
917+
918+ cleanup()
879919
880920 if (! shouldFail && test.didFail) {
881921 fail(s " Neg test shouldn't have failed, but did. Reasons: \n ${ reasonsForFailure(test) }" )
@@ -884,7 +924,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
884924 fail(" Neg test should have failed, but did not" )
885925 }
886926
887- cleanup()
927+ this
888928 }
889929
890930 /** Creates a "run" test run, which is a superset of "pos". In addition to
@@ -895,14 +935,16 @@ trait ParallelTesting extends RunnerOrchestration { self =>
895935 def checkRuns ()(implicit summaryReport : SummaryReporting ): this .type = {
896936 val test = new RunTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
897937
938+ cleanup()
939+
898940 if (! shouldFail && test.didFail) {
899941 fail(s " Run test failed, but should not, reasons: \n ${ reasonsForFailure(test) }" )
900942 }
901943 else if (shouldFail && ! test.didFail) {
902944 fail(" Run test should have failed, but did not" )
903945 }
904946
905- cleanup()
947+ this
906948 }
907949
908950 /** Deletes output directories and files */
@@ -1005,7 +1047,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
10051047 }
10061048
10071049 /** Create out directory for directory `d` */
1008- private def createOutputDirsForDir (d : JFile , sourceDir : JFile , outDir : String ): JFile = {
1050+ def createOutputDirsForDir (d : JFile , sourceDir : JFile , outDir : String ): JFile = {
10091051 val targetDir = new JFile (outDir + s " ${sourceDir.getName}/ ${d.getName}" )
10101052 targetDir.mkdirs()
10111053 targetDir
0 commit comments