Skip to content

Commit bf808b3

Browse files
authored
Add an option to only rerun tests that have failed (#16263)
- testCompilation supports running only failed tests with --failed argument fixes #3798
2 parents d84007c + 6dfc668 commit bf808b3

16 files changed

+82
-23
lines changed

compiler/test/dotc/comptest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ object comptest extends ParallelTesting {
1212
def isInteractive = true
1313
def testFilter = Nil
1414
def updateCheckFiles: Boolean = false
15+
def failedTests = None
1516

1617
val posDir = "./tests/pos/"
1718
val negDir = "./tests/neg/"

compiler/test/dotty/Properties.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ object Properties {
1313
prop == null || prop == "TRUE"
1414
}
1515

16+
/** If property is unset or FALSE we consider it `false` */
17+
private def propIsTrue(name: String): Boolean =
18+
sys.props.getOrElse(name, "FALSE") == "TRUE"
19+
1620
/** Are we running on the CI? */
1721
val isRunByCI: Boolean = sys.env.isDefinedAt("DOTTY_CI_RUN")
1822
|| sys.env.isDefinedAt("DRONE") // TODO remove this when we drop Drone
@@ -30,9 +34,11 @@ object Properties {
3034
*/
3135
val testsFilter: List[String] = sys.props.get("dotty.tests.filter").fold(Nil)(_.split(',').toList)
3236

37+
/** Run only failed tests */
38+
val rerunFailed: Boolean = propIsTrue("dotty.tests.rerunFailed")
39+
3340
/** Tests should override the checkfiles with the current output */
34-
val testsUpdateCheckfile: Boolean =
35-
sys.props.getOrElse("dotty.tests.updateCheckfiles", "FALSE") == "TRUE"
41+
val testsUpdateCheckfile: Boolean = propIsTrue("dotty.tests.updateCheckfiles")
3642

3743
/** When set, the run tests are only compiled - not run, a warning will be
3844
* issued

compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import org.junit.Assume._
1010
import org.junit.experimental.categories.Category
1111

1212
import scala.concurrent.duration._
13+
import reporting.TestReporter
1314
import vulpix._
1415

1516
import java.nio.file._
@@ -214,6 +215,7 @@ object BootstrappedOnlyCompilationTests extends ParallelTesting {
214215
def isInteractive = SummaryReport.isInteractive
215216
def testFilter = Properties.testsFilter
216217
def updateCheckFiles: Boolean = Properties.testsUpdateCheckfile
218+
def failedTests = TestReporter.lastRunFailedTests
217219

218220
implicit val summaryReport: SummaryReporting = new SummaryReport
219221
@AfterClass def tearDown(): Unit = {

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import scala.jdk.CollectionConverters._
1616
import scala.util.matching.Regex
1717
import scala.concurrent.duration._
1818
import TestSources.sources
19+
import reporting.TestReporter
1920
import vulpix._
2021

2122
class CompilationTests {
@@ -317,6 +318,7 @@ object CompilationTests extends ParallelTesting {
317318
def isInteractive = SummaryReport.isInteractive
318319
def testFilter = Properties.testsFilter
319320
def updateCheckFiles: Boolean = Properties.testsUpdateCheckfile
321+
def failedTests = TestReporter.lastRunFailedTests
320322

321323
implicit val summaryReport: SummaryReporting = new SummaryReport
322324
@AfterClass def tearDown(): Unit = {

compiler/test/dotty/tools/dotc/FromTastyTests.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package dotc
55
import scala.language.unsafeNulls
66

77
import org.junit.{AfterClass, Test}
8+
import reporting.TestReporter
89
import vulpix._
910

1011
import java.io.{File => JFile}
@@ -48,6 +49,7 @@ object FromTastyTests extends ParallelTesting {
4849
def isInteractive = SummaryReport.isInteractive
4950
def testFilter = Properties.testsFilter
5051
def updateCheckFiles: Boolean = Properties.testsUpdateCheckfile
52+
def failedTests = TestReporter.lastRunFailedTests
5153

5254
implicit val summaryReport: SummaryReporting = new SummaryReport
5355
@AfterClass def tearDown(): Unit = {

compiler/test/dotty/tools/dotc/IdempotencyTests.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import org.junit.{AfterClass, Test}
1212
import org.junit.experimental.categories.Category
1313

1414
import scala.concurrent.duration._
15+
import reporting.TestReporter
1516
import vulpix._
1617

1718

@@ -76,6 +77,7 @@ object IdempotencyTests extends ParallelTesting {
7677
def isInteractive = SummaryReport.isInteractive
7778
def testFilter = Properties.testsFilter
7879
def updateCheckFiles: Boolean = Properties.testsUpdateCheckfile
80+
def failedTests = TestReporter.lastRunFailedTests
7981

8082
implicit val summaryReport: SummaryReporting = new SummaryReport
8183
@AfterClass def tearDown(): Unit = {

compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import scala.util.matching.Regex
1717
import scala.concurrent.duration._
1818
import TestSources.sources
1919
import vulpix._
20+
import reporting.TestReporter
2021

2122
class TastyBootstrapTests {
2223
import ParallelTesting._
@@ -114,6 +115,7 @@ object TastyBootstrapTests extends ParallelTesting {
114115
def isInteractive = SummaryReport.isInteractive
115116
def testFilter = Properties.testsFilter
116117
def updateCheckFiles: Boolean = Properties.testsUpdateCheckfile
118+
def failedTests = TestReporter.lastRunFailedTests
117119

118120
implicit val summaryReport: SummaryReporting = new SummaryReport
119121
@AfterClass def tearDown(): Unit = {

compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import org.junit.Test
44
import org.junit.AfterClass
55
import org.junit.Assert.*
66
import org.junit.experimental.categories.Category
7-
87
import dotty.{BootstrappedOnlyTests, Properties}
98
import dotty.tools.vulpix.*
109
import dotty.tools.vulpix.TestConfiguration.*
1110
import dotty.tools.dotc.Main
11+
import dotty.tools.dotc.reporting.TestReporter
1212

13-
import java.nio.file.{Files, FileSystems, Path, Paths, StandardCopyOption}
13+
import java.nio.file.{FileSystems, Files, Path, Paths, StandardCopyOption}
1414
import scala.jdk.CollectionConverters.*
1515
import scala.util.Properties.userDir
1616
import scala.language.unsafeNulls
@@ -85,6 +85,7 @@ object CoverageTests extends ParallelTesting:
8585
def testFilter = Properties.testsFilter
8686
def isInteractive = SummaryReport.isInteractive
8787
def updateCheckFiles = Properties.testsUpdateCheckfile
88+
def failedTests = TestReporter.lastRunFailedTests
8889

8990
given summaryReport: SummaryReporting = SummaryReport()
9091
@AfterClass def tearDown(): Unit =

compiler/test/dotty/tools/dotc/reporting/TestReporter.scala

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@ package dotc
33
package reporting
44

55
import scala.language.unsafeNulls
6-
7-
import java.io.{ PrintStream, PrintWriter, File => JFile, FileOutputStream, StringWriter }
6+
import java.io.{BufferedReader, FileInputStream, FileOutputStream, FileReader, PrintStream, PrintWriter, StringReader, StringWriter, File as JFile}
87
import java.text.SimpleDateFormat
98
import java.util.Date
10-
import core.Decorators._
9+
import core.Decorators.*
1110

1211
import scala.collection.mutable
13-
12+
import scala.jdk.CollectionConverters.*
1413
import util.SourcePosition
15-
import core.Contexts._
16-
import Diagnostic._
17-
import interfaces.Diagnostic.{ ERROR, WARNING }
14+
import core.Contexts.*
15+
import Diagnostic.*
16+
import dotty.Properties
17+
import interfaces.Diagnostic.{ERROR, WARNING}
18+
19+
import scala.io.Codec
1820

1921
class TestReporter protected (outWriter: PrintWriter, filePrintln: String => Unit, logLevel: Int)
2022
extends Reporter with UniqueMessagePositions with HideNonSensicalMessages with MessageRendering {
@@ -84,17 +86,23 @@ extends Reporter with UniqueMessagePositions with HideNonSensicalMessages with M
8486
}
8587

8688
object TestReporter {
89+
private val testLogsDirName: String = "testlogs"
90+
private val failedTestsFileName: String = "last-failed.log"
91+
private val failedTestsFile: JFile = new JFile(s"$testLogsDirName/$failedTestsFileName")
92+
8793
private var outFile: JFile = _
8894
private var logWriter: PrintWriter = _
95+
private var failedTestsWriter: PrintWriter = _
8996

9097
private def initLog() = if (logWriter eq null) {
9198
val date = new Date
9299
val df0 = new SimpleDateFormat("yyyy-MM-dd")
93100
val df1 = new SimpleDateFormat("yyyy-MM-dd-'T'HH-mm-ss")
94-
val folder = s"testlogs/tests-${df0.format(date)}"
101+
val folder = s"$testLogsDirName/tests-${df0.format(date)}"
95102
new JFile(folder).mkdirs()
96103
outFile = new JFile(s"$folder/tests-${df1.format(date)}.log")
97104
logWriter = new PrintWriter(new FileOutputStream(outFile, true))
105+
failedTestsWriter = new PrintWriter(new FileOutputStream(failedTestsFile, false))
98106
}
99107

100108
def logPrintln(str: String) = {
@@ -144,4 +152,16 @@ object TestReporter {
144152
}
145153
rep
146154
}
155+
156+
def lastRunFailedTests: Option[List[String]] =
157+
Option.when(
158+
Properties.rerunFailed &&
159+
failedTestsFile.exists() &&
160+
failedTestsFile.isFile
161+
)(java.nio.file.Files.readAllLines(failedTestsFile.toPath).asScala.toList)
162+
163+
def writeFailedTests(tests: List[String]): Unit =
164+
initLog()
165+
tests.foreach(failed => failedTestsWriter.println(failed))
166+
failedTestsWriter.flush()
147167
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package dotty.tools.vulpix
2+
3+
case class FailedTestInfo(title: String, extra: String)

0 commit comments

Comments
 (0)