Skip to content

Commit 48595fb

Browse files
committed
Test can be skipped
Specify release for test
1 parent 327ecc2 commit 48595fb

File tree

6 files changed

+71
-52
lines changed

6 files changed

+71
-52
lines changed

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

Lines changed: 70 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,11 @@ trait ParallelTesting extends RunnerOrchestration { self =>
384384
/** Number of failed tests */
385385
def failureCount: Int = _failureCount
386386

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+
387392
protected def logBuildInstructions(testSource: TestSource, reporters: Seq[TestReporter]) = {
388393
val (errCount, warnCount) = countErrorsAndWarnings(reporters)
389394
val errorMsg = testSource.buildInstructions(errCount, warnCount)
@@ -456,13 +461,20 @@ trait ParallelTesting extends RunnerOrchestration { self =>
456461
val toolArgs = toolArgsFor(files.toList.map(_.toPath), getCharsetFromEncodingOpt(flags0))
457462

458463
val spec = raw"(\d+)(\+)?".r
459-
val testFilter = toolArgs.get(ToolName.Test) match
464+
val testIsFiltered = toolArgs.get(ToolName.Test) match
460465
case Some("-jvm" :: spec(n, more) :: Nil) =>
461466
if more == "+" then isJavaAtLeast(n) else javaSpecVersion == n
462467
case Some(args) => throw new IllegalStateException(args.mkString("unknown test option: ", ", ", ""))
463468
case None => true
469+
val minRelease = toolArgs.get(ToolName.Test) match
470+
case Some("-jvm" :: spec(n, more) :: Nil) =>
471+
if more == "+" then javaSpecVersion else n
472+
case _ => "8"
464473

465-
def scalacOptions = toolArgs.get(ToolName.Scalac).getOrElse(Nil)
474+
def scalacOptions =
475+
toolArgs.get(ToolName.Scalac)
476+
.map(args => if args.exists(_.startsWith("-release")) then args else "-release" :: minRelease :: args)
477+
.getOrElse(Nil)
466478

467479
val flags = flags0
468480
.and(scalacOptions: _*)
@@ -482,9 +494,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
482494
else None
483495
} else None
484496

485-
val reporter =
486-
TestReporter.reporter(realStdout, logLevel =
487-
if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR)
497+
val reporter = TestReporter.reporter(realStdout, logLevel = if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR)
488498

489499
val driver =
490500
if (times == 1) new Driver
@@ -503,7 +513,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
503513

504514
val allArgs = flags.all
505515

506-
if testFilter then
516+
if testIsFiltered then
507517
// If a test contains a Java file that cannot be parsed by Dotty's Java source parser, its
508518
// name must contain the string "JAVA_ONLY".
509519
val dottyFiles = files.filterNot(_.getName.contains("JAVA_ONLY")).map(_.getPath)
@@ -517,6 +527,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
517527
echo(s"\njava compilation failed: \n${ javaErrors.get }")
518528
fail(failure = JavaCompilationFailure(javaErrors.get))
519529
}
530+
else
531+
skip()
520532
end if
521533

522534
reporter
@@ -738,7 +750,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
738750
}
739751

