Skip to content

Commit cad895d

Browse files
authored
Skip test of legacy compiler if not JDK 17 (#25452)
Fixes #23090 ## How much have your relied on LLM-based tools in this contribution? LLM-free. That is reminiscent of [Ollie, ollie, in come free](https://www.appalachianhistory.net/2017/06/ollie-ollie-in-come-free.html), which is how we said it. ## How was the solution tested? Manually tested locally under JDK 25, to show that ``` tests/run/backwardsCompat-implicitParens/A_1_c3.0.2.scala ``` causes that test to be skipped. Single test files were not compiled correctly (with the legacy compiler), so also test that this fails without the fix and is skipped with the fix: ``` tests/run/lazyVals_c3.1.0.scala ``` ## Additional notes Left the unused import of `chaining` because lacking it results in a tangential rabbit hole: #25451
1 parent 6b70f91 commit cad895d

6 files changed

Lines changed: 69 additions & 17 deletions

File tree

compiler/test/dotc/scoverage-ignore.excludelist

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ i20053b.scala
2828
i2146.scala
2929
i23179.scala
3030
i23489.scala
31+
i25460.scala
3132
i5039.scala
3233
i8623.scala
3334
i8900a3.scala
3435
i9228.scala
36+
lazyVals_c3.0.0.scala
37+
lazyVals_c3.1.0.scala
3538
minicheck.scala
3639
minicheck-toplevel.scala
3740
mt-scrutinee-widen3.scala
@@ -41,4 +44,3 @@ skolems2.scala
4144
spurious-overload.scala
4245
tailrec.scala
4346
traitParams.scala
44-
i25460.scala

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

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import scala.collection.mutable, mutable.ArrayBuffer, mutable.ListBuffer
1616
import scala.io.{Codec, Source}
1717
import scala.jdk.CollectionConverters.*
1818
import scala.util.{Random, Try, Using}
19-
import scala.collection.mutable.ListBuffer
19+
import scala.util.control.NonFatal
20+
import scala.util.matching.Regex
21+
import scala.util.Properties.{isJavaAtLeast, javaSpecVersion}
2022

2123
import dotc.{Compiler, Driver}
2224
import dotty.tools.dotc.CoverageSupport
@@ -27,6 +29,7 @@ import dotc.reporting.{Reporter, TestReporter}
2729
import dotc.reporting.Diagnostic
2830
import dotc.util.{SourceFile, SourcePosition, Spans, NoSourcePosition}
2931
import io.AbstractFile
32+
import util.chaining.*
3033

3134
/** A parallel testing suite whose goal is to integrate nicely with JUnit
3235
*
@@ -199,16 +202,15 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
199202
flags: TestFlags,
200203
outDir: JFile
201204
)(using val group: TestGroup) extends TestSource {
205+
import SeparateCompilationSource.*
202206
case class Group(ordinal: Int, compiler: String)
203207

204-
lazy val compilationGroups: List[(Group, Array[JFile])] =
205-
val Compiler = """c([\d\.]+)""".r
206-
val Ordinal = """(\d+)""".r
208+
lazy val compilationGroups: List[(Group, Array[JFile])] = {
207209
def groupFor(file: JFile): Group =
208210
val groupSuffix = file.getName.dropWhile(_ != '_').stripSuffix(".scala").stripSuffix(".java")
209211
val groupSuffixParts = groupSuffix.split("_")
210-
val ordinal = groupSuffixParts.collectFirst { case Ordinal(n) => n.toInt }.getOrElse(Int.MinValue)
211-
val compiler = groupSuffixParts.collectFirst { case Compiler(c) => c }.getOrElse("")
212+
val ordinal = groupSuffixParts.collectFirst { case GroupOrdinal(n) => n.toInt }.getOrElse(Int.MinValue)
213+
val compiler = groupSuffixParts.collectFirst { case CompilerVersion(c) => c }.getOrElse("")
212214
Group(ordinal, compiler)
213215

214216
dir.listFiles
@@ -217,15 +219,32 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
217219
.toList
218220
.sortBy { (g, _) => (g.ordinal, g.compiler) }
219221
.map { (g, f) => (g, f.sorted) }
222+
}
220223

221224
def sourceFiles = compilationGroups.map(_._2).flatten.toArray
222225

223226
def checkFileBasePathCandidates: Array[String] =
224227
Array(dir.getPath)
225228
}
229+
object SeparateCompilationSource:
230+
val CompilerVersion = """c([\d\.]+)""".r
231+
val HasCompilerVersion = """_c([\d\.]+)""".r.unanchored
232+
val GroupOrdinal = """(\d+)""".r
226233

234+
/** Skip if there are no sources, such as in a spurious directory,
235+
* or when compiling with a legacy compiler which may not run under this jdk.
236+
*/
227237
protected def shouldSkipTestSource(testSource: TestSource): Boolean =
228-
testSource.sourceFiles.length == 0
238+
val files = testSource.sourceFiles
239+
files.length == 0
240+
||
241+
!TestConfiguration.usingBaselineJava
242+
&&
243+
testSource.match
244+
case separate: SeparateCompilationSource =>
245+
separate.compilationGroups.exists((group, _) => group.compiler.nonEmpty)
246+
case _ =>
247+
files.exists(f => SeparateCompilationSource.HasCompilerVersion.matches(f.getName))
229248

230249
protected def shouldReRun(testSource: TestSource): Boolean =
231250
failedTests.forall(rerun => testSource match {
@@ -246,7 +265,15 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
246265
Try(testSource match {
247266
case testSource @ JointCompilationSource(name, files, flags, outDir, fromTasty, decompilation) =>
248267
val reporter = fromTasty match
249-
case NotFromTasty => compile(testSource.sourceFiles, flags, outDir)
268+
case NotFromTasty =>
269+
if testSource.sourceFiles.length == 1 then
270+
testSource.sourceFiles(0).getName match
271+
case SeparateCompilationSource.HasCompilerVersion(version) =>
272+
val compiler = version.stripSuffix(".")
273+
compileWithOtherCompiler(compiler, testSource.sourceFiles, flags, outDir)
274+
case _ => compile(testSource.sourceFiles, flags, outDir)
275+
else
276+
compile(testSource.sourceFiles, flags, outDir)
250277
case FromTasty => compileFromTasty(flags, outDir)
251278
case FromBestEffortTasty => compileFromBestEffortTasty(flags, outDir)
252279
case WithBestEffortTasty(bestEffortDir) => compileWithBestEffortTasty(testSource.sourceFiles, bestEffortDir, flags, outDir)
@@ -487,7 +514,6 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
487514
throw e
488515

489516
protected def compile(files0: Array[JFile], flags0: TestFlags, targetDir: JFile): TestReporter = {
490-
import scala.util.Properties.*
491517

492518
def flattenFiles(f: JFile): Array[JFile] =
493519
if (f.isDirectory) f.listFiles.flatMap(flattenFiles)
@@ -630,7 +656,7 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
630656
case Nil => Nil
631657
flags.copy(options = loop(flags.options.toList).toArray)
632658

633-
protected def compileWithOtherCompiler(compiler: String, files: Array[JFile], flags: TestFlags, targetDir: JFile): TestReporter =
659+
protected def compileWithOtherCompiler(compiler: String, files: Array[JFile], flags: TestFlags, targetDir: JFile): TestReporter = {
634660
def artifactClasspath(organizationName: String, moduleName: String) =
635661
import coursier.*
636662
val dep = Dependency(
@@ -690,6 +716,8 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
690716
}
691717

692718
reporter
719+
}
720+
end compileWithOtherCompiler
693721

694722
protected def compileFromBestEffortTasty(flags0: TestFlags, targetDir: JFile): TestReporter = {
695723
val classes = flattenFiles(targetDir).filter(isBestEffortTastyFile).map(_.toString)
@@ -1532,6 +1560,8 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
15321560
* target all files are grouped according to the file suffix `_X` where `X`
15331561
* is a number. These groups are then ordered in ascending order based on
15341562
* the value of `X` and each group is compiled one after the other.
1563+
* A file can request compilation by a legacy compiler via a version suffix:
1564+
* `A_1_c3.2.0.scala` in group 1 is compiled by 3.2.0 when testing under the minimum supported JDK.
15351565
*
15361566
* For this function to work as expected, we use the same convention for
15371567
* directory layout as the old partest. That is:
@@ -1555,8 +1585,14 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
15551585
!isPicklerTest || source.compilationGroups.length == 1
15561586
}
15571587
val targets =
1558-
files.map(f => JointCompilationSource(testGroup.name, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir))) ++
1559-
dirs.map { dir => SeparateCompilationSource(testGroup.name, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir)) }.filter(picklerDirFilter)
1588+
files.map: f =>
1589+
val out = createOutputDirsForFile(f, sourceDir, outDir)
1590+
JointCompilationSource(testGroup.name, Array(f), flags, out)
1591+
++
1592+
dirs.map: dir =>
1593+
val out = createOutputDirsForDir(dir, sourceDir, outDir)
1594+
SeparateCompilationSource(testGroup.name, dir, flags, out)
1595+
.filter(picklerDirFilter)
15601596

15611597
// Create a CompilationTest and let the user decide whether to execute a pos or a neg test
15621598
new CompilationTest(targets)

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@ package tools
33
package vulpix
44

55
import scala.language.unsafeNulls
6+
import scala.util.Properties.javaSpecVersion
67

78
import java.io.File
89

10+
import dotc.config.ScalaSettingsProperties.supportedReleaseVersions
11+
912
object TestConfiguration {
1013

14+
val usingBaselineJava = javaSpecVersion.startsWith(supportedReleaseVersions.headOption.getOrElse("17"))
15+
1116
val pageWidth = 120
1217

1318
val noCheckOptions = Array(

tests/run-tasty-inspector/tastyPaths.scala

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import scala.quoted.*
22
import scala.tasty.inspector.*
33

4-
import java.io.File.separatorChar
4+
import java.io.File.{pathSeparator, separatorChar}
5+
6+
import dotty.tools.dotc.util.ClasspathFromClassloader
7+
import dotty.tools.io.{FileExtension, Path}
58

69
opaque type PhoneNumber = String
710

@@ -14,8 +17,12 @@ object Test {
1417
def main(args: Array[String]): Unit = {
1518
// Artefact of the current test infrastructure
1619
// TODO improve infrastructure to avoid needing this code on each test
17-
val classpath = dotty.tools.dotc.util.ClasspathFromClassloader(this.getClass.getClassLoader).split(java.io.File.pathSeparator).find(_.contains("runWithCompiler")).get
18-
val allTastyFiles = dotty.tools.io.Path(classpath).walkFilter(_.ext == dotty.tools.io.FileExtension.Tasty).map(_.toString).toList
20+
val classpath =
21+
ClasspathFromClassloader(getClass.getClassLoader)
22+
.split(pathSeparator)
23+
.find(_.contains("runWithCompiler"))
24+
.get
25+
val allTastyFiles = Path(classpath).walkFilter(_.ext == FileExtension.Tasty).map(_.toString).toList
1926
val tastyFiles = allTastyFiles.filter(_.contains("I8163"))
2027

2128
TastyInspector.inspectTastyFiles(tastyFiles)(new TestInspector())
@@ -30,4 +37,4 @@ class TestInspector() extends Inspector:
3037
quotes.reflect.SourceFile.current
3138
assert(false)
3239
catch case ex: java.lang.UnsupportedOperationException =>
33-
println(ex.getMessage) // ok
40+
println(ex.getMessage) // ok

tests/run/lazyVals_c3.0.0.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// scalajs: --skip
12
// Compiled with 3.0.0 and run with current compiler
23
class Foo:
34
lazy val x =

tests/run/lazyVals_c3.1.0.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// scalajs: --skip
12
// Compiled with 3.1.0 and run with current compiler
23
class Foo:
34
lazy val x =

0 commit comments

Comments
 (0)