@@ -6,22 +6,21 @@ import java.io.{ File => JFile }
6
6
import java .text .SimpleDateFormat
7
7
import java .util .HashMap
8
8
import 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 }
11
11
12
12
import scala .io .Source
13
13
import scala .util .control .NonFatal
14
14
import scala .util .Try
15
15
import scala .collection .mutable
16
16
import scala .util .matching .Regex
17
17
import scala .util .Random
18
-
19
18
import dotc .core .Contexts ._
20
- import dotc .reporting .{ Reporter , TestReporter }
19
+ import dotc .reporting .{ Reporter , StoredTestReporter , TestReporter }
21
20
import dotc .reporting .diagnostic .MessageContainer
22
21
import dotc .interfaces .Diagnostic .ERROR
23
22
import dotc .util .DiffUtil
24
- import dotc .{ Driver , Compiler }
23
+ import dotc .{ Compiler , Driver }
25
24
26
25
/** A parallel testing suite whose goal is to integrate nicely with JUnit
27
26
*
@@ -47,7 +46,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
47
46
/** A test source whose files or directory of files is to be compiled
48
47
* in a specific way defined by the `Test`
49
48
*/
50
- private sealed trait TestSource { self =>
49
+ sealed trait TestSource { self =>
51
50
def name : String
52
51
def outDir : JFile
53
52
def flags : TestFlags
@@ -128,7 +127,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
128
127
/** A group of files that may all be compiled together, with the same flags
129
128
* and output directory
130
129
*/
131
- private final case class JointCompilationSource (
130
+ final case class JointCompilationSource (
132
131
name : String ,
133
132
files : Array [JFile ],
134
133
flags : TestFlags ,
@@ -143,7 +142,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
143
142
/** A test source whose files will be compiled separately according to their
144
143
* suffix `_X`
145
144
*/
146
- private final case class SeparateCompilationSource (
145
+ final case class SeparateCompilationSource (
147
146
name : String ,
148
147
dir : JFile ,
149
148
flags : TestFlags ,
@@ -176,7 +175,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
176
175
/** Each `Test` takes the `testSources` and performs the compilation and assertions
177
176
* according to the implementing class "neg", "run" or "pos".
178
177
*/
179
- private abstract class Test (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )(implicit val summaryReport : SummaryReporting ) { test =>
178
+ private abstract class Test (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean , checkCompileOutput : Boolean = false )(implicit val summaryReport : SummaryReporting ) { test =>
180
179
181
180
import summaryReport ._
182
181
@@ -352,9 +351,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
352
351
else None
353
352
} else None
354
353
354
+ val logLevel = if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR
355
355
val reporter =
356
- TestReporter .reporter(realStdout, logLevel =
357
- if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR )
356
+ if (checkCompileOutput)
357
+ TestReporter .storedReporter(realStdout, logLevel = logLevel)
358
+ else
359
+ TestReporter .reporter(realStdout, logLevel = logLevel)
358
360
359
361
val driver =
360
362
if (times == 1 ) new Driver
@@ -463,10 +465,28 @@ trait ParallelTesting extends RunnerOrchestration { self =>
463
465
private def flattenFiles (f : JFile ): Array [JFile ] =
464
466
if (f.isDirectory) f.listFiles.flatMap(flattenFiles)
465
467
else Array (f)
468
+
469
+ protected def verifyCompileOutput (source : TestSource , checkFile : JFile , reporter : StoredTestReporter ): Unit = {
470
+ reporter.writer.flush()
471
+ val checkLines = Source .fromFile(checkFile).getLines().mkString(" \n " )
472
+ val outputLines = reporter.writer.toString.trim.replaceAll(" \\ s+\n " , " \n " )
473
+
474
+ if (outputLines != checkLines) {
475
+ val msg = s " Output from ' ${source.title}' did not match check file ' ${checkFile.getName}'. "
476
+ println(" ===============================" )
477
+ println(" expected: \n " + checkLines)
478
+ println(" actual: \n " + outputLines)
479
+ println(" ===============================" )
480
+
481
+ echo(msg)
482
+ addFailureInstruction(msg)
483
+ failTestSource(source)
484
+ }
485
+ }
466
486
}
467
487
468
- private final class PosTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )(implicit summaryReport : SummaryReporting )
469
- extends Test (testSources, times, threadLimit, suppressAllOutput) {
488
+ private final class PosTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean , checkCompileOutput : Boolean = false )(implicit summaryReport : SummaryReporting )
489
+ extends Test (testSources, times, threadLimit, suppressAllOutput, checkCompileOutput ) {
470
490
protected def encapsulatedCompilation (testSource : TestSource ) = new LoggedRunnable {
471
491
def checkTestSource (): Unit = tryCompile(testSource) {
472
492
testSource match {
@@ -499,6 +519,15 @@ trait ParallelTesting extends RunnerOrchestration { self =>
499
519
reporters.foreach(logReporterContents)
500
520
logBuildInstructions(reporters.head, testSource, errorCount, warningCount)
501
521
}
522
+
523
+ // verify compilation check file
524
+ (1 to testSource.compilationGroups.length).foreach { index =>
525
+ val checkFile = new JFile (dir.getAbsolutePath.reverse.dropWhile(_ == '/' ).reverse + " /" + index + " .check" )
526
+
527
+ if (checkFile.exists && checkCompileOutput)
528
+ verifyCompileOutput(testSource, checkFile, reporters(index).asInstanceOf [StoredTestReporter ])
529
+ }
530
+ }
502
531
}
503
532
}
504
533
}
@@ -622,8 +651,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
622
651
}
623
652
}
624
653
625
- private final class NegTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )(implicit summaryReport : SummaryReporting )
626
- extends Test (testSources, times, threadLimit, suppressAllOutput) {
654
+ private final class NegTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean , checkCompileOutput : Boolean = false )(implicit summaryReport : SummaryReporting )
655
+ extends Test (testSources, times, threadLimit, suppressAllOutput, checkCompileOutput ) {
627
656
protected def encapsulatedCompilation (testSource : TestSource ) = new LoggedRunnable {
628
657
def checkTestSource (): Unit = tryCompile(testSource) {
629
658
// In neg-tests we allow two types of error annotations,
@@ -700,6 +729,14 @@ trait ParallelTesting extends RunnerOrchestration { self =>
700
729
if (actualErrors > 0 )
701
730
reporters.foreach(logReporterContents)
702
731
732
+ // Compilation check file: for testing plugins
733
+ (1 to testSource.compilationGroups.length).foreach { index =>
734
+ val checkFile = new JFile (dir.getAbsolutePath.reverse.dropWhile(_ == '/' ).reverse + " /" + index + " .check" )
735
+
736
+ if (checkFile.exists && checkCompileOutput)
737
+ verifyCompileOutput(testSource, checkFile, reporters(index).asInstanceOf [StoredTestReporter ])
738
+ }
739
+
703
740
(compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, errors), errorMap)
704
741
}
705
742
}
@@ -847,10 +884,10 @@ trait ParallelTesting extends RunnerOrchestration { self =>
847
884
) {
848
885
import org .junit .Assert .fail
849
886
850
- private [ ParallelTesting ] def this (target : TestSource ) =
887
+ def this (target : TestSource ) =
851
888
this (List (target), 1 , true , None , false , false )
852
889
853
- private [ ParallelTesting ] def this (targets : List [TestSource ]) =
890
+ def this (targets : List [TestSource ]) =
854
891
this (targets, 1 , true , None , false , false )
855
892
856
893
/** Compose test targets from `this` with `other`
@@ -879,8 +916,10 @@ trait ParallelTesting extends RunnerOrchestration { self =>
879
916
* compilation without generating errors and that they do not crash the
880
917
* compiler
881
918
*/
882
- def checkCompile ()(implicit summaryReport : SummaryReporting ): this .type = {
883
- val test = new PosTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
919
+ def checkCompile (checkCompileOutput : Boolean = false )(implicit summaryReport : SummaryReporting ): this .type = {
920
+ val test = new PosTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput, checkCompileOutput).executeTestSuite()
921
+
922
+ cleanup()
884
923
885
924
if (! shouldFail && test.didFail) {
886
925
fail(s " Expected no errors when compiling, failed for the following reason(s): \n ${ reasonsForFailure(test) }" )
@@ -889,15 +928,17 @@ trait ParallelTesting extends RunnerOrchestration { self =>
889
928
fail(" Pos test should have failed, but didn't" )
890
929
}
891
930
892
- cleanup()
931
+ this
893
932
}
894
933
895
934
/** Creates a "neg" test run, which makes sure that each test generates the
896
935
* correct amount of errors at the correct positions. It also makes sure
897
936
* that none of these tests crash the compiler
898
937
*/
899
- def checkExpectedErrors ()(implicit summaryReport : SummaryReporting ): this .type = {
900
- val test = new NegTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
938
+ def checkExpectedErrors (checkCompileOutput : Boolean = false )(implicit summaryReport : SummaryReporting ): this .type = {
939
+ val test = new NegTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput, checkCompileOutput).executeTestSuite()
940
+
941
+ cleanup()
901
942
902
943
if (! shouldFail && test.didFail) {
903
944
fail(s " Neg test shouldn't have failed, but did. Reasons: \n ${ reasonsForFailure(test) }" )
@@ -906,7 +947,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
906
947
fail(" Neg test should have failed, but did not" )
907
948
}
908
949
909
- cleanup()
950
+ this
910
951
}
911
952
912
953
/** Creates a "run" test run, which is a superset of "pos". In addition to
@@ -917,14 +958,16 @@ trait ParallelTesting extends RunnerOrchestration { self =>
917
958
def checkRuns ()(implicit summaryReport : SummaryReporting ): this .type = {
918
959
val test = new RunTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
919
960
961
+ cleanup()
962
+
920
963
if (! shouldFail && test.didFail) {
921
964
fail(s " Run test failed, but should not, reasons: \n ${ reasonsForFailure(test) }" )
922
965
}
923
966
else if (shouldFail && ! test.didFail) {
924
967
fail(" Run test should have failed, but did not" )
925
968
}
926
969
927
- cleanup()
970
+ this
928
971
}
929
972
930
973
/** Deletes output directories and files */
@@ -1027,7 +1070,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
1027
1070
}
1028
1071
1029
1072
/** Create out directory for directory `d` */
1030
- private def createOutputDirsForDir (d : JFile , sourceDir : JFile , outDir : String ): JFile = {
1073
+ def createOutputDirsForDir (d : JFile , sourceDir : JFile , outDir : String ): JFile = {
1031
1074
val targetDir = new JFile (outDir + s " ${sourceDir.getName}/ ${d.getName}" )
1032
1075
targetDir.mkdirs()
1033
1076
targetDir
0 commit comments