mirror of https://github.com/sbt/sbt.git
Fix #3013: ScriptedPlugin: Add support for paginated tests
This was already supported in the internal Scripted used by sbt but not in the ScriptedPlugin. This is fixed by just copy-pasting the modified parser. We will have to wait for sbt itself to be built using an sbt with the upgraded ScriptedPlugin to be able to avoid the code duplication.
This commit is contained in:
parent
a7413f6415
commit
052face8ee
|
|
@ -0,0 +1,12 @@
|
|||
### Improvements
|
||||
|
||||
- ScriptedPlugin: Add the ability to paginate scripted tests.
|
||||
It is now possible to run a subset of scripted tests in a directory at once,
|
||||
for example:
|
||||
```
|
||||
scripted source-dependencies/*1of3
|
||||
```
|
||||
Will create three pages and run page 1. This is especially useful when running
|
||||
scripted tests on a CI, to benefit from the available parallelism.
|
||||
[3013]: https://github.com/sbt/sbt/pull/3013
|
||||
[@smarter]: https://github.com/smarter
|
||||
|
|
@ -19,6 +19,8 @@ object Scripted {
|
|||
import DefaultParsers._
|
||||
// Paging, 1-index based.
|
||||
case class ScriptedTestPage(page: Int, total: Int)
|
||||
// FIXME: Duplicated with ScriptedPlugin.scriptedParser, this can be
|
||||
// avoided once we upgrade build.properties to 0.13.14
|
||||
def scriptedParser(scriptedBase: File): Parser[Seq[String]] =
|
||||
{
|
||||
val scriptedFiles: NameFilter = ("test": NameFilter) | "pending"
|
||||
|
|
|
|||
|
|
@ -38,20 +38,51 @@ object ScriptedPlugin extends Plugin {
|
|||
m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[Array[String]], classOf[File], classOf[Array[String]])
|
||||
}
|
||||
|
||||
private def scriptedParser(scriptedBase: File): Parser[Seq[String]] =
|
||||
import DefaultParsers._
|
||||
case class ScriptedTestPage(page: Int, total: Int)
|
||||
|
||||
private[sbt] def scriptedParser(scriptedBase: File): Parser[Seq[String]] =
|
||||
{
|
||||
import DefaultParsers._
|
||||
val pairs = (scriptedBase * AllPassFilter * AllPassFilter * "test").get map { (f: File) =>
|
||||
|
||||
val scriptedFiles: NameFilter = ("test": NameFilter) | "pending"
|
||||
val pairs = (scriptedBase * AllPassFilter * AllPassFilter * scriptedFiles).get map { (f: File) =>
|
||||
val p = f.getParentFile
|
||||
(p.getParentFile.getName, p.getName)
|
||||
}
|
||||
val pairMap = pairs.groupBy(_._1).mapValues(_.map(_._2).toSet)
|
||||
val pairMap = pairs.groupBy(_._1).mapValues(_.map(_._2).toSet);
|
||||
|
||||
val id = charClass(c => !c.isWhitespace && c != '/').+.string
|
||||
val groupP = token(id.examples(pairMap.keySet)) <~ token('/')
|
||||
def nameP(group: String) = token("*".id | id.examples(pairMap(group)))
|
||||
val testID = for (group <- groupP; name <- nameP(group)) yield (group, name)
|
||||
(token(Space) ~> matched(testID)).*
|
||||
val groupP = token(id.examples(pairMap.keySet.toSet)) <~ token('/')
|
||||
|
||||
// A parser for page definitions
|
||||
val pageP: Parser[ScriptedTestPage] = ("*" ~ NatBasic ~ "of" ~ NatBasic) map {
|
||||
case _ ~ page ~ _ ~ total => ScriptedTestPage(page, total)
|
||||
}
|
||||
// Grabs the filenames from a given test group in the current page definition.
|
||||
def pagedFilenames(group: String, page: ScriptedTestPage): Seq[String] = {
|
||||
val files = pairMap(group).toSeq.sortBy(_.toLowerCase)
|
||||
val pageSize = files.size / page.total
|
||||
// The last page may loose some values, so we explicitly keep them
|
||||
val dropped = files.drop(pageSize * (page.page - 1))
|
||||
if (page.page == page.total) dropped
|
||||
else dropped.take(pageSize)
|
||||
}
|
||||
def nameP(group: String) = {
|
||||
token("*".id | id.examples(pairMap(group)))
|
||||
}
|
||||
val PagedIds: Parser[Seq[String]] =
|
||||
for {
|
||||
group <- groupP
|
||||
page <- pageP
|
||||
files = pagedFilenames(group, page)
|
||||
// TODO - Fail the parser if we don't have enough files for the given page size
|
||||
//if !files.isEmpty
|
||||
} yield files map (f => group + '/' + f)
|
||||
|
||||
val testID = (for (group <- groupP; name <- nameP(group)) yield (group, name))
|
||||
val testIdAsGroup = matched(testID) map (test => Seq(test))
|
||||
//(token(Space) ~> matched(testID)).*
|
||||
(token(Space) ~> (PagedIds | testIdAsGroup)).* map (_.flatten)
|
||||
}
|
||||
|
||||
def scriptedTask: Initialize[InputTask[Unit]] = Def.inputTask {
|
||||
|
|
|
|||
Loading…
Reference in New Issue