@@ -384,6 +384,11 @@ trait ParallelTesting extends RunnerOrchestration { self =>
384
384
/** Number of failed tests */
385
385
def failureCount : Int = _failureCount
386
386
387
+ private var _skipCount = 0
388
+ protected final def skip (): Unit = synchronized { _skipCount += 1 }
389
+ def skipCount : Int = _skipCount
390
+ def skipped : Boolean = skipCount > 0
391
+
387
392
protected def logBuildInstructions (testSource : TestSource , reporters : Seq [TestReporter ]) = {
388
393
val (errCount, warnCount) = countErrorsAndWarnings(reporters)
389
394
val errorMsg = testSource.buildInstructions(errCount, warnCount)
@@ -456,7 +461,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
456
461
val toolArgs = toolArgsFor(files.toList.map(_.toPath), getCharsetFromEncodingOpt(flags0))
457
462
458
463
val spec = raw " (\d+)(\+)? " .r
459
- val testFilter = toolArgs.get(ToolName .Test ) match
464
+ val testIsFiltered = toolArgs.get(ToolName .Test ) match
460
465
case Some (" -jvm" :: spec(n, more) :: Nil ) =>
461
466
if more == " +" then isJavaAtLeast(n) else javaSpecVersion == n
462
467
case Some (args) => throw new IllegalStateException (args.mkString(" unknown test option: " , " , " , " " ))
@@ -482,9 +487,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
482
487
else None
483
488
} else None
484
489
485
- val reporter =
486
- TestReporter .reporter(realStdout, logLevel =
487
- if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR )
490
+ val reporter = TestReporter .reporter(realStdout, logLevel = if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR )
488
491
489
492
val driver =
490
493
if (times == 1 ) new Driver
@@ -503,7 +506,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
503
506
504
507
val allArgs = flags.all
505
508
506
- if testFilter then
509
+ if testIsFiltered then
507
510
// If a test contains a Java file that cannot be parsed by Dotty's Java source parser, its
508
511
// name must contain the string "JAVA_ONLY".
509
512
val dottyFiles = files.filterNot(_.getName.contains(" JAVA_ONLY" )).map(_.getPath)
@@ -517,6 +520,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
517
520
echo(s " \n java compilation failed: \n ${ javaErrors.get }" )
518
521
fail(failure = JavaCompilationFailure (javaErrors.get))
519
522
}
523
+ else
524
+ skip()
520
525
end if
521
526
522
527
reporter
@@ -738,7 +743,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
738
743
}
739
744
740
745
private def verifyOutput (checkFile : Option [JFile ], dir : JFile , testSource : TestSource , warnings : Int , reporters : Seq [TestReporter ], logger : LoggedRunnable ) = {
741
- if (Properties .testsNoRun) addNoRunWarning()
746
+ if skipped then ()
747
+ else if Properties .testsNoRun then addNoRunWarning()
742
748
else runMain(testSource.runClassPath) match {
743
749
case Success (output) => checkFile match {
744
750
case Some (file) if file.exists => diffTest(testSource, file, output.linesIterator.toList, reporters, logger)
@@ -762,7 +768,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
762
768
extends Test (testSources, times, threadLimit, suppressAllOutput) {
763
769
override def suppressErrors = true
764
770
765
- override def maybeFailureMessage (testSource : TestSource , reporters : Seq [TestReporter ]): Option [String ] = {
771
+ override def maybeFailureMessage (testSource : TestSource , reporters : Seq [TestReporter ]): Option [String ] = if skipped then None else
766
772
def compilerCrashed = reporters.exists(_.compilerCrashed)
767
773
lazy val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(testSource.sourceFiles.toIndexedSeq)
768
774
lazy val actualErrors = reporters.foldLeft(0 )(_ + _.errorCount)
@@ -786,20 +792,21 @@ trait ParallelTesting extends RunnerOrchestration { self =>
786
792
else if ! errorMap.isEmpty then s " \n Expected error(s) have {<error position>=<unreported error>}: $errorMap"
787
793
else null
788
794
}
789
- }
795
+ end maybeFailureMessage
790
796
791
797
override def onSuccess (testSource : TestSource , reporters : Seq [TestReporter ], logger : LoggedRunnable ): Unit =
792
798
checkFile(testSource).foreach(diffTest(testSource, _, reporterOutputLines(reporters), reporters, logger))
793
799
794
800
def reporterOutputLines (reporters : Seq [TestReporter ]): List [String ] =
795
801
reporters.flatMap(_.consoleOutput.split(" \n " )).toList
796
802
797
- // In neg-tests we allow two types of error annotations,
798
- // "nopos-error" which doesn't care about position and "error" which
799
- // has to be annotated on the correct line number.
803
+ // In neg-tests we allow two or three types of error annotations.
804
+ // Normally, `// error` must be annotated on the correct line number.
805
+ // `// nopos-error` allows for an error reported without a position.
806
+ // `// anypos-error` allows for an error reported with a position that can't be annotated in the check file.
800
807
//
801
808
// We collect these in a map `"file:row" -> numberOfErrors`, for
802
- // nopos errors we save them in `"file" -> numberOfNoPosErrors`
809
+ // nopos and anypos errors we save them in `"file" -> numberOfNoPosErrors`
803
810
def getErrorMapAndExpectedCount (files : Seq [JFile ]): (HashMap [String , Integer ], Int ) =
804
811
val comment = raw " //( *)(nopos-|anypos-)?error " .r
805
812
val errorMap = new HashMap [String , Integer ]()
@@ -964,8 +971,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
964
971
* ===============
965
972
* Since this is a parallel test suite, it is essential to be able to
966
973
* compose tests to take advantage of the concurrency. This is done using
967
- * the `+` function. This function will make sure that tests being combined
968
- * are compatible according to the `require`s in `+`.
974
+ * `aggregateTests` in the companion, which will ensure that aggregation is allowed.
969
975
*/
970
976
final class CompilationTest private (
971
977
private [ParallelTesting ] val targets : List [TestSource ],
@@ -983,6 +989,14 @@ trait ParallelTesting extends RunnerOrchestration { self =>
983
989
def this (targets : List [TestSource ]) =
984
990
this (targets, 1 , true , None , false , false )
985
991
992
+ def copy (targets : List [TestSource ],
993
+ times : Int = times,
994
+ shouldDelete : Boolean = shouldDelete,
995
+ threadLimit : Option [Int ] = threadLimit,
996
+ shouldFail : Boolean = shouldFail,
997
+ shouldSuppressOutput : Boolean = shouldSuppressOutput): CompilationTest =
998
+ CompilationTest (targets, times, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput)
999
+
986
1000
/** Creates a "pos" test run, which makes sure that all tests pass
987
1001
* compilation without generating errors and that they do not crash the
988
1002
* compiler
@@ -1003,23 +1017,23 @@ trait ParallelTesting extends RunnerOrchestration { self =>
1003
1017
}
1004
1018
1005
1019
/** Creates a "neg" test run, which makes sure that each test generates the
1006
- * correct amount of errors at the correct positions. It also makes sure
1007
- * that none of these tests crash the compiler
1020
+ * correct number of errors at the correct positions. It also makes sure
1021
+ * that none of these tests crashes the compiler.
1008
1022
*/
1009
- def checkExpectedErrors ()(implicit summaryReport : SummaryReporting ): this .type = {
1023
+ def checkExpectedErrors ()(implicit summaryReport : SummaryReporting ): this .type =
1010
1024
val test = new NegTest (targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
1011
1025
1012
1026
cleanup()
1013
1027
1014
- if (shouldFail && ! test.didFail) {
1015
- fail( s " Neg test shouldn't have failed, but did. Reasons: \n ${ reasonsForFailure(test) } " )
1016
- }
1017
- else if ( ! shouldFail && test.didFail) {
1018
- fail(" Neg test should have failed, but did not" )
1019
- }
1028
+ if ! test.skipped then
1029
+ if shouldFail && ! test.didFail then
1030
+ fail( s " Neg test shouldn't have failed, but did. Reasons: \n ${ reasonsForFailure(test) } " )
1031
+ else if ! shouldFail && test.didFail then
1032
+ fail(" Neg test should have failed, but did not" )
1033
+ end if
1020
1034
1021
1035
this
1022
- }
1036
+ end checkExpectedErrors
1023
1037
1024
1038
/** Creates a "fuzzy" test run, which makes sure that each test compiles (or not) without crashing */
1025
1039
def checkNoCrash ()(implicit summaryReport : SummaryReporting ): this .type = {
@@ -1044,12 +1058,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
1044
1058
1045
1059
cleanup()
1046
1060
1047
- if ( ! shouldFail && test.didFail) {
1048
- fail( s " Run test failed, but should not, reasons: \n ${ reasonsForFailure( test) } " )
1049
- }
1050
- else if ( shouldFail && ! test.didFail) {
1051
- fail(" Run test should have failed, but did not" )
1052
- }
1061
+ if ! test.skipped then
1062
+ if ! shouldFail && test.didFail then
1063
+ fail( s " Run test failed, but should not, reasons: \n ${ reasonsForFailure(test) } " )
1064
+ else if shouldFail && ! test.didFail then
1065
+ fail(" Run test should have failed, but did not" )
1066
+ end if
1053
1067
1054
1068
this
1055
1069
}
@@ -1174,35 +1188,32 @@ trait ParallelTesting extends RunnerOrchestration { self =>
1174
1188
}
1175
1189
}
1176
1190
1177
- object CompilationTest {
1191
+ object CompilationTest :
1178
1192
1179
1193
/** Compose test targets from `tests`
1180
- *
1181
- * It does this, only if the two tests are compatible. Otherwise it throws
1182
- * an `IllegalArgumentException`.
1183
- *
1184
- * Grouping tests together like this allows us to take advantage of the
1185
- * concurrency offered by this test suite as each call to an executing
1186
- * method (`pos()` / `checkExpectedErrors()`/ `run()`) will spin up a thread pool with the
1187
- * maximum allowed level of concurrency. Doing this for only a few targets
1188
- * does not yield any real benefit over sequential compilation.
1189
- *
1190
- * As such, each `CompilationTest` should contain as many targets as
1191
- * possible.
1192
- */
1193
- def aggregateTests (tests : CompilationTest * ): CompilationTest = {
1194
+ *
1195
+ * It does this, only if all the tests are mutally compatible.
1196
+ * Otherwise it throws an `IllegalArgumentException`.
1197
+ *
1198
+ * Grouping tests together like this allows us to take advantage of the
1199
+ * concurrency offered by this test suite, as each call to an executing
1200
+ * method (`pos()` / `checkExpectedErrors()`/ `run()`) will spin up a thread pool with the
1201
+ * maximum allowed level of concurrency. Doing this for only a few targets
1202
+ * does not yield any real benefit over sequential compilation.
1203
+ *
1204
+ * As such, each `CompilationTest` should contain as many targets as
1205
+ * possible.
1206
+ */
1207
+ def aggregateTests (tests : CompilationTest * ): CompilationTest =
1194
1208
assert(tests.nonEmpty)
1195
- def aggregate (test1 : CompilationTest , test2 : CompilationTest ) = {
1209
+ def aggregate (test1 : CompilationTest , test2 : CompilationTest ) =
1196
1210
require(test1.times == test2.times, " can't combine tests that are meant to be benchmark compiled" )
1197
1211
require(test1.shouldDelete == test2.shouldDelete, " can't combine tests that differ on deleting output" )
1198
1212
require(test1.shouldFail == test2.shouldFail, " can't combine tests that have different expectations on outcome" )
1199
1213
require(test1.shouldSuppressOutput == test2.shouldSuppressOutput, " can't combine tests that both suppress and don't suppress output" )
1200
- new CompilationTest (test1.targets ++ test2.targets, test1.times, test1.shouldDelete, test1.threadLimit, test1.shouldFail, test1.shouldSuppressOutput)
1201
- }
1214
+ test1.copy(test1.targets ++ test2.targets) // what if thread limit differs? currently threads are limited on aggregate only
1202
1215
tests.reduce(aggregate)
1203
- }
1204
-
1205
- }
1216
+ end CompilationTest
1206
1217
1207
1218
/** Create out directory for directory `d` */
1208
1219
def createOutputDirsForDir (d : JFile , sourceDir : JFile , outDir : String ): JFile = {
0 commit comments