@@ -4,6 +4,7 @@ package vulpix
44
55import java .io .{File => JFile , IOException }
66import java .lang .System .{lineSeparator => EOL }
7+ import java .net .URL
78import java .nio .file .StandardCopyOption .REPLACE_EXISTING
89import java .nio .file .{Files , NoSuchFileException , Path , Paths }
910import java .nio .charset .StandardCharsets
@@ -127,10 +128,10 @@ trait ParallelTesting extends RunnerOrchestration { self =>
127128 }
128129 sb.toString + " \n\n "
129130 }
130- case self : SeparateCompilationSource => {
131+ case self : SeparateCompilationSource => { // TODO: this is incorrect when using other versions of compiler
131132 val command = sb.toString
132133 val fsb = new StringBuilder (command)
133- self.compilationGroups.foreach { files =>
134+ self.compilationGroups.foreach { (_, files) =>
134135 files.map(_.getPath).foreach { path =>
135136 fsb.append(delimiter)
136137 lineLen = 8
@@ -173,31 +174,28 @@ trait ParallelTesting extends RunnerOrchestration { self =>
173174 flags : TestFlags ,
174175 outDir : JFile
175176 ) extends TestSource {
176-
177- /** Get the files grouped by `_X` as a list of groups, files missing this
178- * suffix will be put into the same group.
179- * Files in each group are sorted alphabetically.
180- *
181- * Filters out all none source files
182- */
183- def compilationGroups : List [Array [JFile ]] =
184- dir
185- .listFiles
186- .groupBy { file =>
187- val name = file.getName
188- Try {
189- val potentialNumber = name
190- .substring(0 , name.lastIndexOf('.' ))
191- .reverse.takeWhile(_ != '_' ).reverse
192-
193- potentialNumber.toInt.toString
194- }
195- .toOption
196- .getOrElse(" " )
197- }
198- .toList.sortBy(_._1).map(_._2.filter(isSourceFile).sorted)
199-
200- def sourceFiles : Array [JFile ] = compilationGroups.flatten.toArray
177+ case class Group (ordinal : Int , compiler : String , target : String )
178+
179+ def compilationGroups : List [(Group , Array [JFile ])] =
180+ val Name = """ [^_]*((?:_.*)*)\.\w+""" .r
181+ val Target = """ t([\d\.]+)""" .r
182+ val Compiler = """ v([\d\.]+)""" .r
183+ val Ordinal = """ (\d+)""" .r
184+ def groupFor (file : JFile ): Group =
185+ val Name (annotPart) = file.getName
186+ val annots = annotPart.split(" _" )
187+ val ordinal = annots.collectFirst { case Ordinal (n) => n.toInt }.getOrElse(Int .MinValue )
188+ val target = annots.collectFirst { case Target (t) => t }.getOrElse(" " )
189+ val compiler = annots.collectFirst { case Compiler (c) => c}.getOrElse(" " )
190+ Group (ordinal, compiler, target)
191+
192+ dir.listFiles
193+ .groupBy(groupFor)
194+ .toList
195+ .sortBy { (g, _) => (g.ordinal, g.compiler, g.target) }
196+ .map { (g, f) => (g, f.sorted) }
197+
198+ def sourceFiles = compilationGroups.map(_._2).flatten.toArray
201199 }
202200
203201 private trait CompilationLogic { this : Test =>
@@ -216,7 +214,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
216214 List (reporter)
217215
218216 case testSource @ SeparateCompilationSource (_, dir, flags, outDir) =>
219- testSource.compilationGroups.map(files => compile(files, flags, suppressErrors, outDir)) // TODO? only `compile` option?
217+ testSource.compilationGroups.map { (group, files) =>
218+ if group.compiler.isEmpty then
219+ compile(files, flags, suppressErrors, outDir)
220+ else
221+ compileWithOtherCompiler(group.compiler, files, flags, outDir)
222+ }
220223 })
221224
222225 final def countErrorsAndWarnings (reporters : Seq [TestReporter ]): (Int , Int ) =
@@ -500,6 +503,18 @@ trait ParallelTesting extends RunnerOrchestration { self =>
500503 reporter
501504 }
502505
506+ protected def compileWithOtherCompiler (compiler : String , files : Array [JFile ], flags : TestFlags , targetDir : JFile ): TestReporter =
507+ val reporter = TestReporter .reporter(realStdout, ERROR ) // TODO: do some reporting
508+
509+ val command = Array (getCompiler(compiler).toString + " /bin/scalac" ) ++ flags.and(" -d" , targetDir.getPath).all ++ files.map(_.getPath)
510+ val process = Runtime .getRuntime.exec(command)
511+ val output = Source .fromInputStream(process.getErrorStream).mkString
512+ if process.waitFor() != 0 then
513+ echo(s " \n Compilation using Scala $compiler failed: \n $output" )
514+ fail()
515+
516+ reporter
517+
503518 protected def compileFromTasty (flags0 : TestFlags , suppressErrors : Boolean , targetDir : JFile ): TestReporter = {
504519 val tastyOutput = new JFile (targetDir.getPath + " _from-tasty" )
505520 tastyOutput.mkdir()
@@ -1371,4 +1386,26 @@ object ParallelTesting {
13711386
13721387 def isTastyFile (f : JFile ): Boolean =
13731388 f.getName.endsWith(" .tasty" )
1389+
1390+ def getCompiler (version : String ): JFile =
1391+ val patch = trueVersions(version)
1392+ val dir = cache.resolve(s " scala3- ${patch}" ).toFile
1393+ if dir.exists then
1394+ dir
1395+ else
1396+ import scala .sys .process ._
1397+ val zipPath = cache.resolve(s " scala3- $patch.zip " )
1398+ (URL (s " https://github.com/lampepfl/dotty/releases/download/ $patch/scala3- $patch.zip " ) #>> zipPath.toFile #&& s " unzip $zipPath -d $cache" ).!!
1399+ dir
1400+
1401+
1402+ private val trueVersions = Map (
1403+ " 3.0" -> " 3.0.2" ,
1404+ " 3.1" -> " 3.1.0"
1405+ )
1406+
1407+ private lazy val cache =
1408+ val dir = Files .createTempDirectory(" dotty.tests" )
1409+ // dir.toFile.deleteOnExit()
1410+ dir
13741411}
0 commit comments