Skip to content

Commit 4abc122

Browse files
committed
Update-check option for partest, added "do not edit" header
Jenkins uses US-ASCII charset, added tool to detect when invalid chars are used and fixed files.
1 parent 395e505 commit 4abc122

File tree

5 files changed

+105
-45
lines changed

5 files changed

+105
-45
lines changed

src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Standard-Section: "ASTs" TopLevelStat*
7070
7171
Term = Path
7272
Application
73-
IDENT NameRef Type // used when idents type is not a TermRef
73+
IDENT NameRef Type // used when ident's type is not a TermRef
7474
SELECT possiblySigned_NameRef qual_Term
7575
NEW cls_Type
7676
SUPER Length this_Term mixinTrait_Type?
@@ -169,8 +169,8 @@ Standard-Section: "ASTs" TopLevelStat*
169169
LABEL // method generated as a label
170170
FIELDaccessor // getter or setter
171171
CASEaccessor // getter for case class param
172-
COVARIANT // type param marked “+”
173-
CONTRAVARIANT // type param marked “-”
172+
COVARIANT // type param marked "+"
173+
CONTRAVARIANT // type param marked "-"
174174
SCALA2X // Imported from Scala2.x
175175
DEFAULTparameterized // Method with default params
176176
INSUPERCALL // defined in the argument of a constructor supercall

src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
680680
}
681681
}
682682

683-
/** implements the run-time aspects of (§8.2) (typedPattern has already done the necessary type transformations)
683+
/** implements the run-time aspects of (P8.2) (typedPattern has already done the necessary type transformations)
684684
*
685685
* Type patterns consist of types, type variables, and wildcards. A type pattern T is of one of the following forms:
686686
- A reference to a class C, p.C, or T#C.
@@ -699,7 +699,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
699699
700700
- A parameterized type pattern T[a1,...,an], where the ai are type variable patterns or wildcards _.
701701
This type pattern matches all values which match T for some arbitrary instantiation of the type variables and wildcards.
702-
The bounds or alias type of these type variable are determined as described in (§8.3).
702+
The bounds or alias type of these type variable are determined as described in (P8.3).
703703
704704
- A parameterized type pattern scala.Array[T1], where T1 is a type pattern. // TODO
705705
This type pattern matches any non-null instance of type scala.Array[U1], where U1 is a type matched by T1.
@@ -1284,28 +1284,28 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
12841284

12851285
// Some notes from the specification
12861286

1287-
/*A constructor pattern is of the form c(p1, ..., pn) where n 0.
1287+
/*A constructor pattern is of the form c(p1, ..., pn) where n >= 0.
12881288
It consists of a stable identifier c, followed by element patterns p1, ..., pn.
1289-
The constructor c is a simple or qualified name which denotes a case class (§5.3.2).
1289+
The constructor c is a simple or qualified name which denotes a case class (P5.3.2).
12901290
12911291
If the case class is monomorphic, then it must conform to the expected type of the pattern,
1292-
and the formal parameter types of xs primary constructor (§5.3) are taken as the expected
1292+
and the formal parameter types of x's primary constructor (P5.3) are taken as the expected
12931293
types of the element patterns p1, ..., pn.
12941294
12951295
If the case class is polymorphic, then its type parameters are instantiated so that the
12961296
instantiation of c conforms to the expected type of the pattern.
1297-
The instantiated formal parameter types of cs primary constructor are then taken as the
1297+
The instantiated formal parameter types of c's primary constructor are then taken as the
12981298
expected types of the component patterns p1, ..., pn.
12991299
13001300
The pattern matches all objects created from constructor invocations c(v1, ..., vn)
13011301
where each element pattern pi matches the corresponding value vi .
1302-
A special case arises when cs formal parameter types end in a repeated parameter.
1303-
This is further discussed in (§8.1.9).
1302+
A special case arises when c's formal parameter types end in a repeated parameter.
1303+
This is further discussed in (P8.1.9).
13041304
**/
13051305

