summaryrefslogtreecommitdiff
path: root/src/partest
diff options
context:
space:
mode:
authormichelou <michelou@epfl.ch>2007-09-11 15:41:12 +0000
committermichelou <michelou@epfl.ch>2007-09-11 15:41:12 +0000
commit385b899a0cb04337525b32c201e1dbabb5b1bef9 (patch)
treee056f154572164dc6b55ce4b0c40caf5c0490d98 /src/partest
parentcf471e6091fa5c2d74ddbafde7da08f3ca64f416 (diff)
downloadscala-385b899a0cb04337525b32c201e1dbabb5b1bef9.tar.gz
scala-385b899a0cb04337525b32c201e1dbabb5b1bef9.tar.bz2
scala-385b899a0cb04337525b32c201e1dbabb5b1bef9.zip
partest integration (alpha)
Diffstat (limited to 'src/partest')
-rw-r--r--src/partest/scala/tools/partest/MasterActor.scala163
-rw-r--r--src/partest/scala/tools/partest/TestRunner.scala197
-rw-r--r--src/partest/scala/tools/partest/WorkerActor.scala307
-rw-r--r--src/partest/scala/tools/partest/utils/PrintMgr.scala51
4 files changed, 718 insertions, 0 deletions
diff --git a/src/partest/scala/tools/partest/MasterActor.scala b/src/partest/scala/tools/partest/MasterActor.scala
new file mode 100644
index 0000000000..77924a73b5
--- /dev/null
+++ b/src/partest/scala/tools/partest/MasterActor.scala
@@ -0,0 +1,163 @@
+/* __ *\
+** ________ ___ / / ___ Scala Parallel Testing **
+** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: $
+
+package scala.tools.partest
+
+import java.awt.event.{ActionEvent, ActionListener}
+import java.io.{File, FileOutputStream, PrintStream}
+import javax.swing.Timer
+
+import scala.actors.Actor
+import scala.tools.nsc.Settings
+
+import utils.PrintMgr._
+
+/**
+ * @author Adriaan Moors, Thomas Hofer
+ * @version 1.0
+ */
+class MasterActor(testDir: File, out: PrintStream) extends Actor {
+ import scala.actors.Actor._
+
+ private final val testPathLen = testDir.getPath.length
+
+ private final val WIDTH = 56
+ private final val TIMEOUT = 1360000
+
+ private var counter = 0
+ private var failed = 0
+
+ private var conservative = false
+
+ private val globalSettings = new Settings(x => ())
+
+ //private var numOfActors = Math.min(4, Math.max(Integer.parseInt(System.getProperty("actors.maxPoolSize")),
+ private val numOfActors = 4
+ //println("Starting with " + numOfActors + " actors...")
+
+ private var workers = (for (i <- 0 until numOfActors) yield (new WorkerActor(this, new Settings(x => ()), new ExtConsoleReporter(globalSettings)), i)).toList
+
+ private var workingOn: List[(Int, Test)] = List()
+
+ private var timers = (for (i <- 0 until numOfActors) yield createTimer(workers(i)._1)).toList
+
+ private var testsToRun: List[Test] = List()
+
+ private var failedTests: List[Test] = List()
+
+ private def createTimer(worker: WorkerActor): Timer = {
+ val action: ActionListener = new ActionListener {
+ def actionPerformed(event: ActionEvent) {
+ val workerID = workers.find((_)._1 == worker) match {
+ case Some(x) => x
+ case None => (null, -1)
+ }
+ val test = workingOn.find((_)._1 == workerID._2) match {
+ case Some(x) => x._2
+ case None => null
+ }
+ println("Actor " + workerID._1 + " failed, while testing " + test.file.getPath)
+ failedTests.find(_ == test) match {
+ case Some(x) => //...
+ case None => testFailed(workerID, test)
+ }
+
+ }
+ }
+
+ new Timer(TIMEOUT, action)
+ }
+
+ private def testFailed(actor: (WorkerActor, Int), test: Test) = {
+ failedTests = test :: failedTests
+ var newWorker = new WorkerActor(this, new Settings(x => ()), new ExtConsoleReporter(globalSettings))
+ timers(actor._2).stop
+ timers = timers.take(actor._2 - 1) ::: List(createTimer(newWorker)) ::: timers.drop(actor._2)
+ newWorker.start
+ //println("Started actor " + newWorker)
+ workers = (newWorker, actor._2) :: workers.remove(_ == actor)
+
+ timers(actor._2).start
+ newWorker ! (test, true, conservative)
+ }
+
+ private def hasNextTest = !testsToRun.isEmpty
+
+ private def nextTest(): Test = {
+ val test = testsToRun.head
+ testsToRun = testsToRun.tail
+ test
+ }
+
+ def act() {
+ loop {
+ react {
+ case (test: Test) =>
+ testsToRun = test :: testsToRun
+
+ case ("start", conservative: Boolean) =>
+ this.conservative = conservative
+ workers foreach ((x) => {
+ if (hasNextTest) {
+ x._1.start
+ val test = nextTest()
+ // TODO Change here should be x._1 ! (test, false, conservative)
+ x._1 ! (test, false, conservative)
+ timers(x._2).start
+ workingOn = (x._2, test) :: workingOn
+ }
+ })
+
+ case (kind: String, succeeded: Boolean, file: File) =>
+ val workerID = workers.find((_)._1 == sender) match {
+ case Some(x) => x
+ case None => (null, -1)
+ }
+ if (workerID._2 != -1) {
+ workingOn = workingOn.remove((_)._1 == workerID._2)
+ if (hasNextTest) {
+ val test = nextTest()
+ // TODO Change here should be x._1 ! (test, false, conservative)
+ sender ! (test, false, conservative)
+ timers(workerID._2).restart
+ workingOn = (workerID._2, test) :: workingOn
+ } else {
+ sender ! false
+ timers(workerID._2).stop
+ }
+ } else {
+ //Houston, we got a problem...
+ }
+ counter += 1
+ printOutline("testing: ")
+ val name = file.getPath.substring(testPathLen)
+ print("[...]" + name + List.toString(List.make(WIDTH - name.length, ' ')) + "[")
+ if (succeeded) {
+ printSuccess(" OK ")
+ } else {
+ failed += 1
+ printFailure("FAILED")
+ }
+ println("]")
+ if (workingOn.isEmpty) {
+ out.println(failed)
+ out.println(counter - failed)
+ out.close
+ println
+ exit
+ }
+
+ case msg =>
+ println(msg)
+ }
+ }
+ }
+
+}
diff --git a/src/partest/scala/tools/partest/TestRunner.scala b/src/partest/scala/tools/partest/TestRunner.scala
new file mode 100644
index 0000000000..1fa0680a9a
--- /dev/null
+++ b/src/partest/scala/tools/partest/TestRunner.scala
@@ -0,0 +1,197 @@
+/* __ *\
+** ________ ___ / / ___ Scala Parallel Testing **
+** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: $
+
+package scala.tools.partest
+
+import java.awt.event.{ActionEvent, ActionListener}
+import java.io.{File, FilenameFilter, FileOutputStream, PrintStream}
+
+import scala.tools.nsc.Settings
+
+import utils.PrintMgr
+import utils.PrintMgr._
+
+/**
+ * @author Adriaan Moors, Thomas Hofer
+ * @version 1.0
+ */
+class Test(val kind: String, val file: File) {
+ val dir = file.getParent
+ protected def baseSettings(settings: Settings) {
+ settings.classpath.value = dir
+ settings.outdir.value = {
+ var outDir = new File(dir, fileBase + "-" + kind + ".obj")
+ outDir.mkdir
+ outDir.toString
+ }
+ settings.deprecation.value = true
+ settings.nowarnings.value = false
+ settings.encoding.value = "iso-8859-1"
+ }
+ def defineSettings(settings: Settings) {
+ baseSettings(settings)
+ }
+ private def basename(name: String): String = {
+ val inx = name.lastIndexOf(".")
+ if (inx < 0) name else name.substring(0, inx)
+ }
+ val fileBase: String = basename(file.getName)
+ val logFile: File = new File(dir, fileBase + "-" + kind + ".log")
+ val checkFile: File = {
+ var chkFile = new File(dir, fileBase + ".check")
+ if (chkFile.isFile) {
+ chkFile
+ } else {
+ new File(dir, fileBase + "-" + kind + ".check")
+ }
+ }
+}
+
+case class PosTest(override val file: File) extends Test("pos", file)
+case class NegTest(override val file: File) extends Test("neg", file)
+case class JVMTest(override val file: File) extends Test("jvm", file) {
+ override def defineSettings(settings: Settings) {
+ baseSettings(settings)
+ settings.target.value =
+ if (dir endsWith "jvm5") "jvm-1.5" else "jvm-1.4"
+ settings.classpath.value = System.getProperty("JVMEXTCP")
+ TestRunner.printVerbose("CLASSPATH="+settings.classpath.value +"\n")
+ }
+}
+case class ShootoutTest(override val file: File) extends Test("shootout", file) {
+ override def defineSettings(settings: Settings) {
+ baseSettings(settings)
+ settings.classpath.value = System.getProperty("JVMEXTCP")
+ }
+}
+
+/**
+ * @author Stephane Micheloud
+ * @version 1.0
+ */
+object TestRunner {
+ private var posCheck = false
+ private var negCheck = false
+ private var jvmCheck = false
+ private var runCheck = false
+ private var shootoutCheck = false
+
+ private var conservative = false
+ private var verbose = false
+
+ private var testDir: File = _
+ private val con = new PrintStream(Console.out)
+ private var out = con
+
+ private def go {
+ val master = new MasterActor(testDir, out)
+ val filter = new FilenameFilter {
+ def accept(dir: File, name: String): Boolean = name endsWith ".scala"
+ }
+ def getFiles(kind: String): List[File] = {
+ val kindDir = "files" + File.separator + kind
+ val dir = new File(testDir, kindDir)
+ if (dir.isDirectory) dir.listFiles(filter).toList
+ else {
+ println("Directory \"" + testDir.getPath + File.separator + kindDir + "\" not found")
+ Nil
+ }
+ }
+
+ master.start
+
+ if (posCheck) {
+ printOutline("Testing compiler (on files whose compilation should succeed)\n")
+ for (file <- getFiles("pos")) master ! PosTest(file)
+ }
+ if (negCheck) {
+ printOutline("Testing compiler (on files whose compilation should fail)\n")
+ for (file <- getFiles("neg")) master ! NegTest(file)
+ }
+ if (jvmCheck) {
+ printOutline("Testing JVM backend\n")
+ for (file <- getFiles("jvm")) master ! JVMTest(file)
+ for (file <- getFiles("run")) master ! JVMTest(file)
+ for (file <- getFiles("jvm5")) master ! JVMTest(file)
+ } else if (runCheck) {
+ printOutline("Testing JVM backend\n")
+ for (file <- getFiles("run")) master ! JVMTest(file)
+ }
+ if (shootoutCheck) {
+ printOutline("Testing shootout benchmarks\n")
+ for (file <- getFiles("shootout")) master! ShootoutTest(file)
+ }
+
+ master ! ("start", conservative)
+ }
+
+ private def printUsage {
+ println("Usage: TestRunner [<options>] <testdir> [<resfile>]")
+ println(" --pos ...")
+ println(" --neg ...")
+ println(" --jvm ...")
+ println(" --run ...")
+ println(" --shootout ...")
+ println(" --conservative ...")
+ println(" --verbose display progress information")
+ println
+ println("Send bugs to <scala@listes.epfl.ch>")
+ exit(1)
+ }
+
+ final def printVerbose(msg: String) {
+ if (verbose) {
+ printOutline("debug : ")
+ println(msg)
+ }
+ }
+
+ def main(args: Array[String]) {
+ if (args.length == 0)
+ printUsage
+ else {
+ for (arg <- args) {
+ arg match {
+ case "--pos" => posCheck = true
+ case "--neg" => negCheck = true
+ case "--jvm" => jvmCheck = true
+ case "--run" => runCheck = true
+ case "--shootout" => shootoutCheck = true
+ case "--conservative" => conservative = true
+ case "--verbose" => verbose = true
+ case _ =>
+ if (testDir eq null) {
+ val dir = new File(arg)
+ if (dir.isDirectory) testDir = dir
+ else {
+ println("Directory \"" + arg + "\" not found")
+ exit(1)
+ }
+ } else if (out eq con) {
+ val file = new File(arg)
+ if (file.isFile || file.createNewFile)
+ out = new PrintStream(file)
+ else {
+ println("Result file \"" + arg + "\" not found")
+ exit(1)
+ }
+ } else
+ printUsage
+ }
+ }
+ if (!(posCheck | negCheck | jvmCheck | runCheck | shootoutCheck)) {
+ posCheck = true
+ negCheck = true
+ }
+ initialization(PrintMgr.MANY)
+ go
+ }
+ }
+}
diff --git a/src/partest/scala/tools/partest/WorkerActor.scala b/src/partest/scala/tools/partest/WorkerActor.scala
new file mode 100644
index 0000000000..4b8bd3b4d0
--- /dev/null
+++ b/src/partest/scala/tools/partest/WorkerActor.scala
@@ -0,0 +1,307 @@
+/* __ *\
+** ________ ___ / / ___ Scala Parallel Testing **
+** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: $
+
+package scala.tools.partest
+
+import java.io.{BufferedInputStream, BufferedReader, File, FileReader,
+ FileInputStream, FileOutputStream, InputStreamReader,
+ PrintStream, PrintWriter}
+import java.net.URL
+
+import scala.actors.Actor
+import scala.tools.nsc.{Global, ObjectRunner, Settings}
+import scala.tools.nsc.reporters.{Reporter, AbstractReporter, ConsoleReporter}
+
+
+class ExtConsoleReporter(override val settings: Settings, reader: BufferedReader, var writer: PrintWriter) extends ConsoleReporter(settings, reader, writer) {
+ def this(settings: Settings) = {
+ this(settings, Console.in, new PrintWriter("/dev/null"))
+ }
+ def hasWarnings: Boolean = WARNING.count != 0
+}
+
+class ExtGlobal(settings: Settings, reporter: Reporter) extends Global(settings, reporter) {
+ override def inform(msg: String) {}
+}
+
+/**
+ * @author Adriaan Moors, Thomas Hofer
+ * @version 1.0
+ */
+class WorkerActor(val master: MasterActor, val settings: Settings, var reporter: ExtConsoleReporter) extends Actor {
+ import scala.actors.Actor._
+
+ def newGlobal: ExtGlobal = new ExtGlobal(settings, reporter)
+
+ def newGlobal(log: File): ExtGlobal = {
+ reporter = new ExtConsoleReporter(new Settings(x => ()), Console.in, new PrintWriter(log))
+ reporter.shortname = true
+ newGlobal
+ }
+
+ private def dirDelete(dir: File) {
+ if (dir.isDirectory) {
+ for (file <- dir.list) dirDelete(new File(dir, file))
+ }
+ dir.delete
+ }
+
+ def act() {
+ var compiler = newGlobal
+ val bufferSize = 1024
+ val originBuffer = new Array[Byte](bufferSize)
+ val destBuffer = new Array[Byte](bufferSize)
+ loop {
+ react {
+ case (test: Test, bypass: Boolean, conservative: Boolean) => {
+ var bypassObjectRunner = bypass
+ if (!bypassObjectRunner) {
+ // TODO check the shootout source files for "dangerous" patterns, such as: Console.read, Scheduler.impl,
+ val dangerousCode = List("Console.read", "Scheduler.impl", "System.exit", "System.out").foldLeft("")((x, y) => x + " -e " + y)
+ val grepCmd = "grep " + test.file.getPath + " " + dangerousCode
+ TestRunner.printVerbose("grep cmd: " + grepCmd + "\n")
+
+ val grep = Runtime.getRuntime.exec(grepCmd)
+
+ val in = new BufferedReader(new InputStreamReader(grep.getInputStream))
+
+ val line = in.readLine
+ bypassObjectRunner = (line != null)
+
+ in.close
+
+ //println(bypassObjectRunner)
+ }
+
+ var start = System.currentTimeMillis
+ //println("Starting..." + test.kind + " " + test.test)
+
+ var toCompile = List(test.file.getPath)
+
+ var outDir: File = new File(test.dir, test.fileBase + "-" + test.kind + ".obj")
+ if (! outDir.exists) {
+ outDir.mkdir
+ //println(this.toString + " " + "Created " + outDir)
+ } else {
+ //println(this.toString + " " + "Didn't need to create " + outDir)
+ }
+ test match {
+ case NegTest(_) =>
+ compiler = newGlobal(test.logFile)
+
+ case JVMTest(_) =>
+ //println(test.file.getPath + ": " + test.checkFile.exists + " / " + test.logFile.exists)
+ if (test.checkFile.exists) {
+ var checkReader = new BufferedReader(new FileReader(test.checkFile))
+ var firstLine = checkReader.readLine
+ if (firstLine != null && firstLine.startsWith("warning")) {
+ //reporter = new ExtConsoleReporter(new Settings(x => ()), Console.in, new PrintWriter(logFile))
+ //reporter.shortname = true
+ compiler = newGlobal(test.logFile)
+ }
+ } else if (conservative) compiler = newGlobal
+
+ case ShootoutTest(_) =>
+ var testFile = new File(outDir, "Test.scala")
+ if (testFile.exists) {
+ toCompile = List(testFile.toString)
+ //println(this.toString + " ready to compile :" + toCompile)
+ } else {
+ // BASH script couldn't create test file...
+ }
+ if (test.checkFile.exists) {
+ var checkReader = new BufferedReader(new FileReader(test.checkFile))
+ var firstLine = checkReader.readLine
+ if (firstLine.startsWith("warning")) {
+ //reporter = new ExtConsoleReporter(new Settings(x => ()), Console.in, new PrintWriter(logFile))
+ //reporter.shortname = true
+ compiler = newGlobal(test.logFile)
+ }
+ } else if (conservative) compiler = newGlobal
+
+ case _ =>
+ }
+
+ val c = compiler
+
+ //println("about to define compilation settings...")
+
+ test.defineSettings(settings)
+ try {
+ //println(this.toString + " " + "Launching compiler on " + toCompile)
+ (new c.Run) compile toCompile
+ reporter.printSummary
+ reporter.writer.flush
+ reporter.writer.close
+ //println(this.toString + " " + "Finished compiling " + test.fileBase)
+ } catch {
+ case e => {
+ e.printStackTrace
+ reporter.error(null, "IO/Error")
+ }
+ }
+ (reporter.hasErrors, test) match {
+ case (_, NegTest(_)) =>
+ case (true, _) =>
+ compiler = newGlobal
+ val c = compiler
+ try {
+ (new c.Run) compile toCompile
+ } catch {
+ case e => reporter.error(null, "IO/Error")
+ }
+ case _ =>
+ }
+
+ var result = test match {
+ case NegTest(_) => reporter.hasErrors
+ case _ => !reporter.hasErrors
+ }
+
+ (bypassObjectRunner, result, test) match {
+ case (_, _, PosTest(_)) =>
+ case (_, _, NegTest(_)) =>
+ case (false, true, _) =>
+ System.setProperty("scalatest.output", outDir.toString)
+ test match {
+ case ShootoutTest(_) => System.setProperty("scalatest.cwd", test.dir)
+ case _ => {}
+ }
+
+ var classpath: List[URL] = outDir.toURL :: List((new File(test.dir)).toURL) ::: List.fromString(System.getProperty("CLASSPATH"), ':').map(x => (new File(x)).toURL) ::: List.fromString(System.getProperty("JVMEXTCP"), ':').map(x => (new File(x)).toURL)
+
+ try {
+ //println(this.toString + " " + "Launching test " + test.fileBase)
+ var out = new FileOutputStream(test.logFile, true)
+ Console.withOut(new PrintStream(out)) {
+ ObjectRunner.run(classpath, "Test", List("jvm"))
+ }
+ out.flush
+ out.close
+ //println(this.toString + " " + "Finished running " + test.fileBase)
+ } catch { case t => println(t) }
+
+ case _ =>
+ }
+ (!bypassObjectRunner && result, test.checkFile.exists, test) match {
+ case (_, _, PosTest(_)) =>
+ case (true, true, _) =>
+ /*var cmd: String = "diff " + test.logFile + " " + test.checkFile
+ //println(this.toString + " Comparing files " + test.fileBase)
+ var proc: Process = Runtime.getRuntime.exec(cmd)
+ proc.waitFor
+ result = (proc.exitValue == 0)*/
+ var equalNow = true
+ if (test.checkFile.canRead) {
+ val originStream = new FileInputStream(test.logFile)
+ val destStream = new FileInputStream(test.checkFile)
+ var originSize = originStream.read(originBuffer)
+ while (originSize >= 0) {
+ if (originSize == destStream.read(destBuffer)) {
+ for (idx <- 0 until originSize)
+ equalNow = equalNow && (originBuffer(idx) == destBuffer(idx))
+ if (!equalNow) {
+ result = false
+ //println("Diff1: diffs found")
+ }
+ }
+ else {
+ result = false
+ //println("Diff1: diffs found")
+ }
+ originSize = originStream.read(originBuffer)
+ }
+ if (destStream.read(destBuffer) >= 0) result = false
+ }
+
+ case _ =>
+ //println("Not testing diff... " + test.test)
+ }
+
+ (bypassObjectRunner || !result, test) match {
+ case (_, PosTest(_)) =>
+ case (_, NegTest(_)) =>
+ case (true, _) =>
+ result = true
+ var javaoptsFile = new File(test.dir, test.fileBase + ".javaopts")
+ //var javaNewOpts = (new BufferedFileReader(javaoptsFile)).readLine
+ //if (javaoptsFile.exists && javaNewOpts != null) {}
+ //Use Runtime.exec to execute the compiled file and pipe the standard system out and the console out to the logfile
+ var cmd = "env JAVACMD=java JAVA_OPTS=-Djava.library.path="+test.dir+" "+System.getProperty("SCALA")+" -Dscalatest.lib="+System.getProperty("scalatest.lib")+" -Dscalatest.cwd="+test.dir+" -Dscalatest.output="+outDir+" -classpath "+outDir+":"+System.getProperty("CLASSPATH")+":"+System.getProperty("JVMEXTCP")+" Test jvm"
+
+ //println(cmd)
+
+ var execution = Runtime.getRuntime.exec(cmd)
+
+ var in = execution.getInputStream
+ var out = new FileOutputStream(test.logFile)
+
+ var c = in.read
+ while (c != -1) {
+ out.write(c)
+ c = in.read
+ }
+
+ in.close
+ out.close
+
+ //println("Running diff")
+
+ /*var diff = Runtime.getRuntime.exec("diff " + test.logFile + " " + test.checkFile)
+ diff.waitFor
+
+ result = (diff.exitValue == 0)*/
+ var equalNow = true
+ if (test.checkFile.canRead) {
+ val originStream = new FileInputStream(test.logFile)
+ val destStream = new FileInputStream(test.checkFile)
+ var originSize = originStream.read(originBuffer)
+ while (originSize >= 0) {
+ if (originSize == destStream.read(destBuffer)) {
+ for (idx <- 0 until originSize)
+ equalNow = equalNow && (originBuffer(idx) == destBuffer(idx))
+ if (!equalNow) {
+ result = false
+ //println("Differences found between the log and check files..")
+ }
+ }
+ else {
+ result = false
+ //println("Differences found between the log and check files..")
+ }
+
+ originSize = originStream.read(originBuffer)
+ }
+ if (destStream.read(destBuffer) >= 0) result = false
+ }
+ //else reportMissing(originFile)
+
+ case _ =>
+ //println("Not Using runtime... " + test.test)
+ }
+ test.logFile.delete
+
+ var end = System.currentTimeMillis
+
+ //println(test.test + ": " + (end - start))
+
+ //printSuccess(this.toString + " " + fileBase + ": "+ result + "\n")
+ master ! (test.kind, result, test.file)
+ dirDelete(outDir)
+ }
+ case false =>
+ exit
+
+ case msg =>
+ println("Unknown message : " + msg)
+ }
+ }
+ }
+}
diff --git a/src/partest/scala/tools/partest/utils/PrintMgr.scala b/src/partest/scala/tools/partest/utils/PrintMgr.scala
new file mode 100644
index 0000000000..a47657d611
--- /dev/null
+++ b/src/partest/scala/tools/partest/utils/PrintMgr.scala
@@ -0,0 +1,51 @@
+/* __ *\
+** ________ ___ / / ___ Scala Parallel Testing **
+** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id: $
+
+package scala.tools.partest.utils
+
+/**
+ * @author Thomas Hofer
+ */
+object PrintMgr {
+
+ val NONE = 0
+ val SOME = 1
+ val MANY = 2
+
+ var outline = ""
+ var success = ""
+ var failure = ""
+ var warning = ""
+ var default = ""
+
+ def initialization(number: Int) = number match {
+ case MANY =>
+ outline = Console.BOLD + Console.BLACK
+ success = Console.BOLD + Console.GREEN
+ failure = Console.BOLD + Console.RED
+ warning = Console.BOLD + Console.YELLOW
+ default = Console.RESET
+ case SOME =>
+ outline = Console.BOLD + Console.BLACK
+ success = Console.RESET
+ failure = Console.BOLD + Console.BLACK
+ warning = Console.BOLD + Console.BLACK
+ default = Console.RESET
+ case _ =>
+ }
+
+ def printOutline(msg: String) = print(outline + msg + default)
+
+ def printSuccess(msg: String) = print(success + msg + default)
+
+ def printFailure(msg: String) = print(failure + msg + default)
+
+ def printWarning(msg: String) = print(warning + msg + default)
+}