-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Killing partest part 2 - Enter the Vulpix #2194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
||
def testFilter: Option[Regex] = sys.props.get("dotty.partest.filter").map(r => new Regex(r)) | ||
def maxDuration = 180.seconds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note - we have some tests that run for quite a long time. In most cases these are benchmarks. But there are some which aren't and run for up to 60 seconds.
I propose to have a split between these run tests and the regular run tests in:
./tests/run-long/
And have an interface for them which allows for longer execution.
@@ -1,13 +1,14 @@ | |||
package dotty | |||
package tools | |||
package dotc | |||
package vulpix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if it shouldn't just be dotty.tools.vulpix
:)
import scala.concurrent.duration.Duration | ||
import scala.collection.mutable | ||
|
||
trait RunnerOrchestration { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some documentation explaining what this is and how it works here?
|
||
private[this] val monitor = new RunnerMonitor | ||
|
||
private class RunnerMonitor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docs here too plz
private[this] val busyRunners = mutable.Set.empty[Runner] | ||
|
||
private def getRunner(): Runner = synchronized { | ||
while (freeRunners.isEmpty) wait() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks correct, but I've forgotten everything I ever knew about Java concurrency, are you sure there's no existing higher-level concurrency thing from https://docs.oracle.com/javase/8/docs/api/?java/util/concurrent/package-summary.html you could use instead of the wait/notify dance ?
def testFilter: Option[Regex] = sys.props.get("dotty.partest.filter").map(r => new Regex(r)) | ||
def maxDuration = 3.seconds | ||
def numberOfSlaves = 5 | ||
def safeMode = sys.env.get("SAFEMODE").isDefined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer dotty.tests.safemode
def numberOfSlaves = 5 | ||
def safeMode = sys.env.get("SAFEMODE").isDefined | ||
def isInteractive = SummaryReport.isInteractive | ||
def testFilter = sys.props.get("dotty.partest.filter").map(r => new Regex(r)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here dotty.tests.filter
, that way all the properties related to testing are in the dotty.tests
namespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, we should have documentation for all these properties in one place, and it would be good if we limited string handling to one place too, I suggest having something like:
object DottyTestsProperties {
// *Documentation of what safeMode is*
def safeMode = sys.props.get("dotty.partest.filter")
...
}
public Failure(String output) { this.output = output; } | ||
} | ||
|
||
static class Timeout implements Status, Serializable {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something that a child JVM can send? Otherwise it should not be part of Status
assuming Status
defines the communication protocol between the JVMs.
private def createProcess: Process = ??? | ||
private def createProcess: Process = { | ||
val sep = sys.props("file.separator") | ||
val cp = sys.props("java.class.path") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes me sad, but I won't disallow that for now.
private def runMain(dir: JFile): Status = { | ||
def renderStackTrace(ex: Throwable): String = | ||
ex.getStackTrace | ||
.takeWhile(_.getMethodName != "invoke0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this for? I think I'd be happier not having my stack traces mangled in some undocumented way, what if I have a test with an invoke0 method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to add some of the meta-tests proposed by @DarkDimius: #2125 (review)
.drone.yml
Outdated
- ;set testOptions in LocalProject("dotty-compiler-bootstrapped") += Tests.Argument(TestFrameworks.JUnit, "--exclude-categories=dotty.tools.dotc.hydra.ParallelTesting") ;partest-only --show-diff --verbose | ||
- ;dotty-compiler/testOnly dotty.tools.dotc.CompilationTests | ||
- ;publishLocal ;dotty-bootstrapped/testOnly dotty.tools.dotc.CompilationTests | ||
- test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should still be running the old JUnit tests with the CI.
import scala.util.control.NonFatal | ||
|
||
class ParallelTestTests extends ParallelTesting { | ||
class VulpixTests extends ParallelTesting { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some documentation on what this is for.
|
||
object comptest extends ParallelTesting { | ||
|
||
def maxDuration = 3.seconds | ||
def numberOfSlaves = 5 | ||
def safeMode = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this different from the other overrides of safeMode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a legacy main used by some folks in the lab - it's only running a single test. No need to restart VMs after this single test.
trait RunnerOrchestration { | ||
|
||
/** The maximum amount of active runners, which contain a child JVM */ | ||
def numberOfSlaves: Int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is always overriden as 5, why not make it the default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, why isn't this based on the number of CPUs?
081d928
to
7a63f42
Compare
For the moment I cannot yet run CompilationTests instead of the old
... and so on with 10 new entries per second. This fills all available lines and crowds out useful output.
It should at least tell me the name of the test that failed.
|
Hopefully fixed by 4d76b10 Gotta board the plane! Will look at the rest on board |
4d76b10
to
84917a3
Compare
Fixed (1) in 84917a3 instead. You'll now need to set property "dotty.tests.interactive" to "FALSE" to have the tests run without interactive progress bar. Apparently eclipse had to revert a fix that handled (2): could you gist or otherwise add the console output here? You can use <details>paste all the things here</details> Which results in: paste all the things here
How do you want to run this, from commandline or from eclipse? An sbt alias like We could also do it via properties or env... |
I'd say, make everything a flag and a property, so people who use IDEs can set the property, and people who use sbt can use the flag which is more convenient. |
I'm not sure if having two side-channels is a good thing. I'd strongly prefer to have no more than one. |
No it's fine, the sbt flag just needs to set the property, so you only have one side-channel in the end. |
7966234
to
a44d8f8
Compare
a44d8f8
to
1fff140
Compare
/** This class adds summary reports to `ParallelTesting` | ||
* | ||
* It is written in Java because we currently cannot explicitly write static | ||
* methods in Scala without SIP-25 (`@static` fields and methods in Scala) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you only need static methods, isn't using a scala-defined object sufficient? The compiler will emit a corresponding class with static methods forwarding to the object's methods for interoperability with Java.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't work with JUnit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But why though.
bd0e317
to
280a0c8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise LGTM, looking forward to playing with it more!
@@ -52,6 +51,15 @@ trait ParallelTesting { self => | |||
def outDir: JFile | |||
def flags: Array[String] | |||
|
|||
def classPath: String = { | |||
val (beforeCp, cpAndAfter) = flags.toList.span(_ != "-classpath") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just do:
flags.dropWhile(_ != "-classpath").drop(1).headOption
protected final val realStdout = System.out | ||
protected final val realStderr = System.err | ||
|
||
/** A runnable that logs its contents in a buffer */ | ||
trait LoggedRunnable extends Runnable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this doesn't use anything from the outer class, it should not be an inner class, and preferably it should be in its own file.
summaryReport.addStartingMessage { | ||
"""|WARNING | ||
|------- | ||
|Run tests were only compiled, not run - this is due to `dotty.tests.norun` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
due to the
if (!compilerCrashed && errorCount == 0 && hasCheckFile) verifier() | ||
else if (!compilerCrashed && errorCount == 0) { | ||
if (Properties.testsNoRun) addNoRunWarning() | ||
else runMain(testSource.classPath) match { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like the repetition with verifyOutput
above here, would be nicer if we pretended that all tests had a check file (no check file would be equivalent to empty check file).
childStdin = null | ||
} | ||
|
||
private[this] var didAddCleanup = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document this variable, and maybe give it a nicer name?
import scala.collection.mutable | ||
import dotc.reporting.TestReporter | ||
|
||
trait SummaryReporting { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some documentation in this file, what's a SummaryReporting? What's a SummaryReport? Also, the fact that these are two different classes with very similar name is confusing, maybe use SummaryReport and DefaultSummaryReport; I'm not sure.
|
||
failedTests.map(x => " " + x).foreach(rep.append) | ||
|
||
// If we're compiling locally, we don't need reproduce instructions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reproduction, not reproduce
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I disagree, I want reproduction instructions, please make it an option at least :).
implicit val defaultOutputDir: String = "../out/" | ||
|
||
implicit class RichStringArray(val xs: Array[String]) extends AnyVal { | ||
def and(args: String*): Array[String] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
@@ -55,4 +61,16 @@ class ParallelTestTests extends ParallelTesting { | |||
|
|||
@Test def runOutRedirects: Unit = | |||
compileFile("../tests/partest-test/i2147.scala", defaultOptions).expectFailure.checkRuns() | |||
|
|||
@Test def infiteNonRec: Unit = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: infite -> infinite, same below
project/Build.scala
Outdated
val args: Seq[String] = spaceDelimited("<arg>").parsed | ||
testOptions := Seq() | ||
val realArgs = if (args.nonEmpty) args else Seq(".*") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, just change the filter to contain the regexp you pass as argument instead of being equal to it :).
Note that merging this as-is will not protect us against fork bombs. This is because the timeout of tests is currently 180 seconds. A forkbomb that is allowed to run for that long...
280a0c8
to
e8b695d
Compare
e8b695d
to
f6d519a
Compare
fixes: #2183
fixes: #2210