Skip to content

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

Merged
merged 25 commits into from
Apr 12, 2017

Conversation

felixmulder
Copy link
Contributor

@felixmulder felixmulder commented Apr 5, 2017

fixes: #2183
fixes: #2210

@felixmulder felixmulder requested a review from smarter April 5, 2017 08:52

def testFilter: Option[Regex] = sys.props.get("dotty.partest.filter").map(r => new Regex(r))
def maxDuration = 180.seconds
Copy link
Contributor Author

@felixmulder felixmulder Apr 5, 2017

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
Copy link
Member

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 {
Copy link
Member

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 {
Copy link
Member

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()
Copy link
Member

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
Copy link
Member

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))
Copy link
Member

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

Copy link
Member

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 {}
Copy link
Member

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")
Copy link
Member

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")
Copy link
Member

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?

Copy link
Member

@smarter smarter left a 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
Copy link
Member

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 {
Copy link
Member

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
Copy link
Member

@smarter smarter Apr 5, 2017

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?

Copy link
Contributor Author

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
Copy link
Member

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?

Copy link
Member

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?

@felixmulder felixmulder force-pushed the topic/hydra-part-2 branch 2 times, most recently from 081d928 to 7a63f42 Compare April 5, 2017 18:01
@odersky
Copy link
Contributor

odersky commented Apr 6, 2017

For the moment I cannot yet run CompilationTests instead of the old dotc.test as my standard test suite from Eclipse. There are three problems:

  1. My console window looks like this:

    [======================================>] compiling (205/206, 14s)
    [======================================>] compiling (205/206, 14s)
    [======================================>] compiling (205/206, 14s)
    [======================================>] compiling (205/206, 15s)
    [======================================>] compiling (205/206, 15s)
    [======================================>] compiling (205/206, 15s)
    [======================================>] compiling (205/206, 15s)
    [======================================>] compiling (205/206, 15s)
    

... and so on with 10 new entries per second. This fills all available lines and crowds out useful output.

  1. When a test fails I see something like this:

    java.lang.AssertionError: Neg test shouldn't have failed, but did
    at org.junit.Assert.fail(Assert.java:88)

It should at least tell me the name of the test that failed.

  1. It would be good to have an option to disable running tests. It takes a lot of time and if I work on the frontend I am rarely interested in that aspect.

@felixmulder
Copy link
Contributor Author

  1. My console window looks like this:

Hopefully fixed by 4d76b10

Gotta board the plane! Will look at the rest on board

@felixmulder
Copy link
Contributor Author

@odersky:

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 \r. It's the 21st century, what's going on?

(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
  1. It would be good to have an option to disable running tests. It takes a lot of time and if I work on the frontend I am rarely interested in that aspect.

How do you want to run this, from commandline or from eclipse? An sbt alias like testFrontend could be added, but then you'd have to invoke it from sbt.

We could also do it via properties or env...

@smarter
Copy link
Member

smarter commented Apr 6, 2017

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.

@DarkDimius
Copy link
Contributor

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.

@smarter
Copy link
Member

smarter commented Apr 6, 2017

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.

@felixmulder felixmulder force-pushed the topic/hydra-part-2 branch 2 times, most recently from 7966234 to a44d8f8 Compare April 7, 2017 13:23
/** 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)
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why though.

@felixmulder felixmulder force-pushed the topic/hydra-part-2 branch 3 times, most recently from bd0e317 to 280a0c8 Compare April 11, 2017 11:21
Copy link
Member

@smarter smarter left a 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")
Copy link
Member

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 {
Copy link
Member

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`
Copy link
Member

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 {
Copy link
Member

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
Copy link
Member

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 {
Copy link
Member

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reproduction, not reproduce

Copy link
Member

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] = {
Copy link
Member

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 =
Copy link
Member

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

val args: Seq[String] = spaceDelimited("<arg>").parsed
testOptions := Seq()
val realArgs = if (args.nonEmpty) args else Seq(".*")
Copy link
Member

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 :).

@felixmulder felixmulder merged commit d541452 into scala:master Apr 12, 2017
@allanrenucci allanrenucci deleted the topic/hydra-part-2 branch December 14, 2017 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missing information in Vulpix test logs Remove old partest
4 participants