Skip to content

Commit cc50729

Browse files
committed
Merge pull request #587 from vsalvis/vsalvis-partest-run
Less verbose partest
2 parents 4f27848 + adfe78d commit cc50729

File tree

5 files changed

+127
-78
lines changed

5 files changed

+127
-78
lines changed

project/Build.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ object DottyBuild extends Build {
118118

119119
("-DpartestParentID=" + pid) :: tuning ::: agentOptions ::: travis_build ::: fullpath
120120
}
121-
) ++ addCommandAlias("partest", ";test:compile;lockPartestFile;test:test;runPartestRunner")
121+
) ++ addCommandAlias("partest", ";test:compile;lockPartestFile;test:test;runPartestRunner") ++
122+
addCommandAlias("partest-only", ";test:compile;lockPartestFile;test:test-only dotc.tests;runPartestRunner")
122123

123124
lazy val dotty = Project(id = "dotty", base = file("."), settings = defaults)
124125

test/dotty/partest/DPConfig.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ object DPConfig {
1818
lazy val testDirs = {
1919
val root = new File(testRoot)
2020
val dirs = if (!root.exists) Array.empty[String] else root.listFiles.filter(_.isDirectory).map(_.getName)
21-
if (dirs.length > 0)
22-
println(s"Partest found generated source directories in $testRoot: " + dirs.mkString(", "))
23-
else
21+
if (dirs.isEmpty)
2422
throw new Exception("Partest did not detect any generated sources")
2523
dirs
2624
}

test/dotty/partest/DPConsoleRunner.scala

Lines changed: 81 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import scala.tools.partest._
99
import scala.tools.partest.nest._
1010
import scala.util.matching.Regex
1111
import tools.nsc.io.{ File => NSCFile }
12-
import java.io.File
12+
import java.io.{ File, PrintStream, FileOutputStream }
1313
import java.net.URLClassLoader
1414

1515
/** Runs dotty partest from the Console, discovering test sources in
@@ -25,7 +25,7 @@ object DPConsoleRunner {
2525
val (jarList, otherArgs) = args.toList.partition(jarFinder.findFirstIn(_).isDefined)
2626
val (extraJars, moreArgs) = jarList match {
2727
case Nil => sys.error("Error: DPConsoleRunner needs \"-dottyJars <jarCount> <jars>*\".")
28-
case jarFinder(nr, jarString) :: Nil =>
28+
case jarFinder(nr, jarString) :: Nil =>
2929
val jars = jarString.split(" ").toList
3030
val count = nr.toInt
3131
if (jars.length < count)
@@ -39,13 +39,13 @@ object DPConsoleRunner {
3939

4040
// console runner has a suite runner which creates a test runner for each test
4141
class DPConsoleRunner(args: String, extraJars: List[String]) extends ConsoleRunner(args) {
42-
println("ConsoleRunner options: " + args)
4342

4443
override val suiteRunner = new DPSuiteRunner (
4544
testSourcePath = optSourcePath getOrElse DPConfig.testRoot,
4645
fileManager = new DottyFileManager(extraJars),
4746
updateCheck = optUpdateCheck,
48-
failed = optFailed)
47+
failed = optFailed,
48+
consoleArgs = args)
4949

5050
override def run = {}
5151
def runPartest = super.run
@@ -62,9 +62,10 @@ class DPSuiteRunner(testSourcePath: String, // relative path, like "files", or "
6262
fileManager: DottyFileManager,
6363
updateCheck: Boolean,
6464
failed: Boolean,
65+
consoleArgs: String,
6566
javaCmdPath: String = PartestDefaults.javaCmd,
6667
javacCmdPath: String = PartestDefaults.javacCmd,
67-
scalacExtraArgs: Seq[String] = Seq.empty)
68+
scalacExtraArgs: Seq[String] = Seq.empty)
6869
extends SuiteRunner(testSourcePath, fileManager, updateCheck, failed, javaCmdPath, javacCmdPath, scalacExtraArgs) {
6970

7071
if (!DPConfig.runTestsInParallel)
@@ -76,41 +77,52 @@ extends SuiteRunner(testSourcePath, fileManager, updateCheck, failed, javaCmdPat
7677
override def banner: String = {
7778
s"""|Welcome to Partest for Dotty! Partest version: ${Properties.versionNumberString}
7879
|Compiler under test: dotty.tools.dotc.Bench or dotty.tools.dotc.Main
79-
|Test root: ${PathSettings.srcDir}${File.separator}
80+
|Generated test sources: ${PathSettings.srcDir}${File.separator}
8081
|Test directories: ${DPConfig.testDirs.toList.mkString(", ")}
82+
|Debugging: failed tests have compiler output in test-kind.clog, run output in test-kind.log, class files in test-kind.obj
8183
|Parallel: ${DPConfig.runTestsInParallel}
84+
|Options: (use partest --help for usage information) ${consoleArgs}
8285
""".stripMargin
8386
}
8487

85-
// override to provide DPTestRunner
88+
// override for DPTestRunner and redirecting compilation output to test.clog
8689
override def runTest(testFile: File): TestState = {
8790
val runner = new DPTestRunner(testFile, this)
8891

89-
// when option "--failed" is provided execute test only if log
90-
// is present (which means it failed before)
9192
val state =
92-
if (failed && !runner.logFile.canRead)
93-
runner.genPass()
94-
else {
95-
val (state, _) =
96-
try timed(runner.run())
97-
catch {
98-
case t: Throwable => throw new RuntimeException(s"Error running $testFile", t)
99-
}
100-
NestUI.reportTest(state)
101-
runner.cleanup()
102-
state
93+
try {
94+
// IO redirection is messy, there are no concurrency guarantees.
95+
// Parts of test output might end up in the wrong file or get lost.
96+
Console.out.flush
97+
Console.err.flush
98+
val clog = runner.cLogFile
99+
val stream = new PrintStream(new FileOutputStream(clog.jfile), true)
100+
val result = Console.withOut(stream)({ Console.withErr(stream)({
101+
val res = runner.run()
102+
Console.err.flush
103+
Console.out.flush
104+
res
105+
})})
106+
result match {
107+
// Append compiler output to transcript if compilation failed,
108+
// printed with --verbose option
109+
case TestState.Fail(f, r@"compilation failed", transcript) =>
110+
TestState.Fail(f, r, transcript ++ clog.fileLines.dropWhile(_ == ""))
111+
case res => res
112+
}
113+
} catch {
114+
case t: Throwable => throw new RuntimeException(s"Error running $testFile", t)
103115
}
116+
NestUI.reportTest(state)
117+
runner.cleanup()
118+
104119
onFinishTest(testFile, state)
105120
}
106-
107-
// override val fileManager = new DottyFileManager(testClassLoader)
108-
// sbt package generates a dotty compiler jar, currently
109-
// ".../git/dotty/target/scala-2.11/dotty_2.11-0.1-SNAPSHOT.jar"
110-
// but it doesn't seem to be used anywhere
111121
}
112122

113123
class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runner(testFile, suiteRunner) {
124+
val cLogFile = SFile(logFile).changeExtension("clog")
125+
114126
// override to provide DottyCompiler
115127
override def newCompiler = new dotty.partest.DPDirectCompiler(this)
116128

@@ -146,18 +158,18 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn
146158
def nerrIsOk(reason: String) = {
147159
val nerrFinder = """compilation failed with (\d+) errors""".r
148160
reason match {
149-
case nerrFinder(found) =>
161+
case nerrFinder(found) =>
150162
SFile(FileOps(testFile) changeExtension "nerr").safeSlurp match {
151163
case Some(exp) if (exp != found) => CompFailedButWrongNErr(exp, found)
152164
case _ => CompFailed
153165
}
154166
case _ => CompFailed
155167
}
156168
}
157-
169+
158170
// we keep the partest semantics where only one round needs to fail
159171
// compilation, not all
160-
val compFailingRounds = compilationRounds(testFile).map({round =>
172+
val compFailingRounds = compilationRounds(testFile).map({round =>
161173
val ok = round.isOk
162174
setLastState(if (ok) genPass else genFail("compilation failed"))
163175
(round.result, ok)
@@ -173,14 +185,14 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn
173185
if (failureStates.exists({ case CompFailed => true; case _ => false })) {
174186
true
175187
} else {
176-
val existsNerr = failureStates.exists({
188+
val existsNerr = failureStates.exists({
177189
case CompFailedButWrongNErr(exp, found) => nextTestActionFailing(s"wrong number of compilation errors, expected: $exp, found: $found"); true
178190
case _ => false
179191
})
180192
if (existsNerr) {
181-
false
193+
false
182194
} else {
183-
val existsDiff = failureStates.exists({
195+
val existsDiff = failureStates.exists({
184196
case CompFailedButWrongDiff() => nextTestActionFailing(s"output differs"); true
185197
case _ => false
186198
})
@@ -193,6 +205,38 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn
193205
}
194206
}
195207

208+
// override to change check file updating to original file, not generated
209+
override def diffIsOk: Boolean = {
210+
// always normalize the log first
211+
normalizeLog()
212+
val diff = currentDiff
213+
// if diff is not empty, is update needed?
214+
val updating: Option[Boolean] = (
215+
if (diff == "") None
216+
else Some(suiteRunner.updateCheck)
217+
)
218+
pushTranscript(s"diff $logFile $checkFile")
219+
nextTestAction(updating) {
220+
case Some(true) =>
221+
val origCheck = SFile(checkFile.changeExtension("checksrc").fileLines(1))
222+
NestUI.echo("Updating original checkfile " + origCheck)
223+
origCheck writeAll file2String(logFile)
224+
genUpdated()
225+
case Some(false) =>
226+
// Get a word-highlighted diff from git if we can find it
227+
val bestDiff = if (updating.isEmpty) "" else {
228+
if (checkFile.canRead)
229+
gitDiff(logFile, checkFile) getOrElse {
230+
s"diff $logFile $checkFile\n$diff"
231+
}
232+
else diff
233+
}
234+
pushTranscript(bestDiff)
235+
genFail("output differs")
236+
case None => genPass() // redundant default case
237+
} getOrElse true
238+
}
239+
196240
// override because Dotty currently doesn't handle separate compilation well,
197241
// so we ignore groups (tests suffixed with _1 and _2)
198242
override def groupedFiles(sources: List[File]): List[List[File]] = {
@@ -217,4 +261,10 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn
217261
// override to add dotty and scala jars to classpath
218262
override def extraClasspath = suiteRunner.fileManager.asInstanceOf[DottyFileManager].extraJarList ::: super.extraClasspath
219263

264+
// override to keep class files if failed and delete clog if ok
265+
override def cleanup = if (lastState.isOk) {
266+
logFile.delete
267+
cLogFile.delete
268+
Directory(outDir).deleteRecursively
269+
}
220270
}

test/partest

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
11
#!/usr/bin/env bash
2-
# partest error message references partest script to update check files, but
3-
# doesn't work for dotty because we don't know where tests came from.
2+
# partest error message references partest script to update check files
43

5-
if [ $1='--update-check' ];
6-
then
7-
echo """ERROR: Since dotty partest runs on generated files, please update the check
8-
files in the original location (run tests) or update the expected error count
9-
(neg tests) in the test file."
10-
else
11-
echo "This script doesn't launch partest, please use sbt partest instead."
12-
fi
4+
exec sbt "partest-only $*"

0 commit comments

Comments
 (0)