Added presentation compiler tests. review by phaller, extempore.

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@24075 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
dragos 2011-01-24 19:17:32 +00:00
parent e2ccd40f32
commit 9c215faff7
14 changed files with 713 additions and 17 deletions

View File

@ -1567,11 +1567,14 @@ BOOTRAPING TEST AND TEST SUITE
<shootouttests dir="${partest.dir}/${partest.srcdir}/shootout" includes="*.scala"/> <shootouttests dir="${partest.dir}/${partest.srcdir}/shootout" includes="*.scala"/>
<scalaptests dir="${partest.dir}/${partest.srcdir}/scalap" includes="**/*.scala"/> <scalaptests dir="${partest.dir}/${partest.srcdir}/scalap" includes="**/*.scala"/>
<scalachecktests dir="${partest.dir}/${partest.srcdir}/scalacheck"> <scalachecktests dir="${partest.dir}/${partest.srcdir}/scalacheck">
<include name="*.scala"/> <include name="*.scala"/>
</scalachecktests> </scalachecktests>
<specializedtests dir="${partest.dir}/${partest.srcdir}/specialized"> <specializedtests dir="${partest.dir}/${partest.srcdir}/specialized">
<include name="*.scala"/> <include name="*.scala"/>
</specializedtests> </specializedtests>
<presentationtests dir="${partest.dir}/${partest.srcdir}/presentation">
<include name="*/*.scala"/>
</presentationtests>
<!-- <scripttests dir="${partest.dir}/${partest.srcdir}/script" includes="*.scala"/> --> <!-- <scripttests dir="${partest.dir}/${partest.srcdir}/script" includes="*.scala"/> -->
</partest> </partest>
</target> </target>

View File

