@@ -43,9 +43,9 @@ abstract class CompilerTest {
4343 val defaultOutputDir : String
4444
4545 /** Override to filter out tests that should not be run by partest. */
46- def partestableFile (prefix : String , fileName : String , extension : String , args : List [String ], xerrors : Int ) = true
47- def partestableDir (prefix : String , dirName : String , args : List [String ], xerrors : Int ) = true
48- def partestableList (testName : String , files : List [String ], args : List [String ], xerrors : Int ) = true
46+ def partestableFile (prefix : String , fileName : String , extension : String , args : List [String ]) = true
47+ def partestableDir (prefix : String , dirName : String , args : List [String ]) = true
48+ def partestableList (testName : String , files : List [String ], args : List [String ]) = true
4949
5050 val generatePartestFiles = {
5151 /* Because we fork in test, the JVM in which this JUnit test runs has a
@@ -68,70 +68,80 @@ abstract class CompilerTest {
6868 val logFile = if (! generatePartestFiles) None else Some (CompilerTest .init)
6969
7070 /** Always run with JUnit. */
71- def compileLine (cmdLine : String , xerrors : Int = 0 )(implicit defaultOptions : List [String ]): Unit = {
71+ def compileLine (cmdLine : String )(implicit defaultOptions : List [String ]): Unit = {
7272 if (generatePartestFiles)
7373 log(" WARNING: compileLine will always run with JUnit, no partest files generated." )
74- compileArgs(cmdLine.split(" \n " ), xerrors )
74+ compileArgs(cmdLine.split(" \n " ), Nil )
7575 }
7676
7777 /** Compiles the given code file.
7878 *
7979 * @param prefix the parent directory (including separator at the end)
8080 * @param fileName the filename, by default without extension
8181 * @param args arguments to the compiler
82- * @param xerrors if > 0, this test is a neg test with the expected number
83- * of compiler errors. Otherwise, this is a pos test.
8482 * @param extension the file extension, .scala by default
8583 * @param defaultOptions more arguments to the compiler
8684 */
87- def compileFile (prefix : String , fileName : String , args : List [String ] = Nil , xerrors : Int = 0 ,
88- extension : String = " .scala" , runTest : Boolean = false )
85+ def compileFile (prefix : String , fileName : String , args : List [String ] = Nil , extension : String = " .scala" , runTest : Boolean = false )
8986 (implicit defaultOptions : List [String ]): Unit = {
90- if (! generatePartestFiles || ! partestableFile(prefix, fileName, extension, args ++ defaultOptions, xerrors)) {
87+ val filePath = s " $prefix$fileName$extension"
88+ val expErrors = expectedErrors(filePath)
89+ if (! generatePartestFiles || ! partestableFile(prefix, fileName, extension, args ++ defaultOptions)) {
9190 if (runTest)
9291 log(s " WARNING: run tests can only be run by partest, JUnit just verifies compilation: $prefix$fileName$extension" )
93- compileArgs((s " $prefix$fileName$extension " :: args).toArray, xerrors )
92+ compileArgs((s " $filePath " :: args).toArray, expErrors )
9493 } else {
95- val kind = testKind(prefix, xerrors, runTest)
94+ val kind = testKind(prefix, runTest)
9695 log(s " generating partest files for test file: $prefix$fileName$extension of kind $kind" )
9796
9897 val sourceFile = new JFile (prefix + fileName + extension)
9998 if (sourceFile.exists) {
10099 val firstDest = SFile (DPConfig .testRoot + JFile .separator + kind + JFile .separator + fileName + extension)
100+ val xerrors = expErrors.map(_.totalErrors).sum
101101 computeDestAndCopyFiles(sourceFile, firstDest, kind, args ++ defaultOptions, xerrors.toString)
102102 } else {
103103 throw new java.io.FileNotFoundException (s " Unable to locate test file $prefix$fileName" )
104104 }
105105 }
106106 }
107- def runFile (prefix : String , fileName : String , args : List [String ] = Nil , xerrors : Int = 0 ,
108- extension : String = " .scala" )(implicit defaultOptions : List [String ]): Unit =
109- compileFile(prefix, fileName, args, xerrors, extension, true )
107+ def runFile (prefix : String , fileName : String , args : List [String ] = Nil , extension : String = " .scala" )
108+ (implicit defaultOptions : List [String ]): Unit = {
109+ compileFile(prefix, fileName, args, extension, true )
110+ }
110111
111112 /** Compiles the code files in the given directory together. If args starts
112113 * with "-deep", all files in subdirectories (and so on) are included. */
113- def compileDir (prefix : String , dirName : String , args : List [String ] = Nil , xerrors : Int = 0 , runTest : Boolean = false )
114+ def compileDir (prefix : String , dirName : String , args : List [String ] = Nil , runTest : Boolean = false )
114115 (implicit defaultOptions : List [String ]): Unit = {
115- if (! generatePartestFiles || ! partestableDir(prefix, dirName, args ++ defaultOptions, xerrors)) {
116- if (runTest)
117- log(s " WARNING: run tests can only be run by partest, JUnit just verifies compilation: $prefix$dirName" )
116+ def computeFilePathsAndExpErrors = {
118117 val dir = Directory (prefix + dirName)
119118 val (files, normArgs) = args match {
120119 case " -deep" :: args1 => (dir.deepFiles, args1)
121120 case _ => (dir.files, args)
122121 }
123- val fileNames = files.toArray.map(_.toString).filter(name => (name endsWith " .scala" ) || (name endsWith " .java" ))
124- compileArgs(fileNames ++ normArgs, xerrors)
122+ val filePaths = files.toArray.map(_.toString).filter(name => (name endsWith " .scala" ) || (name endsWith " .java" ))
123+ val expErrors = expectedErrors(filePaths.toList)
124+ (filePaths, normArgs, expErrors)
125+ }
126+ if (! generatePartestFiles || ! partestableDir(prefix, dirName, args ++ defaultOptions)) {
127+ if (runTest)
128+ log(s " WARNING: run tests can only be run by partest, JUnit just verifies compilation: $prefix$dirName" )
129+ val (filePaths, normArgs, expErrors) = computeFilePathsAndExpErrors
130+ compileArgs(filePaths ++ normArgs, expErrors)
125131 } else {
126132 val (sourceDir, flags, deep) = args match {
127133 case " -deep" :: args1 => (flattenDir(prefix, dirName), args1 ++ defaultOptions, " deep" )
128134 case _ => (new JFile (prefix + dirName), args ++ defaultOptions, " shallow" )
129135 }
130- val kind = testKind(prefix, xerrors, runTest)
136+ val kind = testKind(prefix, runTest)
131137 log(s " generating partest files for test directory ( $deep): $prefix$dirName of kind $kind" )
132138
133139 if (sourceDir.exists) {
134140 val firstDest = Directory (DPConfig .testRoot + JFile .separator + kind + JFile .separator + dirName)
141+ val xerrors = if (isNegTest(prefix)) {
142+ val (_, _, expErrors) = computeFilePathsAndExpErrors
143+ expErrors.map(_.totalErrors).sum
144+ } else 0
135145 computeDestAndCopyFiles(sourceDir, firstDest, kind, flags, xerrors.toString)
136146 if (deep == " deep" )
137147 Directory (sourceDir).deleteRecursively
@@ -140,67 +150,73 @@ abstract class CompilerTest {
140150 }
141151 }
142152 }
143- def runDir (prefix : String , dirName : String , args : List [String ] = Nil , xerrors : Int = 0 )
153+ def runDir (prefix : String , dirName : String , args : List [String ] = Nil )
144154 (implicit defaultOptions : List [String ]): Unit =
145- compileDir(prefix, dirName, args, xerrors, true )
155+ compileDir(prefix, dirName, args, true )
146156
147157 /** Compiles each source in the directory path separately by calling
148158 * compileFile resp. compileDir. */
149- def compileFiles (path : String , args : List [String ] = Nil , verbose : Boolean = true , runTest : Boolean = false )
150- (implicit defaultOptions : List [String ]): Unit = {
159+ def compileFiles (path : String , args : List [String ] = Nil , verbose : Boolean = true , runTest : Boolean = false ,
160+ compileSubDirs : Boolean = true ) (implicit defaultOptions : List [String ]): Unit = {
151161 val dir = Directory (path)
152162 val fileNames = dir.files.toArray.map(_.jfile.getName).filter(name => (name endsWith " .scala" ) || (name endsWith " .java" ))
153163 for (name <- fileNames) {
154164 if (verbose) log(s " testing $path$name" )
155- compileFile(path, name, args, 0 , " " , runTest)
156- }
157- for (subdir <- dir.dirs) {
158- if (verbose) log(s " testing $subdir" )
159- compileDir(path, subdir.jfile.getName, args, 0 , runTest)
165+ compileFile(path, name, args, " " , runTest)
160166 }
167+ if (compileSubDirs)
168+ for (subdir <- dir.dirs) {
169+ if (verbose) log(s " testing $subdir" )
170+ compileDir(path, subdir.jfile.getName, args, runTest)
171+ }
161172 }
162173 def runFiles (path : String , args : List [String ] = Nil , verbose : Boolean = true )
163174 (implicit defaultOptions : List [String ]): Unit =
164175 compileFiles(path, args, verbose, true )
165176
166177 /** Compiles the given list of code files. */
167- def compileList (testName : String , files : List [String ], args : List [String ] = Nil , xerrors : Int = 0 )
178+ def compileList (testName : String , files : List [String ], args : List [String ] = Nil )
168179 (implicit defaultOptions : List [String ]): Unit = {
169- if (! generatePartestFiles || ! partestableList(testName, files, args ++ defaultOptions, xerrors)) {
170- compileArgs((files ++ args).toArray, xerrors)
180+ if (! generatePartestFiles || ! partestableList(testName, files, args ++ defaultOptions)) {
181+ val expErrors = expectedErrors(files)
182+ compileArgs((files ++ args).toArray, expErrors)
171183 } else {
172184 val destDir = Directory (DPConfig .testRoot + JFile .separator + testName)
173185 files.foreach({ file =>
174186 val jfile = new JFile (file)
175187 recCopyFiles(jfile, destDir / jfile.getName)
176188 })
177- compileDir(DPConfig .testRoot + JFile .separator, testName, args, xerrors )
189+ compileDir(DPConfig .testRoot + JFile .separator, testName, args)
178190 destDir.deleteRecursively
179191 }
180192 }
181193
182194 // ========== HELPERS =============
183195
184- private def compileArgs (args : Array [String ], xerrors : Int = 0 )
196+ private def expectedErrors (filePaths : List [String ]): List [ErrorsInFile ] = if (filePaths.exists(isNegTest(_))) filePaths.map(getErrors(_)) else Nil
197+
198+ private def expectedErrors (filePath : String ): List [ErrorsInFile ] = expectedErrors(List (filePath))
199+
200+ private def isNegTest (testPath : String ) = testPath.contains(JFile .separator + " neg" + JFile .separator)
201+
202+ private def compileArgs (args : Array [String ], expectedErrorsPerFile : List [ErrorsInFile ])
185203 (implicit defaultOptions : List [String ]): Unit = {
186204 val allArgs = args ++ defaultOptions
187205 val processor = if (allArgs.exists(_.startsWith(" #" ))) Bench else Main
188206 val reporter = processor.process(allArgs)
189207
190208 val nerrors = reporter.errorCount
191- assert(nerrors == xerrors, s " Wrong # of errors. Expected: $xerrors, found: $nerrors" )
192-
209+ val xerrors = (expectedErrorsPerFile map {_.totalErrors}).sum
210+ assert(nerrors == xerrors,
211+ s """ Wrong # of errors. Expected: $xerrors, found: $nerrors
212+ |Files with expected errors: ${expectedErrorsPerFile.collect{ case er if er.totalErrors > 0 => er.fileName} }
213+ """ .stripMargin)
193214 // NEG TEST
194215 if (xerrors > 0 ) {
195216 val errorLines = reporter.allErrors.map(_.pos)
196217 // reporter didn't record as many errors as its errorCount says
197218 assert(errorLines.length == nerrors, s " Not enough errors recorded. " )
198219
199- val allFiles = (allArgs filter {
200- arg => ! arg.startsWith(" -" ) && (arg.endsWith(" .scala" ) || arg.endsWith(" .java" ))
201- }).toList
202- val expectedErrorsPerFile = allFiles.map(getErrors(_))
203-
204220 // Some compiler errors have an associated source position. Each error
205221 // needs to correspond to a "// error" marker on that line in the source
206222 // file and vice versa.
@@ -233,7 +249,9 @@ abstract class CompilerTest {
233249 /** Captures the number of nopos-errors in the given file and the number of
234250 * errors with a position, represented as a tuple of source line and number
235251 * of errors on that line. */
236- case class ErrorsInFile (fileName : String , noposErrorNr : Int , posErrorLinesToNr : List [(Int , Int )])
252+ case class ErrorsInFile (fileName : String , noposErrorNr : Int , posErrorLinesToNr : List [(Int , Int )]) {
253+ def totalErrors = noposErrorNr + posErrorLinesToNr.map(_._2).sum
254+ }
237255
238256 /** Extracts the errors expected for the given neg test file. */
239257 def getErrors (fileName : String ): ErrorsInFile = {
@@ -319,9 +337,9 @@ abstract class CompilerTest {
319337 private val extensionsToCopy = scala.collection.immutable.HashSet (" scala" , " java" )
320338
321339 /** Determines what kind of test to run. */
322- private def testKind (prefixDir : String , xerrors : Int , runTest : Boolean ) = {
340+ private def testKind (prefixDir : String , runTest : Boolean ) = {
323341 if (runTest) " run"
324- else if (xerrors > 0 ) " neg"
342+ else if (isNegTest(prefixDir) ) " neg"
325343 else if (prefixDir.endsWith(" run" + JFile .separator)) {
326344 log(" WARNING: test is being run as pos test despite being in a run directory. " +
327345 " Use runFile/runDir instead of compileFile/compileDir to do a run test" )
0 commit comments