740752
private def verifyOutput(checkFile: Option[JFile], dir: JFile, testSource: TestSource, warnings: Int, reporters: Seq[TestReporter], logger: LoggedRunnable) = {
741-
if (Properties.testsNoRun) addNoRunWarning()
753+
if skipped then ()
754+
else if Properties.testsNoRun then addNoRunWarning()
742755
else runMain(testSource.runClassPath) match {
743756
case Success(output) => checkFile match {
744757
case Some(file) if file.exists => diffTest(testSource, file, output.linesIterator.toList, reporters, logger)
@@ -762,7 +775,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
762775
extends Test(testSources, times, threadLimit, suppressAllOutput) {
763776
override def suppressErrors = true
764777

765-
override def maybeFailureMessage(testSource: TestSource, reporters: Seq[TestReporter]): Option[String] = {
778+
override def maybeFailureMessage(testSource: TestSource, reporters: Seq[TestReporter]): Option[String] = if skipped then None else
766779
def compilerCrashed = reporters.exists(_.compilerCrashed)
767780
lazy val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(testSource.sourceFiles.toIndexedSeq)
768781
lazy val actualErrors = reporters.foldLeft(0)(_ + _.errorCount)
@@ -786,20 +799,21 @@ trait ParallelTesting extends RunnerOrchestration { self =>
786799
else if !errorMap.isEmpty then s"\nExpected error(s) have {<error position>=<unreported error>}: $errorMap"
787800
else null
788801
}
789-
}
802+
end maybeFailureMessage
790803

791804
override def onSuccess(testSource: TestSource, reporters: Seq[TestReporter], logger: LoggedRunnable): Unit =
792805
checkFile(testSource).foreach(diffTest(testSource, _, reporterOutputLines(reporters), reporters, logger))
793806

794807
def reporterOutputLines(reporters: Seq[TestReporter]): List[String] =
795808
reporters.flatMap(_.consoleOutput.split("\n")).toList
796809

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.
810+
// In neg-tests we allow two or three types of error annotations.
811+
// Normally, `// error` must be annotated on the correct line number.
812+
// `// nopos-error` allows for an error reported without a position.
813+
// `// anypos-error` allows for an error reported with a position that can't be annotated in the check file.
800814
//
801815
// We collect these in a map `"file:row" -> numberOfErrors`, for
802-
// nopos errors we save them in `"file" -> numberOfNoPosErrors`
816+
// nopos and anypos errors we save them in `"file" -> numberOfNoPosErrors`
803817
def getErrorMapAndExpectedCount(files: Seq[JFile]): (HashMap[String, Integer], Int) =
804818
val comment = raw"//( *)(nopos-|anypos-)?error".r
805819
val errorMap = new HashMap[String, Integer]()
@@ -964,8 +978,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
964978
* ===============
965979
* Since this is a parallel test suite, it is essential to be able to
966980
* 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 `+`.
981+
* `aggregateTests` in the companion, which will ensure that aggregation is allowed.
969982
*/
970983
final class CompilationTest private (
971984
private[ParallelTesting] val targets: List[TestSource],
@@ -983,6 +996,14 @@ trait ParallelTesting extends RunnerOrchestration { self =>
983996
def this(targets: List[TestSource]) =
984997
this(targets, 1, true, None, false, false)
985998

999+
def copy(targets: List[TestSource],
1000+
times: Int = times,
1001+
shouldDelete: Boolean = shouldDelete,
1002+
threadLimit: Option[Int] = threadLimit,
1003+
shouldFail: Boolean = shouldFail,
1004+
shouldSuppressOutput: Boolean = shouldSuppressOutput): CompilationTest =
1005+
CompilationTest(targets, times, shouldDelete, threadLimit, shouldFail, shouldSuppressOutput)
1006+
9861007
/** Creates a "pos" test run, which makes sure that all tests pass
9871008
* compilation without generating errors and that they do not crash the
9881009
* compiler
@@ -1003,23 +1024,23 @@ trait ParallelTesting extends RunnerOrchestration { self =>
10031024
}
10041025

10051026
/** 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
1027+
* correct number of errors at the correct positions. It also makes sure
1028+
* that none of these tests crashes the compiler.
10081029
*/
1009-
def checkExpectedErrors()(implicit summaryReport: SummaryReporting): this.type = {
1030+
def checkExpectedErrors()(implicit summaryReport: SummaryReporting): this.type =
10101031
val test = new NegTest(targets, times, threadLimit, shouldFail || shouldSuppressOutput).executeTestSuite()
10111032

10121033
cleanup()
10131034

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-
}
1035+
if !test.skipped then
1036+
if shouldFail && !test.didFail then
1037+
fail(s"Neg test shouldn't have failed, but did. Reasons:\n${ reasonsForFailure(test) }")
1038+
else if !shouldFail && test.didFail then
1039+
fail("Neg test should have failed, but did not")
1040+
end if
10201041

10211042
this
1022-
}
1043+
end checkExpectedErrors
10231044

10241045
/** Creates a "fuzzy" test run, which makes sure that each test compiles (or not) without crashing */
10251046
def checkNoCrash()(implicit summaryReport: SummaryReporting): this.type = {
@@ -1044,12 +1065,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
10441065

10451066
cleanup()
10461067

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-
}
1068+
if !test.skipped then
1069+
if !shouldFail && test.didFail then
1070+
fail(s"Run test failed, but should not, reasons:\n${ reasonsForFailure(test) }")
1071+
else if shouldFail && !test.didFail then
1072+
fail("Run test should have failed, but did not")
1073+
end if
10531074

10541075
this
10551076
}
@@ -1174,35 +1195,32 @@ trait ParallelTesting extends RunnerOrchestration { self =>
11741195
}
11751196
}
11761197

1177-
object CompilationTest {
1198+
object CompilationTest:
11781199

11791200
/** 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 = {
1201+
*
1202+
* It does this, only if all the tests are mutally compatible.
1203+
* Otherwise it throws an `IllegalArgumentException`.
1204+
*
1205+
* Grouping tests together like this allows us to take advantage of the
1206+
* concurrency offered by this test suite, as each call to an executing
1207+
* method (`pos()` / `checkExpectedErrors()`/ `run()`) will spin up a thread pool with the
1208+
* maximum allowed level of concurrency. Doing this for only a few targets
1209+
* does not yield any real benefit over sequential compilation.
1210+
*
1211+
* As such, each `CompilationTest` should contain as many targets as
1212+
* possible.
1213+
*/
1214+
def aggregateTests(tests: CompilationTest*): CompilationTest =
11941215
assert(tests.nonEmpty)
1195-
def aggregate(test1: CompilationTest, test2: CompilationTest) = {
1216+
def aggregate(test1: CompilationTest, test2: CompilationTest) =
11961217
require(test1.times == test2.times, "can't combine tests that are meant to be benchmark compiled")
11971218
require(test1.shouldDelete == test2.shouldDelete, "can't combine tests that differ on deleting output")
11981219
require(test1.shouldFail == test2.shouldFail, "can't combine tests that have different expectations on outcome")
11991220
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-
}
1221+
test1.copy(test1.targets ++ test2.targets) // what if thread limit differs? currently threads are limited on aggregate only
12021222
tests.reduce(aggregate)
1203-
}
1204-
1205-
}
1223+
end CompilationTest
12061224

12071225
/** Create out directory for directory `d` */
12081226
def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: String): JFile = {

tests/neg-with-compiler/t12290/SCALA_ONLY_Invalid1.java renamed to tests/neg/t12290/SCALA_ONLY_Invalid1.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// note that scala's java parser doesn't care about the platform version
12
class SCALA_ONLY_Invalid1 {
23

34
public static final String badOpeningDelimiter = """non-whitespace // error
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)