@ -0,0 +1,175 @@
package scala.tools.nsc.interactive
package tests
import scala.tools.nsc.Settings
import scala.tools.nsc.reporters.StoreReporter
import scala.tools.nsc.util.{BatchSourceFile, SourceFile, Position}
import scala.tools.nsc.io._
import scala.collection.{immutable, mutable}
/** A base class for writing interactive compiler tests.
*
* This class tries to cover common functionality needed when testing the presentation
* compiler: instantiation source files, reloading, creating positions, instantiating
* the presentation compiler, random stress testing.
*
* By default, this class loads all classes found under `src/`. They are found in
* `sourceFiles`. Positions can be created using `pos(file, line, col)`. The presentation
* compiler is available through `compiler`.
*
* It is easy to test member completion and type at a given position. Source
* files are searched for /markers/. By default, the completion marker is `/*!*/` and the
* typedAt marker is `/*?*/`. Place these markers in your source files, and call `completionTests`
* and `typedAtTests` to print the results at all these positions. Sources are reloaded by `reloadSources`
* (blocking call). All ask operations are placed on the work queue without waiting for each one to
* complete before asking the next. After all asks, it waits for each response in turn and prints the result.
* The default timout is 5 seconds per operation.
*
* The same mechanism can be used for custom operations. Use `askAllSources(marker)(f)(g)`. Give your custom
* marker, and provide the two functions: one for creating the request, and the second for processing the
* response, if it didn't time out and there was no error.
*
* @see Check existing tests under test/files/presentation
*
* @author Iulian Dragos
*/
abstract class InteractiveTest {
val completionMarker = "/*!*/"
val typedAtMarker = "/*?*/"
val TIMEOUT = 5000 // 5 seconds
val settings = new Settings
val reporter= new StoreReporter
// need this so that the classpath comes from what partest
// instead of scala.home
settings.usejavacp.value = true
/** The root directory for this test suite, usually the test kind ("test/files/presentation"). */
val outDir = Path(Option(System.getProperty("partest.cwd")).getOrElse("."))
/** The base directory for this test, usually a subdirectory of "test/files/presentation/" */
val baseDir = Option(System.getProperty("partest.testname")).map(outDir / _).getOrElse(Path("."))
// settings.YpresentationDebug.value = true
lazy val compiler = new Global(settings, reporter)
def sources(filename: String*): Seq[SourceFile] =
for (f <- filename) yield
source(if (f.startsWith("/")) Path(f) else baseDir / f)
def source(file: Path) = new BatchSourceFile(AbstractFile.getFile(file.toFile))
def source(filename: String): SourceFile = new BatchSourceFile(AbstractFile.getFile(filename))
def pos(file: SourceFile, line: Int, col: Int): Position =
file.position(line, col)
def filesInDir(dir: Path): Iterator[Path] = {
dir.toDirectory.list.filter(_.isFile)
}
/** Where source files are placed. */
val sourceDir = "src"
/** All .scala files below "src" directory. */
lazy val sourceFiles: Array[SourceFile] =
filesInDir(baseDir / sourceDir).filter(_.extension == "scala").map(source).toArray
/** All positions of the given string in all source files. */
def allPositionsOf(sources: Seq[SourceFile] = sourceFiles, str: String): immutable.Map[SourceFile, Seq[Position]] = {
(for (s <- sources; p <- positionsOf(s, str)) yield p).groupBy(_.source)
}
/** Return all positions of the given str in the given source file. */
def positionsOf(source: SourceFile, str: String): Seq[Position] = {
val buf = new mutable.ListBuffer[Position]
var pos = source.content.indexOfSlice(str)
while (pos >= 0) {
// buf += compiler.rangePos(source, pos - 1, pos - 1, pos - 1)
buf += source.position(pos - 1) // we need the position before the first character of this marker
pos = source.content.indexOfSlice(str, pos + 1)
}
buf.toList
}
/** Perform an operation on all sources at all positions that match the given
* marker string. For instance, askAllSources("/*!*/")(askTypeAt)(println) would
* ask the tyep at all positions marked with /*!*/ and println the result.
*/
def askAllSources[T](marker: String)(askAt: Position => Response[T])(f: (Position, T) => Unit) {
val positions = allPositionsOf(str = marker).valuesIterator.toList.flatten
val responses = for (pos <- positions) yield askAt(pos)
for ((pos, r) <- positions zip responses) r.get(TIMEOUT) match {
case Some(Left(members)) =>
f(pos, members)
case None =>
println("TIMEOUT: " + r)
case _ =>
println("ERROR: " + r)
}
}
/** Ask completion for all marked positions in all sources.
* A completion position is marked with /*!*/.
*/
def completionTests() {
askAllSources(completionMarker) { pos =>
println("askTypeCompletion at " + pos)
val r = new Response[List[compiler.Member]]
compiler.askTypeCompletion(pos, r)
r
} { (pos, members) =>
println("\n" + "=" * 80)
println("[response] aksTypeCompletion at " + (pos.line, pos.column))
println(members.sortBy(_.sym.name.toString).mkString("\n"))
}
}
/** Ask for typedAt for all marker positions in all sources.
*/
def typeAtTests() {
askAllSources(typedAtMarker) { pos =>
println("askTypeAt at " + pos)
val r = new Response[compiler.Tree]
compiler.askTypeAt(pos, r)
r
} { (pos, tree) =>
println("[response] askTypeAt at " + (pos.line, pos.column))
println(tree)
}
}
/** Reload the given source files and wait for them to be reloaded. */
def reloadSources(sources: Seq[SourceFile] = sourceFiles) {
// println("basedir: " + baseDir.path)
// println("sourcedir: " + (baseDir / sourceDir).path)
println("reload: " + sourceFiles.mkString("", ", ", ""))
val reload = new Response[Unit]
compiler.askReload(sourceFiles.toList, reload)
reload.get
}
def runTest: Unit = {
if (runRandomTests) randomTests(20, sourceFiles)
completionTests()
typeAtTests()
}
/** Perform n random tests with random changes. */
def randomTests(n: Int, files: Array[SourceFile]) {
val tester = new Tester(n, files, settings)
tester.run()
}
val runRandomTests = true
def main(args: Array[String]) {
reloadSources()
runTest
compiler.askShutdown()
}
}

View File

@ -153,7 +153,7 @@ class Tester(ntests: Int, inputs: Array[SourceFile], settings: Settings) {
changes foreach (_.deleteAll()) changes foreach (_.deleteAll())
otherTest() otherTest()
def errorCount() = compiler.ask(() => reporter.ERROR.count) def errorCount() = compiler.ask(() => reporter.ERROR.count)
println("\nhalf test round: "+errorCount()) // println("\nhalf test round: "+errorCount())
changes.view.reverse foreach (_.insertAll()) changes.view.reverse foreach (_.insertAll())
otherTest() otherTest()
println("done test round: "+errorCount()) println("done test round: "+errorCount())

View File

@ -71,6 +71,11 @@ class PartestTask extends Task with CompilationPathProperty {
def addConfiguredSpecializedTests(input: FileSet) { def addConfiguredSpecializedTests(input: FileSet) {
specializedFiles = Some(input) specializedFiles = Some(input)
} }
def addConfiguredPresentationTests(input: FileSet) {
presentationFiles = Some(input)
}
def setSrcDir(input: String) { def setSrcDir(input: String) {
srcDir = Some(input) srcDir = Some(input)
@ -146,6 +151,7 @@ class PartestTask extends Task with CompilationPathProperty {
private var shootoutFiles: Option[FileSet] = None private var shootoutFiles: Option[FileSet] = None
private var scalapFiles: Option[FileSet] = None private var scalapFiles: Option[FileSet] = None
private var specializedFiles: Option[FileSet] = None private var specializedFiles: Option[FileSet] = None
private var presentationFiles: Option[FileSet] = None
private var errorOnFailed: Boolean = false private var errorOnFailed: Boolean = false
private var scalacOpts: Option[String] = None private var scalacOpts: Option[String] = None
private var timeout: Option[String] = None private var timeout: Option[String] = None
@ -170,14 +176,25 @@ class PartestTask extends Task with CompilationPathProperty {
// println("----> " + fileSet) // println("----> " + fileSet)
val fileTests = getFiles(Some(fs)) filterNot (x => shouldExclude(x.getName)) val fileTests = getFiles(Some(fs)) filterNot (x => shouldExclude(x.getName))
val dirTests: Iterator[SPath] = fileSetToDir(fs).dirs filterNot (x => shouldExclude(x.name)) val dirResult = getDirs(Some(fs)) filterNot (x => shouldExclude(x.getName))
val dirResult = dirTests.toList.toArray map (_.jfile)
// println("dirs: " + dirResult.toList) // println("dirs: " + dirResult.toList)
// println("files: " + fileTests.toList) // println("files: " + fileTests.toList)
dirResult ++ fileTests dirResult ++ fileTests
} }
private def getDirs(fileSet: Option[FileSet]): Array[File] = fileSet match {
case None => Array()
case Some(fs) =>
def shouldExclude(name: String) = (name endsWith ".obj") || (name startsWith ".")
val dirTests: Iterator[SPath] = fileSetToDir(fs).dirs filterNot (x => shouldExclude(x.name))
val dirResult = dirTests.toList.toArray map (_.jfile)
dirResult
}
private def getPosFiles = getFilesAndDirs(posFiles) private def getPosFiles = getFilesAndDirs(posFiles)
private def getNegFiles = getFilesAndDirs(negFiles) private def getNegFiles = getFilesAndDirs(negFiles)
private def getRunFiles = getFilesAndDirs(runFiles) private def getRunFiles = getFilesAndDirs(runFiles)
@ -189,6 +206,7 @@ class PartestTask extends Task with CompilationPathProperty {
private def getShootoutFiles = getFiles(shootoutFiles) private def getShootoutFiles = getFiles(shootoutFiles)
private def getScalapFiles = getFiles(scalapFiles) private def getScalapFiles = getFiles(scalapFiles)
private def getSpecializedFiles = getFiles(specializedFiles) private def getSpecializedFiles = getFiles(specializedFiles)
private def getPresentationFiles = getDirs(presentationFiles)
override def execute() { override def execute() {
if (isPartestDebug || debug) { if (isPartestDebug || debug) {
@ -236,7 +254,8 @@ class PartestTask extends Task with CompilationPathProperty {
(getScriptFiles, "script", "Running script files"), (getScriptFiles, "script", "Running script files"),
(getShootoutFiles, "shootout", "Running shootout tests"), (getShootoutFiles, "shootout", "Running shootout tests"),
(getScalapFiles, "scalap", "Running scalap tests"), (getScalapFiles, "scalap", "Running scalap tests"),
(getSpecializedFiles, "specialized", "Running specialized files") (getSpecializedFiles, "specialized", "Running specialized files"),
(getPresentationFiles, "presentation", "Running presentation compiler test files")
) )
def runSet(set: TFSet): (Int, Int, Iterable[String]) = { def runSet(set: TFSet): (Int, Int, Iterable[String]) = {

View File

@ -84,14 +84,15 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
val testRep: ExtConsoleReporter = global.reporter.asInstanceOf[ExtConsoleReporter] val testRep: ExtConsoleReporter = global.reporter.asInstanceOf[ExtConsoleReporter]
val testFileFn: (File, FileManager) => TestFile = kind match { val testFileFn: (File, FileManager) => TestFile = kind match {
case "pos" => PosTestFile.apply case "pos" => PosTestFile.apply
case "neg" => NegTestFile.apply case "neg" => NegTestFile.apply
case "run" => RunTestFile.apply case "run" => RunTestFile.apply
case "jvm" => JvmTestFile.apply case "jvm" => JvmTestFile.apply
case "shootout" => ShootoutTestFile.apply case "shootout" => ShootoutTestFile.apply
case "scalap" => ScalapTestFile.apply case "scalap" => ScalapTestFile.apply
case "scalacheck" => ScalaCheckTestFile.apply case "scalacheck" => ScalaCheckTestFile.apply
case "specialized" => SpecializedTestFile.apply case "specialized" => SpecializedTestFile.apply
case "presentation" => PresentationTestFile.apply
} }
val test: TestFile = testFileFn(files.head, fileManager) val test: TestFile = testFileFn(files.head, fileManager)
test.defineSettings(command.settings, out.isEmpty) test.defineSettings(command.settings, out.isEmpty)

View File

@ -36,7 +36,8 @@ class ConsoleRunner extends DirectRunner {
TestSet("script", pathFilter, "Testing script tests"), TestSet("script", pathFilter, "Testing script tests"),
TestSet("scalacheck", x => pathFilter(x) || x.isDirectory, "Testing ScalaCheck tests"), TestSet("scalacheck", x => pathFilter(x) || x.isDirectory, "Testing ScalaCheck tests"),
TestSet("scalap", _.isDirectory, "Run scalap decompiler tests"), TestSet("scalap", _.isDirectory, "Run scalap decompiler tests"),
TestSet("specialized", pathFilter, "Testing specialized tests") TestSet("specialized", pathFilter, "Testing specialized tests"),
TestSet("presentation", _.isDirectory, "Testing presentation compiler tests.")
) )
} }
@ -57,7 +58,7 @@ class ConsoleRunner extends DirectRunner {
private val unaryArgs = List( private val unaryArgs = List(
"--pack", "--all", "--verbose", "--show-diff", "--show-log", "--pack", "--all", "--verbose", "--show-diff", "--show-log",
"--failed", "--update-check", "--version", "--ansi", "--debug" "--failed", "--update-check", "--version", "--ansi", "--debug", "--help"
) ::: testSetArgs ) ::: testSetArgs
private val binaryArgs = List( private val binaryArgs = List(
@ -71,6 +72,7 @@ class ConsoleRunner extends DirectRunner {
/** Early return on no args, version, or invalid args */ /** Early return on no args, version, or invalid args */
if (argstr == "") return NestUI.usage() if (argstr == "") return NestUI.usage()
if (parsed isSet "--version") return printVersion if (parsed isSet "--version") return printVersion
if (parsed isSet "--help") return NestUI.usage()
if (args exists (x => !denotesTestPath(x))) { if (args exists (x => !denotesTestPath(x))) {
val invalid = (args filterNot denotesTestPath).head val invalid = (args filterNot denotesTestPath).head
NestUI.failure("Invalid argument '%s'\n" format invalid) NestUI.failure("Invalid argument '%s'\n" format invalid)

View File

@ -55,3 +55,4 @@ case class SpecializedTestFile(file: JFile, fileManager: FileManager) extends Te
settings.classpath.value = ClassPath.join(PathSettings.srcSpecLib.toString, settings.classpath.value) settings.classpath.value = ClassPath.join(PathSettings.srcSpecLib.toString, settings.classpath.value)
} }
} }
case class PresentationTestFile(file: JFile, fileManager: FileManager) extends TestFile("presentation")

View File

@ -315,6 +315,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
"-Dpartest.output="+outDir.getAbsolutePath, "-Dpartest.output="+outDir.getAbsolutePath,
"-Dpartest.lib="+LATEST_LIB, "-Dpartest.lib="+LATEST_LIB,
"-Dpartest.cwd="+outDir.getParent, "-Dpartest.cwd="+outDir.getParent,
"-Dpartest.testname="+fileBase,
"-Djavacmd="+JAVACMD, "-Djavacmd="+JAVACMD,
"-Djavaccmd="+javacCmd, "-Djavaccmd="+javacCmd,
"-Duser.language=en -Duser.country=US" "-Duser.language=en -Duser.country=US"
@ -540,7 +541,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
execTest(outDir, logFile, PathSettings.srcSpecLib.toString) execTest(outDir, logFile, PathSettings.srcSpecLib.toString)
diffCheck(compareOutput(dir, logFile)) diffCheck(compareOutput(dir, logFile))
}) })
def processSingleFile(file: File): LogContext = kind match { def processSingleFile(file: File): LogContext = kind match {
case "scalacheck" => case "scalacheck" =>
val succFn: (File, File) => Boolean = { (logFile, outDir) => val succFn: (File, File) => Boolean = { (logFile, outDir) =>
@ -592,6 +593,9 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
case "specialized" => case "specialized" =>
runSpecializedTest(file) runSpecializedTest(file)
case "presentation" =>
runJvmTest(file) // for the moment, it's exactly the same as for a run test
case "buildmanager" => case "buildmanager" =>
val logFile = createLogFile(file) val logFile = createLogFile(file)

View File

@ -0,0 +1,8 @@
reload: InteractiveTest.scala
asking position at 19:4
retrieved tree: InteractiveTest.this.settings
====================
asking position at 20:16
retrieved tree: lazy private[this] var compiler: scala.tools.nsc.interactive.CompilerControl = new Global(InteractiveTest.this.settings, InteractiveTest.this.reporter)

View File

@ -0,0 +1,43 @@
import scala.tools.nsc.interactive.tests.InteractiveTest
import scala.tools.nsc.util.Position
/** Example interactive test that does everything by hand. It would be much simpler
* to just add the markers in the test file. This test shows how to drive
* the presentation compiler manually.
*/
object Test extends InteractiveTest {
def askForPos(pos: Position) {
import compiler._
val response = new Response[Tree]
println("asking position at %d:%d".format(pos.line, pos.column))
compiler.askTypeAt(pos, response)
response.get match {
case Left(EmptyTree) =>
println("error retrieving tree at %d:%d".format(pos.line, pos.column))
case Left(t) =>
println("retrieved tree: " + t)
}
println(this.reporter.infos.mkString("\n"))
}
override def runTest {
import compiler._
val src = sourceFiles(0) // only one under src/
val pos = rangePos(src, 426, 426, 433)
val pos1 = src.position(19, 15)
// reload is issued already by the framework, but we can redo it here as an example
val reload = new Response[Unit]
compiler.askReload(List(src), reload)
reload.get // it's important to let reload finish before asking other things.
askForPos(pos)
println("=" * 20)
askForPos(pos1)
compiler.askShutdown()
}
}

View File

@ -0,0 +1,36 @@
package scala.tools.nsc.interactive
package tests
import scala.tools.nsc.Settings
import scala.tools.nsc.reporters.StoreReporter
import scala.tools.nsc.util.{BatchSourceFile, SourceFile, Position}
import scala.tools.nsc.io._
/** A base class for writing interactive compiler tests.
*
* @author Iulian Dragos
*
*/
abstract class InteractiveTest {
val settings = new Settings
val reporter= new StoreReporter
settings.YpresentationDebug.value = true
lazy val compiler: CompilerControl = new Global(settings, reporter)
def sources(filename: String*): Seq[SourceFile] =
filename map source
def source(filename: String) = new BatchSourceFile(AbstractFile.getFile(filename))
def pos(filename: String, line: Int, col: Int): Position =
source(filename).position(line, col)
def runTest: Unit
def main(args: Array[String]) {
runTest
}
}

View File

@ -0,0 +1,191 @@
reload: Tester.scala
askTypeCompletion at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-12,offset=268
askTypeCompletion at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-23,offset=722
askTypeCompletion at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-105,offset=3041
================================================================================
[response] aksTypeCompletion at (12,39)
TypeMember(method $asInstanceOf,[T0]()T0,true,false,method any2stringadd)
TypeMember(method !=,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
TypeMember(method !=,(x$1: Any)Boolean,true,false,method any2stringadd)
TypeMember(method ==,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
TypeMember(method ==,(x$1: Any)Boolean,true,false,method any2stringadd)
TypeMember(method ##,()Int,true,false,method any2stringadd)
TypeMember(method $isInstanceOf,[T0]()Boolean,true,false,method any2stringadd)
TypeMember(method ->,[B](y: B)(scala.tools.nsc.reporters.StoreReporter, B),true,false,method any2ArrowAssoc)
TypeMember(method +,(other: String)java.lang.String,true,false,method any2stringadd)
TypeMember(method ?,[B](y: B)(scala.tools.nsc.reporters.StoreReporter, B),true,false,method any2ArrowAssoc)
TypeMember(constructor StoreReporter,()scala.tools.nsc.reporters.StoreReporter,true,false,<none>)
TypeMember(constructor StringAdd,(self: Any)scala.runtime.StringAdd,true,false,method any2stringadd)
TypeMember(constructor ArrowAssoc,(x: scala.tools.nsc.reporters.StoreReporter)ArrowAssoc[scala.tools.nsc.reporters.StoreReporter],true,false,method any2ArrowAssoc)
TypeMember(value ERROR,=> scala.tools.nsc.reporters.StoreReporter#Severity,true,true,<none>)
TypeMember(value INFO,=> scala.tools.nsc.reporters.StoreReporter#Severity,true,true,<none>)
TypeMember(class Info,scala.tools.nsc.reporters.StoreReporter#Info,true,false,<none>)
TypeMember(class Severity,scala.tools.nsc.reporters.StoreReporter#Severity,true,true,<none>)
TypeMember(value WARNING,=> scala.tools.nsc.reporters.StoreReporter#Severity,true,true,<none>)
TypeMember(method _truncationOK,=> Boolean,false,true,<none>)
TypeMember(method asInstanceOf,[T0]=> T0,true,true,<none>)
TypeMember(method cancelled,=> Boolean,true,true,<none>)
TypeMember(method clone,()java.lang.Object,false,true,<none>)
TypeMember(method comment,(pos: scala.tools.nsc.util.Position,msg: String)Unit,true,true,<none>)
TypeMember(method countAsString,(n: Int)String,true,true,<none>)
TypeMember(method countElementsAsString,(n: Int,elements: String)String,true,true,<none>)
TypeMember(method ensuring,(cond: (scala.tools.nsc.reporters.StoreReporter) => Boolean,msg: => Any)scala.tools.nsc.reporters.StoreReporter,true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: (scala.tools.nsc.reporters.StoreReporter) => Boolean)scala.tools.nsc.reporters.StoreReporter,true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: Boolean,msg: => Any)scala.tools.nsc.reporters.StoreReporter,true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: Boolean)scala.tools.nsc.reporters.StoreReporter,true,false,method any2Ensuring)
TypeMember(method eq,(x$1: AnyRef)Boolean,true,true,<none>)
TypeMember(method equals,(x$1: Any)Boolean,true,true,<none>)
TypeMember(method error,(pos: scala.tools.nsc.util.Position,msg: String)Unit,true,true,<none>)
TypeMember(method finalize,()Unit,false,true,<none>)
TypeMember(method flush,()Unit,true,true,<none>)
TypeMember(method formatted,(fmtstr: String)String,true,false,method any2stringadd)
TypeMember(method getClass,()java.lang.Class[_],true,true,<none>)
TypeMember(method getSource,=> scala.tools.nsc.util.SourceFile,true,true,<none>)
TypeMember(method hasErrors,=> Boolean,true,true,<none>)
TypeMember(method hasWarnings,=> Boolean,true,true,<none>)
TypeMember(method hashCode,()Int,true,true,<none>)
TypeMember(method incompleteHandled,=> Boolean,true,true,<none>)
TypeMember(method incompleteInputError,=> (scala.tools.nsc.util.Position, String) => Unit,true,true,<none>)
TypeMember(method info,(pos: scala.tools.nsc.util.Position,msg: String,force: Boolean)Unit,true,true,<none>)
TypeMember(method info0,((pos: scala.tools.nsc.util.Position,msg: java.lang.String,severity: _5.Severity,force: Boolean)Unit) forSome { val _5: scala.tools.nsc.reporters.StoreReporter },false,false,<none>)
TypeMember(value infos,(=> scala.collection.mutable.HashSet[_3.Info]) forSome { val _3: scala.tools.nsc.reporters.StoreReporter },true,false,<none>)
TypeMember(value infos,scala.collection.mutable.HashSet[_4.Info] forSome { val _4: scala.tools.nsc.reporters.StoreReporter },false,false,<none>)
TypeMember(method isInstanceOf,[T0]=> Boolean,true,true,<none>)
TypeMember(method ne,(x$1: AnyRef)Boolean,true,true,<none>)
TypeMember(method notify,()Unit,true,true,<none>)
TypeMember(method notifyAll,()Unit,true,true,<none>)
TypeMember(method reset,()Unit,true,false,<none>)
TypeMember(value self,Any,false,false,method any2stringadd)
TypeMember(method setSource,(source: scala.tools.nsc.util.SourceFile)Unit,true,true,<none>)
TypeMember(object severity,object scala.tools.nsc.reporters.StoreReporter#severity,true,true,<none>)
TypeMember(method source,=> scala.tools.nsc.util.SourceFile,false,true,<none>)
TypeMember(method synchronized,[T0](x$1: T0)T0,true,true,<none>)
TypeMember(method toString,()java.lang.String,true,true,<none>)
TypeMember(method truncationOK,=> Boolean,true,true,<none>)
TypeMember(method wait,()Unit,true,true,<none>)
TypeMember(method wait,(x$1: Long,x$2: Int)Unit,true,true,<none>)
TypeMember(method wait,(x$1: Long)Unit,true,true,<none>)
TypeMember(method warning,(pos: scala.tools.nsc.util.Position,msg: String)Unit,true,true,<none>)
TypeMember(method withIncompleteHandler,[T](handler: (scala.tools.nsc.util.Position, String) => Unit)(thunk: => T)T,true,true,<none>)
TypeMember(method withSource,[A](src: scala.tools.nsc.util.SourceFile)(op: => A)A,true,true,<none>)
TypeMember(method withoutTruncating,[T](body: => T)T,true,true,<none>)
TypeMember(value x,=> scala.tools.nsc.reporters.StoreReporter,true,false,method any2ArrowAssoc)
TypeMember(value x,scala.tools.nsc.reporters.StoreReporter,false,false,method any2ArrowAssoc)
================================================================================
[response] aksTypeCompletion at (23,24)
TypeMember(method $asInstanceOf,[T0]()T0,true,false,method any2stringadd)
TypeMember(method !=,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
TypeMember(method !=,(x$1: Any)Boolean,true,false,method any2stringadd)
TypeMember(method ==,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
TypeMember(method ==,(x$1: Any)Boolean,true,false,method any2stringadd)
TypeMember(method ##,()Int,true,false,method any2stringadd)
TypeMember(method $isInstanceOf,[T0]()Boolean,true,false,method any2stringadd)
TypeMember(method ->,[B](y: B)(scala.tools.nsc.interactive.Response[U], B),true,false,method any2ArrowAssoc)
TypeMember(method +,(other: String)java.lang.String,true,false,method any2stringadd)
TypeMember(method ?,[B](y: B)(scala.tools.nsc.interactive.Response[U], B),true,false,method any2ArrowAssoc)
TypeMember(constructor Response,()scala.tools.nsc.interactive.Response[U],true,false,<none>)
TypeMember(constructor StringAdd,(self: Any)scala.runtime.StringAdd,true,false,method any2stringadd)
TypeMember(constructor ArrowAssoc,(x: scala.tools.nsc.interactive.Response[U])ArrowAssoc[scala.tools.nsc.interactive.Response[U]],true,false,method any2ArrowAssoc)
TypeMember(method asInstanceOf,[T0]=> T0,true,true,<none>)
TypeMember(method cancel,()Unit,true,false,<none>)
TypeMember(method cancelled,=> Boolean,false,false,<none>)
TypeMember(variable cancelled,Boolean,false,false,<none>)
TypeMember(method clear,()Unit,true,false,<none>)
TypeMember(method clone,()java.lang.Object,false,true,<none>)
TypeMember(method complete,=> Boolean,false,false,<none>)
TypeMember(variable complete,Boolean,false,false,<none>)
TypeMember(method data,=> Option[Either[U,Throwable]],false,false,<none>)
TypeMember(variable data,Option[Either[U,Throwable]],false,false,<none>)
TypeMember(method ensuring,(cond: (scala.tools.nsc.interactive.Response[U]) => Boolean,msg: => Any)scala.tools.nsc.interactive.Response[U],true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: (scala.tools.nsc.interactive.Response[U]) => Boolean)scala.tools.nsc.interactive.Response[U],true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: Boolean,msg: => Any)scala.tools.nsc.interactive.Response[U],true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: Boolean)scala.tools.nsc.interactive.Response[U],true,false,method any2Ensuring)
TypeMember(method eq,(x$1: AnyRef)Boolean,true,true,<none>)
TypeMember(method equals,(x$1: Any)Boolean,true,true,<none>)
TypeMember(method finalize,()Unit,false,true,<none>)
TypeMember(method formatted,(fmtstr: String)String,true,false,method any2stringadd)
TypeMember(method get,=> Either[U,Throwable],true,false,<none>)
TypeMember(method get,(timeout: Long)Option[Either[U,Throwable]],true,false,<none>)
TypeMember(method getClass,()java.lang.Class[_],true,true,<none>)
TypeMember(method hashCode,()Int,true,true,<none>)
TypeMember(method isCancelled,=> Boolean,true,false,<none>)
TypeMember(method isComplete,=> Boolean,true,false,<none>)
TypeMember(method isInstanceOf,[T0]=> Boolean,true,true,<none>)
TypeMember(method ne,(x$1: AnyRef)Boolean,true,true,<none>)
TypeMember(method notify,()Unit,true,true,<none>)
TypeMember(method notifyAll,()Unit,true,true,<none>)
TypeMember(method raise,(exc: Throwable)Unit,true,false,<none>)
TypeMember(value self,Any,false,false,method any2stringadd)
TypeMember(method set,(x: U)Unit,true,false,<none>)
TypeMember(method setProvisionally,(x: U)Unit,true,false,<none>)
TypeMember(method synchronized,[T0](x$1: T0)T0,true,true,<none>)
TypeMember(method toString,()java.lang.String,true,true,<none>)
TypeMember(method wait,()Unit,true,true,<none>)
TypeMember(method wait,(x$1: Long,x$2: Int)Unit,true,true,<none>)
TypeMember(method wait,(x$1: Long)Unit,true,true,<none>)
TypeMember(value x,=> scala.tools.nsc.interactive.Response[U],true,false,method any2ArrowAssoc)
TypeMember(value x,scala.tools.nsc.interactive.Response[U],false,false,method any2ArrowAssoc)
================================================================================
[response] aksTypeCompletion at (105,29)
TypeMember(method $asInstanceOf,[T0]()T0,true,false,method any2stringadd)
TypeMember(method !=,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
TypeMember(method !=,(x$1: Any)Boolean,true,false,method any2stringadd)
TypeMember(method ==,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
TypeMember(method ==,(x$1: Any)Boolean,true,false,method any2stringadd)
TypeMember(method ##,()Int,true,false,method any2stringadd)
TypeMember(method $isInstanceOf,[T0]()Boolean,true,false,method any2stringadd)
TypeMember(method ->,[B](y: B)(scala.tools.nsc.util.SourceFile, B),true,false,method any2ArrowAssoc)
TypeMember(method +,(other: String)java.lang.String,true,false,method any2stringadd)
TypeMember(method ?,[B](y: B)(scala.tools.nsc.util.SourceFile, B),true,false,method any2ArrowAssoc)
TypeMember(constructor SourceFile,()scala.tools.nsc.util.SourceFile,true,false,<none>)
TypeMember(constructor StringAdd,(self: Any)scala.runtime.StringAdd,true,false,method any2stringadd)
TypeMember(constructor ArrowAssoc,(x: scala.tools.nsc.util.SourceFile)ArrowAssoc[scala.tools.nsc.util.SourceFile],true,false,method any2ArrowAssoc)
TypeMember(method asInstanceOf,[T0]=> T0,true,true,<none>)
TypeMember(method beginsWith,(offset: Int,text: String)Boolean,true,false,<none>)
TypeMember(method clone,()java.lang.Object,false,true,<none>)
TypeMember(method content,=> Array[Char],true,false,<none>)
TypeMember(method dbg,(offset: Int)java.lang.String,true,false,<none>)
TypeMember(method ensuring,(cond: (scala.tools.nsc.util.SourceFile) => Boolean,msg: => Any)scala.tools.nsc.util.SourceFile,true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: (scala.tools.nsc.util.SourceFile) => Boolean)scala.tools.nsc.util.SourceFile,true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: Boolean,msg: => Any)scala.tools.nsc.util.SourceFile,true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: Boolean)scala.tools.nsc.util.SourceFile,true,false,method any2Ensuring)
TypeMember(method eq,(x$1: AnyRef)Boolean,true,true,<none>)
TypeMember(method equals,(x$1: Any)Boolean,true,true,<none>)
TypeMember(method file,=> scala.tools.nsc.io.AbstractFile,true,false,<none>)
TypeMember(method finalize,()Unit,false,true,<none>)
TypeMember(method formatted,(fmtstr: String)String,true,false,method any2stringadd)
TypeMember(method getClass,()java.lang.Class[_],true,true,<none>)
TypeMember(method hashCode,()Int,true,true,<none>)
TypeMember(method identifier,(pos: scala.tools.nsc.util.Position,compiler: scala.tools.nsc.Global)Option[String],true,false,<none>)
TypeMember(method isInstanceOf,[T0]=> Boolean,true,true,<none>)
TypeMember(method isLineBreak,(idx: Int)Boolean,true,false,<none>)
TypeMember(method isSelfContained,=> Boolean,true,false,<none>)
TypeMember(method length,=> Int,true,false,<none>)
TypeMember(method lineToOffset,(index: Int)Int,true,false,<none>)
TypeMember(method lineToString,(index: Int)String,true,false,<none>)
TypeMember(method ne,(x$1: AnyRef)Boolean,true,true,<none>)
TypeMember(method notify,()Unit,true,true,<none>)
TypeMember(method notifyAll,()Unit,true,true,<none>)
TypeMember(method offsetToLine,(offset: Int)Int,true,false,<none>)
TypeMember(method path,=> String,true,false,<none>)
TypeMember(method position,(offset: Int)scala.tools.nsc.util.Position,true,false,<none>)
TypeMember(method position,(line: Int,column: Int)scala.tools.nsc.util.Position,true,false,<none>)
TypeMember(method positionInUltimateSource,(position: scala.tools.nsc.util.Position)scala.tools.nsc.util.Position,true,false,<none>)
TypeMember(value self,Any,false,false,method any2stringadd)
TypeMember(method skipWhitespace,(offset: Int)Int,true,false,<none>)
TypeMember(method synchronized,[T0](x$1: T0)T0,true,true,<none>)
TypeMember(method toString,()String,true,false,<none>)
TypeMember(method wait,()Unit,true,true,<none>)
TypeMember(method wait,(x$1: Long,x$2: Int)Unit,true,true,<none>)
TypeMember(method wait,(x$1: Long)Unit,true,true,<none>)
TypeMember(value x,=> scala.tools.nsc.util.SourceFile,true,false,method any2ArrowAssoc)
TypeMember(value x,scala.tools.nsc.util.SourceFile,false,false,method any2ArrowAssoc)
askTypeAt at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-12,offset=243
askTypeAt at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-13,offset=288
[response] askTypeAt at (12,14)
private[this] val reporter: scala.tools.nsc.reporters.StoreReporter = new reporters.StoreReporter()
[response] askTypeAt at (13,14)
private[this] val compiler: scala.tools.nsc.interactive.Global = new Global(Tester.this.settings, Tester.this.reporter)

View File

@ -0,0 +1,9 @@
import scala.tools.nsc.interactive.tests._
/** Simple test that shows how to use the InteractiveTest class. It uses the
* inherited runTest method that runs completion and typedAt tests on all
* sources found under src/
*/
object Test extends InteractiveTest {
override val runRandomTests = false
}

View File

@ -0,0 +1,204 @@
package scala.tools.nsc
package interactive
package tests
import util._
import reporters._
import io.AbstractFile
import collection.mutable.ArrayBuffer
class Tester(ntests: Int, inputs: Array[SourceFile], settings: Settings) {
val reporter/*?*/ = new StoreReporter/*!*/
val compiler/*?*/ = new Global(settings, reporter)
def askAndListen[T, U](msg: String, arg: T, op: (T, Response[U]) => Unit) {
if (settings.verbose.value) print(msg+" "+arg+": ")
val TIMEOUT = 10 // ms
val limit = System.currentTimeMillis() + randomDelayMillis
val res = new Response[U]
op(arg, res)
while (!res.isComplete && !res.isCancelled) {
if (System.currentTimeMillis() > limit) {
print("c"); res./*!*/cancel()
} else res.get(TIMEOUT) match {
case Some(Left(t)) =>
/**/
if (settings.verbose.value) println(t)
case Some(Right(ex)) =>
ex.printStackTrace()
println(ex)
case None =>
}
}
}
def askReload(sfs: SourceFile*) = askAndListen("reload", sfs.toList, compiler.askReload)
def askTypeAt(pos: Position) = askAndListen("type at", pos, compiler.askTypeAt)
def askTypeCompletion(pos: Position) = askAndListen("type at", pos, compiler.askTypeCompletion)
def askScopeCompletion(pos: Position) = askAndListen("type at", pos, compiler.askScopeCompletion)
val rand = new java.util.Random()
private def randomInverse(n: Int) = n / (rand.nextInt(n) + 1)
private def randomDecreasing(n: Int) = {
var r = rand.nextInt((1 to n).sum)
var limit = n
var result = 0
while (r > limit) {
result += 1
r -= limit
limit -= 1
}
result
}
def randomSourceFileIdx() = rand.nextInt(inputs.length)
def randomBatchesPerSourceFile(): Int = randomDecreasing(100)
def randomChangesPerBatch(): Int = randomInverse(50)
def randomPositionIn(sf: SourceFile) = rand.nextInt(sf.content.length)
def randomNumChars() = randomInverse(100)
def randomDelayMillis = randomInverse(10000)
class Change(sfidx: Int, start: Int, nchars: Int, toLeft: Boolean) {
private var pos = start
private var deleted: List[Char] = List()
override def toString =
"In "+inputs(sfidx)+" at "+start+" take "+nchars+" to "+
(if (toLeft) "left" else "right")
def deleteOne() {
val sf = inputs(sfidx)
deleted = sf.content(pos) :: deleted
val sf1 = new BatchSourceFile(sf.file, sf.content.take(pos) ++ sf.content.drop(pos + 1))
inputs(sfidx) = sf1
askReload(sf1)
}
def deleteAll() {
print("/"+nchars)
for (i <- 0 until nchars) {
if (toLeft) {
if (pos > 0 && pos <= inputs(sfidx).length) {
pos -= 1
deleteOne()
}
} else {
if (pos < inputs(sfidx).length) {
deleteOne()
}
}
}
}
def insertAll() {
for (chr <- if (toLeft) deleted else deleted.reverse) {
val sf = inputs(sfidx)
val (pre, post) = sf./*!*/content splitAt pos
pos += 1
val sf1 = new BatchSourceFile(sf.file, pre ++ (chr +: post))
inputs(sfidx) = sf1
askReload(sf1)
}
}
}
val testComment = "/**/"
def testFileChanges(sfidx: Int) = {
lazy val testPositions: Seq[Int] = {
val sf = inputs(sfidx)
val buf = new ArrayBuffer[Int]
var pos = sf.content.indexOfSlice(testComment)
while (pos > 0) {
buf += pos
pos = sf.content.indexOfSlice(testComment, pos + 1)
}
buf
}
def otherTest() {
if (testPositions.nonEmpty) {
val pos = new OffsetPosition(inputs(sfidx), rand.nextInt(testPositions.length))
rand.nextInt(3) match {
case 0 => askTypeAt(pos)
case 1 => askTypeCompletion(pos)
case 2 => askScopeCompletion(pos)
}
}
}
for (i <- 0 until randomBatchesPerSourceFile()) {
val changes = Vector.fill(/**/randomChangesPerBatch()) {
/**/
new Change(sfidx, randomPositionIn(inputs(sfidx)), randomNumChars(), rand.nextBoolean())
}
doTest(sfidx, changes, testPositions, otherTest) match {
case Some(errortrace) =>
println(errortrace)
minimize(errortrace)
case None =>
}
}
}
def doTest(sfidx: Int, changes: Seq[Change], testPositions: Seq[Int], otherTest: () => Unit): Option[ErrorTrace] = {
print("new round with "+changes.length+" changes:")
changes foreach (_.deleteAll())
otherTest()
def errorCount() = compiler.ask(() => reporter.ERROR.count)
// println("\nhalf test round: "+errorCount())
changes.view.reverse foreach (_.insertAll())
otherTest()
println("done test round: "+errorCount())
if (errorCount() != 0)
Some(ErrorTrace(sfidx, changes, reporter.infos, inputs(sfidx).content))
else
None
}
case class ErrorTrace(
sfidx: Int, changes: Seq[Change], infos: collection.Set[reporter.Info], content: Array[Char]) {
override def toString =
"Sourcefile: "+inputs(sfidx)+
"\nChanges:\n "+changes.mkString("\n ")+
"\nErrors:\n "+infos.mkString("\n ")+
"\nContents:\n"+content.mkString
}
def minimize(etrace: ErrorTrace) {}
/**/
def run() {
askReload(inputs: _*)
for (i <- 0 until ntests)
testFileChanges(randomSourceFileIdx())
}
}
/* A program to do presentation compiler stress tests.
* Usage:
*
* scala scala.tools.nsc.interactive.test.Tester <n> <files>
*
* where <n> is the number os tests to be run and <files> is the set of files to test.
* This will do random deletions and re-insertions in any of the files.
* At places where an empty comment /**/ appears it will in addition randomly
* do ask-types, type-completions, or scope-completions.
*/
object Tester {
def main(args: Array[String]) {
val settings = new Settings()
val (_, filenames) = settings.processArguments(args.toList.tail, true)
println("filenames = "+filenames)
val files = filenames.toArray map (str => new BatchSourceFile(AbstractFile.getFile(str)): SourceFile)
new Tester(args(0).toInt, files, settings).run()
sys.exit(0)
}
}