@@ -43,9 +43,9 @@ abstract class CompilerTest {
43
43
val defaultOutputDir : String
44
44
45
45
/** 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
49
49
50
50
val generatePartestFiles = {
51
51
/* Because we fork in test, the JVM in which this JUnit test runs has a
@@ -68,70 +68,80 @@ abstract class CompilerTest {
68
68
val logFile = if (! generatePartestFiles) None else Some (CompilerTest .init)
69
69
70
70
/** 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 = {
72
72
if (generatePartestFiles)
73
73
log(" WARNING: compileLine will always run with JUnit, no partest files generated." )
74
- compileArgs(cmdLine.split(" \n " ), xerrors )
74
+ compileArgs(cmdLine.split(" \n " ), Nil )
75
75
}
76
76
77
77
/** Compiles the given code file.
78
78
*
79
79
* @param prefix the parent directory (including separator at the end)
80
80
* @param fileName the filename, by default without extension
81
81
* @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.
84
82
* @param extension the file extension, .scala by default
85
83
* @param defaultOptions more arguments to the compiler
86
84
*/
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 )
89
86
(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)) {
91
90
if (runTest)
92
91
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 )
94
93
} else {
95
- val kind = testKind(prefix, xerrors, runTest)
94
+ val kind = testKind(prefix, runTest)
96
95
log(s " generating partest files for test file: $prefix$fileName$extension of kind $kind" )
97
96
98
97
val sourceFile = new JFile (prefix + fileName + extension)
99
98
if (sourceFile.exists) {
100
99
val firstDest = SFile (DPConfig .testRoot + JFile .separator + kind + JFile .separator + fileName + extension)
100
+ val xerrors = expErrors.map(_.totalErrors).sum
101
101
computeDestAndCopyFiles(sourceFile, firstDest, kind, args ++ defaultOptions, xerrors.toString)
102
102
} else {
103
103
throw new java.io.FileNotFoundException (s " Unable to locate test file $prefix$fileName" )
104
104
}
105
105
}
106
106
}
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
+ }
110
111
111
112
/** Compiles the code files in the given directory together. If args starts
112
113
* 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 )
114
115
(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 = {
118
117
val dir = Directory (prefix + dirName)
119
118
val (files, normArgs) = args match {
120
119
case " -deep" :: args1 => (dir.deepFiles, args1)
121
120
case _ => (dir.files, args)
122
121
}
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)
125
131
} else {
126
132
val (sourceDir, flags, deep) = args match {
127
133
case " -deep" :: args1 => (flattenDir(prefix, dirName), args1 ++ defaultOptions, " deep" )
128
134
case _ => (new JFile (prefix + dirName), args ++ defaultOptions, " shallow" )
129
135
}
130
- val kind = testKind(prefix, xerrors, runTest)
136
+ val kind = testKind(prefix, runTest)
131
137
log(s " generating partest files for test directory ( $deep): $prefix$dirName of kind $kind" )
132
138
133
139
if (sourceDir.exists) {
134
140
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
135
145
computeDestAndCopyFiles(sourceDir, firstDest, kind, flags, xerrors.toString)
136
146
if (deep == " deep" )
137
147
Directory (sourceDir).deleteRecursively
@@ -140,67 +150,73 @@ abstract class CompilerTest {
140
150
}
141
151
}
142
152
}
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 )
144
154
(implicit defaultOptions : List [String ]): Unit =
145
- compileDir(prefix, dirName, args, xerrors, true )
155
+ compileDir(prefix, dirName, args, true )
146
156
147
157
/** Compiles each source in the directory path separately by calling
148
158
* 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 = {
151
161
val dir = Directory (path)
152
162
val fileNames = dir.files.toArray.map(_.jfile.getName).filter(name => (name endsWith " .scala" ) || (name endsWith " .java" ))
153
163
for (name <- fileNames) {
154
164
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)
160
166
}
167
+ if (compileSubDirs)
168
+ for (subdir <- dir.dirs) {
169
+ if (verbose) log(s " testing $subdir" )
170
+ compileDir(path, subdir.jfile.getName, args, runTest)
171
+ }
161
172
}
162
173
def runFiles (path : String , args : List [String ] = Nil , verbose : Boolean = true )
163
174
(implicit defaultOptions : List [String ]): Unit =
164
175
compileFiles(path, args, verbose, true )
165
176
166
177
/** 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 )
168
179
(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)
171
183
} else {
172
184
val destDir = Directory (DPConfig .testRoot + JFile .separator + testName)
173
185
files.foreach({ file =>
174
186
val jfile = new JFile (file)
175
187
recCopyFiles(jfile, destDir / jfile.getName)
176
188
})
177
- compileDir(DPConfig .testRoot + JFile .separator, testName, args, xerrors )
189
+ compileDir(DPConfig .testRoot + JFile .separator, testName, args)
178
190
destDir.deleteRecursively
179
191
}
180
192
}
181
193
182
194
// ========== HELPERS =============
183
195
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 ])
185
203
(implicit defaultOptions : List [String ]): Unit = {
186
204
val allArgs = args ++ defaultOptions
187
205
val processor = if (allArgs.exists(_.startsWith(" #" ))) Bench else Main
188
206
val reporter = processor.process(allArgs)
189
207
190
208
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)
193
214
// NEG TEST
194
215
if (xerrors > 0 ) {
195
216
val errorLines = reporter.allErrors.map(_.pos)
196
217
// reporter didn't record as many errors as its errorCount says
197
218
assert(errorLines.length == nerrors, s " Not enough errors recorded. " )
198
219
199
- val allFiles = (allArgs filter {
200
- arg => ! arg.startsWith(" -" ) && (arg.endsWith(" .scala" ) || arg.endsWith(" .java" ))
201
- }).toList
202
- val expectedErrorsPerFile = allFiles.map(getErrors(_))
203
-
204
220
// Some compiler errors have an associated source position. Each error
205
221
// needs to correspond to a "// error" marker on that line in the source
206
222
// file and vice versa.
@@ -233,7 +249,9 @@ abstract class CompilerTest {
233
249
/** Captures the number of nopos-errors in the given file and the number of
234
250
* errors with a position, represented as a tuple of source line and number
235
251
* 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
+ }
237
255
238
256
/** Extracts the errors expected for the given neg test file. */
239
257
def getErrors (fileName : String ): ErrorsInFile = {
@@ -319,9 +337,9 @@ abstract class CompilerTest {
319
337
private val extensionsToCopy = scala.collection.immutable.HashSet (" scala" , " java" )
320
338
321
339
/** 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 ) = {
323
341
if (runTest) " run"
324
- else if (xerrors > 0 ) " neg"
342
+ else if (isNegTest(prefixDir) ) " neg"
325
343
else if (prefixDir.endsWith(" run" + JFile .separator)) {
326
344
log(" WARNING: test is being run as pos test despite being in a run directory. " +
327
345
" Use runFile/runDir instead of compileFile/compileDir to do a run test" )
0 commit comments