diff options
Diffstat (limited to 'project/build/Partest.scala')
-rwxr-xr-x | project/build/Partest.scala | 321 |
1 files changed, 237 insertions, 84 deletions
diff --git a/project/build/Partest.scala b/project/build/Partest.scala index b971c668d9..5a6cdc2506 100755 --- a/project/build/Partest.scala +++ b/project/build/Partest.scala @@ -1,160 +1,313 @@ -/* 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._ + + import Partest.{runTest} + import TestSetType._ + + lazy val testRoot = projectRoot / "test" - lazy val testFiles = testRoot / "files" + lazy val testFiles = testRoot / "files" ## lazy val testLibs = testFiles / "lib" - lazy val testSuite= task{ + + 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" )) + 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")) + 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 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) + lazy val testSuiteContinuation:List[TestSet]=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 = filesTestMap.keys.toList:::partestOptions:::filesTestMap.values.toList.flatMap{_.files.map(_.toString.substring(testFiles.asFile.toString.length+1))} + + 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, - (testFiles /"pos") * "*.scala", - (testFiles /"neg") * "*.scala", - (testFiles / "run") ** "*.scala", - (testFiles /"jvm") * "*.scala", - (testFiles / "res") * "*.res", - (testFiles / "buildmanager"), - Path.emptyPathFinder, - (testFiles/ "shootout") * "*.scala", - (testFiles /"scalap") ** "*.scala" - ) + (outputLibraryJar +++ outputCompilerJar +++ outputPartestJar +++ outputScalapJar +++ antJar +++ jlineJar +++ (testLibs * "*.jar")).get, + testRoot, + tests, + None + ) + val javaHome = Path.fromFile(new File(System.getProperty("java.home"))) val java = javaHome / "bin" / "java" - val javac = javaHome / "bin" / "javac" - - runTest(config,Some(java.asFile),Some(javac.asFile),None,Some("2400000"), false,true,false,true,false,log) + val javac = javaHome/"bin"/"javac" + log.debug("Ready to run tests") + if (tests.isEmpty){ + log.debug("Empty test list") + None + }else + runTest(info.launcher.topLoader,config,Some(java.asFile),Some(javac.asFile),scalacOpts,Some("2400000"), true,true,failedOnly,true,false,log) } -} + lazy val externalPartest = task {args => task { + val runner = new ExternalTaskRunner(projectRoot,this.name, "partest " + args.mkString(" "),"Some tests have failed", log) + runner.runTask + }.dependsOn(pack) + }.completeWith(partestCompletionList) -class TestConfiguration(val library:Path, val classpath:Iterable[Path], - posFiles:PathFinder,negFiles:PathFinder,runFiles:PathFinder, jvmFiles:PathFinder, - residentFiles:PathFinder,buildManagerFiles:PathFinder,scriptFiles:PathFinder, - shootoutFiles:PathFinder,scalapFiles:PathFinder){ + lazy val partest = task{ + args => + var failedOnly = false - private def getFilesAndDirs(path:PathFinder):Array[File]={ - ( path * AllPassFilter --- (path * ((new ExactFilter(".svn")) || GlobFilter("*.obj")))).getFiles.toArray - } + def setOptions(options:List[String],acc:List[String]):List[String]= options match{ + case x::xs => x match{ + case "-failed" => {failedOnly= true; log.info("Only tests that failed previously will be run"); setOptions(xs,acc)} + case _ => setOptions(xs,x::acc) + + } + case Nil => acc + } - private def getPosFiles = getFilesAndDirs(posFiles) - private def getNegFiles = getFilesAndDirs(negFiles) - private def getRunFiles = getFilesAndDirs(runFiles) - private def getJvmFiles = getFilesAndDirs(jvmFiles) - private def getResidentFiles = getFilesAndDirs(residentFiles) - private def getBuildManagerFiles = getFilesAndDirs(buildManagerFiles) - private def getScriptFiles = getFilesAndDirs(scriptFiles) - private def getShootoutFiles = getFilesAndDirs(shootoutFiles) - private def getScalapFiles = getFilesAndDirs(scalapFiles) - - lazy val testFileSets = List( - (getPosFiles, "pos", "Compiling files that are expected to build"), - (getNegFiles, "neg", "Compiling files that are expected to fail"), - (getRunFiles, "run", "Compiling and running files"), - (getJvmFiles, "jvm", "Compiling and running files"), - (getResidentFiles, "res", "Running resident compiler scenarii"), - (getBuildManagerFiles, "buildmanager", "Running Build Manager scenarii"), - (getScriptFiles, "script", "Running script files"), - (getShootoutFiles, "shootout", "Running shootout tests"), - (getScalapFiles, "scalap", "Running scalap tests") - ) + 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.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) + } -*/ -/** - * Based on scala.tools.partest.PartestTask - */ -/* -object Partest{ - - def runTest(config:TestConfiguration,javacmd:Option[File],javaccmd:Option[File],scalacOpts:Option[String],timeout:Option[String], + +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) System.setProperty("partest.debug", "true") 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):_*)) - - val antRunner: AnyRef = - classloader.loadClass("scala.tools.partest.nest.AntRunner").newInstance().asInstanceOf[AnyRef] - val antFileManager: AnyRef = - antRunner.getClass.getMethod("fileManager", Array[Class[_]](): _*).invoke(antRunner, Array[Object](): _*) + 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 = - antRunner.getClass.getMethod("reflectiveRunTestsForFiles", Array(classOf[Array[File]], classOf[String]): _*) + runner.getClass.getMethod("reflectiveRunTestsForFiles", Array(classOf[Array[File]], classOf[String]): _*) - def runTestsForFiles(kindFiles: Array[File], kind: String): (Int, Int) = { - val result = runMethod.invoke(antRunner, Array(kindFiles, kind): _*).asInstanceOf[Int] - (result >> 16, result & 0x00FF) + 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 = - antFileManager.getClass.getMethod(name+"_$eq", Array(classOf[Boolean]): _*) - setMethod.invoke(antFileManager, Array(java.lang.Boolean.valueOf(value)).asInstanceOf[Array[Object]]: _*) + 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 = - antFileManager.getClass.getMethod(name+"_$eq", Array(classOf[String]): _*) - setMethod.invoke(antFileManager, Array(value).asInstanceOf[Array[Object]]: _*) + fileManager.getClass.getMethod(name+"_$eq", Array(classOf[String]): _*) + setMethod.invoke(fileManager, Array(value).asInstanceOf[Array[Object]]: _*) } + System.setProperty("partest.srcdir",config.testRoot.absolutePath) + setFileManagerBooleanProperty("showDiff", showDiff) setFileManagerBooleanProperty("showLog", showLog) setFileManagerBooleanProperty("failed", runFailed) if (!javacmd.isEmpty) setFileManagerStringProperty("JAVACMD", javacmd.get.getAbsolutePath) if (!javaccmd.isEmpty) - setFileManagerStringProperty("JAVAC_CMD", javaccmd.get.getAbsolutePath) - setFileManagerStringProperty("CLASSPATH", config.classpath.mkString(File.pathSeparator)) + setFileManagerStringProperty("JAVAC_CMD", "javac") + setFileManagerStringProperty("CLASSPATH",(config.classpath.map(_.absolutePath).mkString(File.pathSeparator))) setFileManagerStringProperty("LATEST_LIB", config.library.absolutePath) - if (!scalacOpts.isEmpty) - setFileManagerStringProperty("SCALAC_OPTS", scalacOpts.get) + scalacOpts match { + case None => setFileManagerStringProperty("SCALAC_OPTS","") + case Some(options) => setFileManagerStringProperty("SCALAC_OPTS",options) + } if (!timeout.isEmpty) setFileManagerStringProperty("timeout", timeout.get) type TFSet = (Array[File], String, String) - val testFileSets = config.testFileSets + 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: TFSet): (Int, Int) = { - val (files, name, msg) = set - if (files.isEmpty) (0, 0) + 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(msg) - runTestsForFiles(files, name) + 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 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) + 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.".format(allFailures, s) + 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> + + +} |