13061306
/* A typed pattern x : T consists of a pattern variable x and a type pattern T.
13071307
The type of x is the type pattern T, where each type variable and wildcard is replaced by a fresh, unknown type.
1308-
This pattern matches any value matched by the type pattern T (§8.2); it binds the variable name to that value.
1308+
This pattern matches any value matched by the type pattern T (P8.2); it binds the variable name to that value.
13091309
*/
13101310

13111311
/* A pattern binder x@p consists of a pattern variable x and a pattern p.
@@ -1319,8 +1319,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
13191319
A literal pattern L matches any value that is equal (in terms of ==) to the literal L.
13201320
The type of L must conform to the expected type of the pattern.
13211321
1322-
8.1.5 Stable Identifier Patterns (a stable identifier r (see §3.1))
1323-
The pattern matches any value v such that r == v (§12.1).
1322+
8.1.5 Stable Identifier Patterns (a stable identifier r (see P3.1))
1323+
The pattern matches any value v such that r == v (P12.1).
13241324
The type of r must conform to the expected type of the pattern.
13251325
*/
13261326

test/dotty/partest/DPConsoleRunner.scala

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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,6 +62,7 @@ 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,
6768
scalacExtraArgs: Seq[String] = Seq.empty)
@@ -76,9 +77,11 @@ 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

@@ -92,12 +95,13 @@ extends SuiteRunner(testSourcePath, fileManager, updateCheck, failed, javaCmdPat
9295
// Parts of test output might end up in the wrong file or get lost.
9396
Console.out.flush
9497
Console.err.flush
95-
val clog = SFile(runner.logFile).changeExtension("clog")
98+
val clog = runner.cLogFile
9699
val stream = new PrintStream(new FileOutputStream(clog.jfile), true)
97100
val result = Console.withOut(stream)({ Console.withErr(stream)({
98-
runner.run()
101+
val res = runner.run()
99102
Console.err.flush
100103
Console.out.flush
104+
res
101105
})})
102106
result match {
103107
// Append compiler output to transcript if compilation failed,
@@ -117,6 +121,8 @@ extends SuiteRunner(testSourcePath, fileManager, updateCheck, failed, javaCmdPat
117121
}
118122

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

@@ -199,6 +205,38 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn
199205
}
200206
}
201207

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+
202240
// override because Dotty currently doesn't handle separate compilation well,
203241
// so we ignore groups (tests suffixed with _1 and _2)
204242
override def groupedFiles(sources: List[File]): List[List[File]] = {
@@ -223,4 +261,10 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn
223261
// override to add dotty and scala jars to classpath
224262
override def extraClasspath = suiteRunner.fileManager.asInstanceOf[DottyFileManager].extraJarList ::: super.extraClasspath
225263

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+
}
226270
}

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 $*"

test/test/CompilerTest.scala

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ abstract class CompilerTest extends DottyTest {
101101
}
102102
}
103103
}
104-
def runFile(prefix: String, fileName: String, args: List[String] = Nil, xerrors: Int = 0,
104+
def runFile(prefix: String, fileName: String, args: List[String] = Nil, xerrors: Int = 0,
105105
extension: String = ".scala")(implicit defaultOptions: List[String]): Unit =
106106
compileFile(prefix, fileName, args, xerrors, extension, true)
107107

@@ -131,7 +131,7 @@ abstract class CompilerTest extends DottyTest {
131131
val firstDest = Directory(DPConfig.testRoot + JFile.separator + kind + JFile.separator + dirName)
132132
computeDestAndCopyFiles(sourceDir, firstDest, kind, flags, xerrors.toString)
133133
if (deep == "deep")
134-
deleteDir(sourceDir)
134+
Directory(sourceDir).deleteRecursively
135135
} else {
136136
throw new java.io.FileNotFoundException(s"Unable to locate test dir $prefix$dirName")
137137
}
@@ -172,7 +172,7 @@ abstract class CompilerTest extends DottyTest {
172172
recCopyFiles(jfile, destDir / jfile.getName)
173173
})
174174
compileDir(DPConfig.testRoot + JFile.separator, testName, args, xerrors)
175-
deleteDir(destDir.jfile)
175+
destDir.deleteRecursively
176176
}
177177
}
178178

@@ -186,14 +186,14 @@ abstract class CompilerTest extends DottyTest {
186186
}
187187

