1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
|
import sbt._
import java.io.File
import java.net.URLClassLoader
import TestSet.{filter}
class TestSet(val SType: TestSetType.Value, val kind: String, val description: String, val files: Array[File]){
/**
* @param a list of file that we want to know wheter they are members of the test set or not
* @return two lists : the first contains files that are member of the test set, the second contains the files that aren't
*/
def splitContent(f: List[File]):(List[File], List[File]) = {
f.partition((f: File) => files.elements.exists((e: File) => f == e))
}
}
object TestSet {
def apply(sType: TestSetType.Value, kind: String, description: String, files: PathFinder)= new TestSet(sType, kind, description, filter(files))
def filter(p: PathFinder): Array[File] =( p --- p **(HiddenFileFilter || GlobFilter("*.obj")||GlobFilter("*.log"))).getFiles.toArray
}
object TestSetType extends Enumeration {
val Std, Continuations = Value
}
class TestConfiguration(val library: Path, val classpath: Iterable[Path], val testRoot: Path,
val tests: List[TestSet], val junitReportDir: Option[Path]){
}
trait PartestRunner {
self: BasicLayer with Packer =>
import Partest.runTest
import TestSetType._
lazy val testRoot = projectRoot / "test"
lazy val testFiles = testRoot / "files" ##
lazy val testLibs = testFiles / "lib"
lazy val posFilesTest = TestSet(Std,"pos", "Compiling files that are expected to build", testFiles / "pos" * ("*.scala" || DirectoryFilter))
lazy val negFilesTest = TestSet(Std,"neg", "Compiling files that are expected to fail", testFiles / "neg" * ("*.scala" || DirectoryFilter))
lazy val runFilesTest = TestSet(Std,"run", "Compiling and running files", testFiles / "run" * ("*.scala" || DirectoryFilter))
lazy val jvmFilesTest = TestSet(Std,"jvm", "Compiling and running files", testFiles / "jvm" *("*.scala" || DirectoryFilter))
lazy val resFilesTest = TestSet(Std,"res", "Running resident compiler scenarii", testFiles / "res" * ("*.res"))
lazy val buildmanagerFilesTest = TestSet(Std,"buildmanager", "Running Build Manager scenarii", testFiles / "buildmanager" * DirectoryFilter)
// lazy val scalacheckFilesTest = TestSet(Std,"scalacheck", "Running scalacheck tests", testFiles / "scalacheck" * ("*.scala" || DirectoryFilter))
lazy val scriptFilesTest = TestSet(Std,"script", "Running script files", testFiles / "script" * ("*.scala"))
lazy val shootoutFilesTest = TestSet(Std,"shootout", "Running shootout tests", testFiles / "shootout" * ("*.scala"))
lazy val scalapFilesTest = TestSet(Std,"scalap", "Running scalap tests", testFiles / "scalap" * ("*.scala"))
lazy val specializedFilesTest = TestSet(Std,"specialized", "Running specialized tests", testFiles / "specialized" * ("*.scala"))
// lazy val negContinuationTest = TestSet(Continuations,"neg", "Compiling continuations files that are expected to fail", testFiles / "continuations-neg" * ("*.scala" || DirectoryFilter))
// lazy val runContinuationTest = TestSet(Continuations,"run", "Compiling and running continuations files", testFiles / "continuations-run" ** ("*.scala" ))
//
// lazy val continuationScalaOpts = (
// "-Xpluginsdir " +
// continuationPluginConfig.packagingConfig.jarDestination.asFile.getParent +
// " -Xplugin-require:continuations -P:continuations:enable"
// )
lazy val testSuiteFiles: List[TestSet] = List(
posFilesTest, negFilesTest, runFilesTest, jvmFilesTest, resFilesTest,
buildmanagerFilesTest,
//scalacheckFilesTest,
shootoutFilesTest, scalapFilesTest,
specializedFilesTest
)
lazy val testSuiteContinuation: List[TestSet] = Nil // List(negContinuationTest, runContinuationTest)
private lazy val filesTestMap: Map[String, TestSet] =
Map(testSuiteFiles.map(s => (s.kind,s) ):_*)
// + (("continuations-neg",negContinuationTest),("continuations-run", runContinuationTest))
private lazy val partestOptions = List("-failed")
private lazy val partestCompletionList: Seq[String] = {
val len = testFiles.asFile.toString.length + 1
filesTestMap.keys.toList ++ partestOptions ++
(filesTestMap.values.toList flatMap (_.files) map (_.toString take len))
}
private def runPartest(tests: List[TestSet], scalacOpts: Option[String], failedOnly: Boolean) = {
val config = new TestConfiguration(
outputLibraryJar,
(outputLibraryJar +++ outputCompilerJar +++ outputPartestJar +++ outputScalapJar +++ antJar +++ jlineJar +++ (testLibs * "*.jar")).get,
testRoot,
tests,
None
)
val javaHome = Path.fromFile(new File(System.getProperty("java.home")))
val java = Some(javaHome / "bin" / "java" asFile)
val javac = Some(javaHome / "bin" / "javac" asFile)
val timeout = Some("2400000")
val loader = info.launcher.topLoader
log.debug("Ready to run tests")
if (tests.isEmpty) {
log.debug("Empty test list")
None
}
else runTest(
loader, config, java, javac,
scalacOpts, timeout, true, true,
failedOnly, true, isDebug, log
)
}
def partestDebugProp =
if (isDebug) List("-Dpartest.debug=true")
else Nil
lazy val externalPartest = task { args =>
task {
if (isForked) partest(args).run
else withJVMArgs(partestDebugProp ++ args: _*) {
if (forkTasks("partest")) None
else Some("Some tests failed.")
}
} dependsOn pack
} completeWith partestCompletionList
lazy val partest = task { args =>
var failedOnly = false
def setOptions(options: List[String], acc: List[String]): List[String] = options match {
case "-failed" :: xs =>
failedOnly = true
log.info("Only tests that failed previously will be run")
setOptions(xs, acc)
case x :: xs =>
setOptions(xs, x :: acc)
case _ => acc
}
def resolveSets(l: List[String], rem: List[String], acc: List[TestSet]): (List[String], List[TestSet]) = {
def searchSet(arg: String): Option[TestSet] = filesTestMap get arg
l match {
case x :: xs => searchSet(x) match {
case Some(s) => resolveSets(xs, rem, s :: acc)
case None => resolveSets(xs, x :: rem, acc)
}
case Nil => (rem, acc)
}
}
def resolveFiles(l: List[String], sets: List[TestSet]):(List[String], List[TestSet]) = {
def resolve0(filesToResolve: List[File], setsToSearchIn: List[TestSet], setAcc: List[TestSet]):(List[String], List[TestSet])= {
filesToResolve match {
case Nil => (Nil, setAcc) // If we have no files left to resolve, we can return the list of the set we have
case list => {
setsToSearchIn match {
case Nil => (list.map(_.toString), setAcc)// If we already had search all sets to find a match, we return the list of the files that where problematic and the set we have
case x :: xs => {
val (found, notFound)= x.splitContent(list)
if(!found.isEmpty){
val newSet = new TestSet(x.SType, x.kind, x.description, found.toArray)
resolve0(notFound, xs, newSet :: setAcc)
} else {
resolve0(notFound, xs, setAcc)
}
}
}
}
}
}
resolve0(l.map(Path.fromString(testFiles, _).asFile), filesTestMap.values.toList, sets)
}
val keys = setOptions(args.toList, Nil)
if (keys.isEmpty) {
task { runPartest(testSuiteFiles, None, failedOnly) }
}
else {
val (fileNames, sets) = resolveSets(keys, Nil, Nil)
val (notFound, allSets) = resolveFiles(fileNames, sets)
if (!notFound.isEmpty)
log.info("Don't know what to do with : \n"+notFound.mkString("\n"))
task { runPartest(allSets, None, failedOnly) }
}
// if (keys.length == 0) task {
// runPartest(testSuiteFiles, None, failedOnly) orElse {
// runPartest(testSuiteContinuation, None, failedOnly)
// } // this is the case where there were only config options, we will run the standard test suite
// }
// else {
// val (fileNames, sets) = resolveSets(keys, Nil, Nil)
// val (notFound, allSets) = resolveFiles(fileNames, sets)
// if (!notFound.isEmpty)
// log.info("Don't know what to do with : \n"+notFound.mkString("\n"))
//
// val (std, continuations) = allSets partition (_.SType == TestSetType.Std)
// task {
// runPartest(std, None, failedOnly) orElse {
// runPartest(continuations, Some(continuationScalaOpts), failedOnly)
// }
// }
// }
}.completeWith(partestCompletionList)
}
object Partest {
def runTest(
parentLoader: ClassLoader,
config: TestConfiguration,
javacmd: Option[File],
javaccmd: Option[File],
scalacOpts: Option[String],
timeout: Option[String],
showDiff: Boolean,
showLog: Boolean,
runFailed: Boolean,
errorOnFailed: Boolean,
debug: Boolean,
log: Logger
): Option[String] = {
if (debug)
log.setLevel(Level.Debug)
if (config.classpath.isEmpty)
return Some("The classpath is empty")
log.debug("Classpath is "+ config.classpath)
val classloader = new URLClassLoader(
Array(config.classpath.toSeq.map(_.asURL):_*),
ClassLoader.getSystemClassLoader.getParent
)
val runner: AnyRef =
classloader.loadClass("scala.tools.partest.nest.SBTRunner").newInstance().asInstanceOf[AnyRef]
val fileManager: AnyRef =
runner.getClass.getMethod("fileManager", Array[Class[_]](): _*).invoke(runner, Array[Object](): _*)
val runMethod =
runner.getClass.getMethod("reflectiveRunTestsForFiles", Array(classOf[Array[File]], classOf[String]): _*)
def runTestsForFiles(kindFiles: Array[File], kind: String) = {
val result = runMethod.invoke(runner, Array(kindFiles, kind): _*).asInstanceOf[java.util.HashMap[String, Int]]
scala.collection.jcl.Conversions.convertMap(result)
}
def setFileManagerBooleanProperty(name: String, value: Boolean) {
log.debug("Setting partest property :"+name+" to :"+value)
val setMethod =
fileManager.getClass.getMethod(name+"_$eq", Array(classOf[Boolean]): _*)
setMethod.invoke(fileManager, Array(java.lang.Boolean.valueOf(value)).asInstanceOf[Array[Object]]: _*)
}
def setFileManagerStringProperty(name: String, value: String) {
log.debug("Setting partest property :"+name+" to :"+value)
val setMethod =
fileManager.getClass.getMethod(name+"_$eq", Array(classOf[String]): _*)
setMethod.invoke(fileManager, Array(value).asInstanceOf[Array[Object]]: _*)
}
// System.setProperty("partest.srcdir", "files")
setFileManagerBooleanProperty("showDiff", showDiff)
setFileManagerBooleanProperty("showLog", showLog)
setFileManagerBooleanProperty("failed", runFailed)
if (!javacmd.isEmpty)
setFileManagerStringProperty("JAVACMD", javacmd.get.getAbsolutePath)
if (!javaccmd.isEmpty)
setFileManagerStringProperty("JAVAC_CMD", "javac")
setFileManagerStringProperty("CLASSPATH", (config.classpath.map(_.absolutePath).mkString(File.pathSeparator)))
setFileManagerStringProperty("LATEST_LIB", config.library.absolutePath)
setFileManagerStringProperty("SCALAC_OPTS", scalacOpts getOrElse "")
if (!timeout.isEmpty)
setFileManagerStringProperty("timeout", timeout.get)
type TFSet = (Array[File], String, String)
val testFileSets = config.tests
def resultsToStatistics(results: Iterable[(_, Int)]): (Int, Int) = {
val (files, failures) = results map (_._2 == 0) partition (_ == true)
def count(i: Iterable[_]): Int ={
var c = 0
for (elem <-i) yield {
c = c+1
}
c
}
(count(files), count(failures))
}
def runSet(set: TestSet): (Int, Int, Iterable[String]) = {
val (files, name, msg) = (set.files, set.kind, set.description)
log.debug("["+name+"] "+ msg+files.mkString(", files :\n","\n",""))
if (files.isEmpty) {
log.debug("No files !")
(0, 0, List())
}
else {
log.info(name +" : "+ msg)
val results: Iterable[(String, Int)] = runTestsForFiles(files, name)
val (succs, fails) = resultsToStatistics(results)
val failed: Iterable[String] = results.filter( _._2!=0) map(_ match {
case (path, 1) => path + " [FAILED]"
case (path, 2) => path + " [TIMOUT]"
})
val r =(succs, fails, failed)
config.junitReportDir match {
case Some(d) => {
val report = testReport(name, results, succs, fails)
scala.xml.XML.save(d/name+".xml", report)
}
case None =>
}
r
}
}
val _results = testFileSets map runSet
val allSuccesses = _results.map (_._1).foldLeft(0)( _ + _ )
val allFailures = _results.map (_._2).foldLeft(0)( _ + _ )
val allFailedPaths = _results flatMap (_._3)
def f(msg: String): Option[String] =
if (errorOnFailed && allFailures > 0) {
Some(msg)
}
else {
log.info(msg)
None
}
def s = if (allFailures > 1) "s" else ""
val msg =
if (allFailures > 0) "Test suite finished with %d case%s failing.\n".format(allFailures, s)+ allFailedPaths.mkString("\n")
else if (allSuccesses == 0) "There were no tests to run."
else "Test suite finished with no failures."
f(msg)
}
private def oneResult(res: (String, Int)) =
<testcase name ={res._1}>{
res._2 match {
case 0 => scala.xml.NodeSeq.Empty
case 1 => <failure message="Test failed"/>
case 2 => <failure message="Test timed out"/>
}
}</testcase>
private def testReport(kind: String, results: Iterable[(String, Int)], succs: Int, fails: Int) =
<testsuite name ={kind} tests ={(succs + fails).toString} failures ={fails.toString}>
<properties/>
{
results.map(oneResult(_))
}
</testsuite>
}
|