188188
// In particular, don't copy flags from scalac tests
189-
private val extensionsToCopy = scala.collection.immutable.HashSet("scala", "java", "check")
189+
private val extensionsToCopy = scala.collection.immutable.HashSet("scala", "java")
190190

191191
/** Determines what kind of test to run. */
192192
private def testKind(prefixDir: String, xerrors: Int, runTest: Boolean) = {
193193
if (runTest) "run"
194194
else if (xerrors > 0) "neg"
195195
else if (prefixDir.endsWith("run" + JFile.separator)) {
196-
log("WARNING: test is being run as pos test despite being in a run directory. " +
196+
log("WARNING: test is being run as pos test despite being in a run directory. " +
197197
"Use runFile/runDir instead of compileFile/compileDir to do a run test")
198198
"pos"
199199
} else "pos"
@@ -239,10 +239,12 @@ abstract class CompilerTest extends DottyTest {
239239
if (nerr != "0")
240240
dest.changeExtension("nerr").createFile(true).writeAll(nerr)
241241
sourceFile.changeExtension("check").ifFile({ check =>
242-
if (kind == "run")
242+
if (kind == "run") {
243243
FileManager.copyFile(check.jfile, dest.changeExtension("check").jfile)
244-
else
244+
dest.changeExtension("checksrc").createFile(true).writeAll("check file generated from source:\n" + check.toString)
245+
} else {
245246
log(s"WARNING: ignoring $check for test kind $kind")
247+
}
246248
})
247249

248250
}
@@ -253,7 +255,18 @@ abstract class CompilerTest extends DottyTest {
253255
processFileDir(sourceFile, { sf =>
254256
if (extensionsToCopy.contains(sf.extension)) {
255257
dest.parent.jfile.mkdirs
256-
FileManager.copyFile(sourceFile.jfile, dest.jfile)
258+
val contents = try sf.slurp catch {
259+
case e: java.nio.charset.MalformedInputException =>
260+
println("ERROR: illegal character detected for file " + sf + " (charset " + sf.creationCodec + ")")
261+
checkEncoding(sf)
262+
throw e
263+
}
264+
dest.toFile.writeAll("/* ==========================================\n",
265+
" * ========= AUTOMATICALLY GENERATED ========\n",
266+
" * ========= DO NOT EDIT THIS FILE ==========\n",
267+
" * ==========================================\n",
268+
" * Original: " + sf.toString + " */\n\n",
269+
contents)
257270
} else {
258271
log(s"WARNING: ignoring $sf")
259272
}
@@ -326,16 +339,27 @@ abstract class CompilerTest extends DottyTest {
326339
destDir.jfile
327340
}
328341

329-
/** Recursively deletes directories (and files). */
330-
private def deleteDir(dir: JFile): Unit = {
331-
val children = dir.listFiles
332-
if (children != null)
333-
children.foreach(deleteDir(_))
334-
dir.delete
335-
}
336-
337342
/** Write either to console (JUnit) or log file (partest). */
338343
private def log(msg: String) = logFile.map(_.appendAll(msg + "\n")).getOrElse(println(msg))
344+
345+
/** Jenkins uses different Character encoding, check if this is the problem. */
346+
private def checkEncoding(sf: SFile) = {
347+
val reader1 = sf.reader(scala.io.Codec.UTF8) // local machine
348+
val reader2 = sf.reader(scala.io.Codec(java.nio.charset.Charset.forName("US-ASCII"))) // jenkins
349+
try {
350+
var read1, read2, count, diffcount = 0
351+
while ((read1 > -1 || read2 > -1) && diffcount < 30) {
352+
read1 = reader1.read(); read2 = reader2.read()
353+
count += 1
354+
if (read1 != read2) {
355+
println("difference at character " + count + ": UTF8: " + read1.toChar + ", US-ASCII (jenkins): " + read2.toChar)
356+
diffcount += 1
357+
}
358+
}
359+
} finally {
360+
reader1.close; reader2.close
361+
}
362+
}
339363
}
340364

341365
object CompilerTest extends App {

0 commit comments

Comments
 (0)