summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-10-26 22:38:03 -0700
committerLi Haoyi <haoyi.sg@gmail.com>2017-10-26 22:38:03 -0700
commitafd5de935cb11394848c5040909f2f02fc26335f (patch)
tree031dddb0f055ff307e4aa3276a9e7f32997e684f /src/test
parentd8c23bbf9063404c334bf2abc9ad102729126ead (diff)
downloadmill-afd5de935cb11394848c5040909f2f02fc26335f.tar.gz
mill-afd5de935cb11394848c5040909f2f02fc26335f.tar.bz2
mill-afd5de935cb11394848c5040909f2f02fc26335f.zip
- Split out `ForgeTests` into `EvaluatioNTests` and `GraphTests`
- Added a non-trivial test graph to our test suite EvaluationTests have broken, need to fix
Diffstat (limited to 'src/test')
-rw-r--r--src/test/scala/forge/EvaluationTests.scala122
-rw-r--r--src/test/scala/forge/ForgeTests.scala309
-rw-r--r--src/test/scala/forge/GraphTests.scala203
-rw-r--r--src/test/scala/forge/TestUtil.scala78
4 files changed, 403 insertions, 309 deletions
diff --git a/src/test/scala/forge/EvaluationTests.scala b/src/test/scala/forge/EvaluationTests.scala
new file mode 100644
index 00000000..34ebd684
--- /dev/null
+++ b/src/test/scala/forge/EvaluationTests.scala
@@ -0,0 +1,122 @@
+package forge
+
+import java.nio.{file => jnio}
+
+import forge.Target.test
+import utest._
+
+object EvaluationTests extends TestSuite{
+
+ val tests = Tests{
+ val baseCtx = DefCtx("forge.ForgeTests.tests ", None)
+
+ val (singleton, pair, anonTriple, diamond, anonDiamond, bigSingleTerminal) = TestUtil.makeGraphs()
+ 'evaluateSingle - {
+ val evaluator = new Evaluator(jnio.Paths.get("target/workspace"), baseCtx)
+
+ def check(target: Target[_], expValue: Any, expEvaled: Seq[Target[_]]) = {
+ val Evaluator.Results(returnedValues, returnedEvaluated) = evaluator.evaluate(Seq(target))
+ assert(
+ returnedValues == Seq(expValue),
+ returnedEvaluated == expEvaled
+ )
+ // Second time the value is already cached, so no evaluation needed
+ val Evaluator.Results(returnedValues2, returnedEvaluated2) = evaluator.evaluate(Seq(target))
+ assert(
+ returnedValues2 == returnedValues,
+ returnedEvaluated2 == Nil
+ )
+ }
+
+ 'singleton - {
+ import singleton._
+ // First time the target is evaluated
+ check(single, expValue = 0, expEvaled = Seq(single))
+
+ single.counter += 1
+ // After incrementing the counter, it forces re-evaluation
+ check(single, expValue = 1, expEvaled = Seq(single))
+ }
+ 'pair - {
+ import pair._
+ check(down, expValue = 0, expEvaled = Seq(up, down))
+
+ down.counter += 1
+ check(down, expValue = 1, expEvaled = Seq(down))
+
+ up.counter += 1
+ check(down, expValue = 2, expEvaled = Seq(up, down))
+ }
+ 'anonTriple - {
+ import anonTriple._
+ val middle = down.inputs(0)
+ check(down, expValue = 0, expEvaled = Seq(up, middle, down))
+
+ down.counter += 1
+ check(down, expValue = 1, expEvaled = Seq(down))
+
+ up.counter += 1
+ check(down, expValue = 2, expEvaled = Seq(up, middle, down))
+
+ middle.asInstanceOf[Target.Test].counter += 1
+
+ check(down, expValue = 3, expEvaled = Seq(middle, down))
+ }
+ 'diamond - {
+ import diamond._
+ check(down, expValue = 0, expEvaled = Seq(up, left, right, down))
+
+ down.counter += 1
+ check(down, expValue = 1, expEvaled = Seq(down))
+
+ up.counter += 1
+ // Increment by 2 because up is referenced twice: once by left once by right
+ check(down, expValue = 3, expEvaled = Seq(up, left, right, down))
+
+ left.counter += 1
+ check(down, expValue = 4, expEvaled = Seq(left, down))
+
+ right.counter += 1
+ check(down, expValue = 5, expEvaled = Seq(right, down))
+ }
+ 'anonDiamond - {
+ import anonDiamond._
+ val left = down.inputs(0).asInstanceOf[Target.Test]
+ val right = down.inputs(1).asInstanceOf[Target.Test]
+ check(down, expValue = 0, expEvaled = Seq(up, left, right, down))
+
+ down.counter += 1
+ check(down, expValue = 1, expEvaled = Seq(down))
+
+ up.counter += 1
+ // Increment by 2 because up is referenced twice: once by left once by right
+ check(down, expValue = 3, expEvaled = Seq(up, left, right, down))
+
+ left.counter += 1
+ check(down, expValue = 4, expEvaled = Seq(left, down))
+
+ right.counter += 1
+ check(down, expValue = 5, expEvaled = Seq(right, down))
+ }
+// 'anonImpureDiamond - {
+// import AnonImpureDiamond._
+// val left = down.inputs(0).asInstanceOf[Target.Test]
+// val right = down.inputs(1).asInstanceOf[Target.Test]
+// check(down, expValue = 0, expEvaled = Seq(up, left, right, down))
+//
+// down.counter += 1
+// check(down, expValue = 1, expEvaled = Seq(left, down))
+// }
+ }
+
+
+// 'full - {
+// val sourceRoot = Target.path(jnio.Paths.get("src/test/resources/example/src"))
+// val resourceRoot = Target.path(jnio.Paths.get("src/test/resources/example/resources"))
+// val allSources = list(sourceRoot)
+// val classFiles = compileAll(allSources)
+// val jar = jarUp(resourceRoot, classFiles)
+// Evaluator.apply(jar, jnio.Paths.get("target/workspace"))
+// }
+ }
+}
diff --git a/src/test/scala/forge/ForgeTests.scala b/src/test/scala/forge/ForgeTests.scala
deleted file mode 100644
index 5e9d8e37..00000000
--- a/src/test/scala/forge/ForgeTests.scala
+++ /dev/null
@@ -1,309 +0,0 @@
-package forge
-
-import utest._
-import Target.test
-import java.nio.{file => jnio}
-object ForgeTests extends TestSuite{
-
- val tests = Tests{
- val baseCtx = DefCtx("forge.ForgeTests.tests ", None)
-
- object Singleton {
- val single = T{ test() }
- }
- object Pair {
- val up = T{ test() }
- val down = T{ test(up) }
- }
-
- object AnonTriple{
- val up = T{ test() }
- val down = T{ test(test(up)) }
- }
- object Diamond{
- val up = T{ test() }
- val left = T{ test(up) }
- val right = T{ test(up) }
- val down = T{ test(left, right) }
- }
- object AnonDiamond{
- val up = T{ test() }
- val down = T{ test(test(up), test(up)) }
- }
-
- object AnonImpureDiamond{
- val up = T{ test() }
- val down = T{ test(test(up), test(up)) }
- }
-
-
- 'syntaxLimits - {
- // Make sure that we properly prohibit cases where a `test()` target can
- // be created more than once with the same `DefCtx`, while still allowing
- // cases where the `test()` target is created exactly one time, or even
- // zero-or-one times (since that's ok, as long as it's not more than once)
-
- 'neg - {
- 'nakedTest - {
- compileError("test()")
- ()
- }
- 'notFunctionCall - {
- compileError("T{ 123 }")
- ()
- }
- 'functionCallWithoutImplicit - {
- compileError("T{ println() }")
- ()
- }
- // Make sure the snippets without `test()`s compile, but the same snippets
- // *with* the `test()` calls do not (presumably due to the `@compileTimeOnly`
- // annotation)
- //
- // For some reason, `if(false)` isn't good enough because scalac constant
- // folds the conditional, eliminates the entire code block, and makes any
- // `@compileTimeOnly`s annotations disappear...
-
-
- 'canEvaluateMoreThanOnce - {
- if (math.random() > 10) T{ Seq(1, 2).map(_ => ???); test() }
- compileError("T{ Seq(1, 2).map(_ => test()); test() }")
-
- if (math.random() > 10) T{ class Foo{ ??? }; test() }
- compileError("T{ class Foo{ test() }; test() }")
-
- if (math.random() > 10) T{ test({while(true){ }; ???}) }
- compileError("T{ test({while(true){ test() }; ???}) }")
-
- if (math.random() > 10) T{ do{ } while(true); test() }
- compileError("T{ do{ test() } while(true); test() }")
-
- if (math.random() > 10) T{ def foo() = ???; test() }
- compileError("T{ def foo() = test(); test() }")
-
- if (math.random() > 10) T{ None.getOrElse(???); test() }
- if (math.random() > 10) T{ None.contains(test()); test() }
- compileError("T{ None.getOrElse(test()); test() }")
-
- ()
- }
- }
- 'pos - {
- T{ test({val x = test(); x}) }
- T{ test({lazy val x = test(); x}) }
- T { object foo {val x = test()}; test(foo.x) }
- T{ test({val x = if (math.random() > 0.5) test() else test(); x}) }
-
- ()
- }
- }
-
-
- 'topoSortedTransitiveTargets - {
- def check(targets: Seq[Target[_]], expected: Seq[Target[_]]) = {
- val result = Evaluator.topoSortedTransitiveTargets(targets).values
- assert(result == expected)
- }
-
- 'singleton - check(
- targets = Seq(Singleton.single),
- expected = Seq(Singleton.single)
- )
- 'pair - check(
- targets = Seq(Pair.down),
- expected = Seq(Pair.up, Pair.down)
- )
- 'anonTriple - check(
- targets = Seq(AnonTriple.down),
- expected = Seq(AnonTriple.up, AnonTriple.down.inputs(0), AnonTriple.down)
- )
- 'diamond - check(
- targets = Seq(Diamond.down),
- expected = Seq(Diamond.up, Diamond.left, Diamond.right, Diamond.down)
- )
- 'anonDiamond - check(
- targets = Seq(Diamond.down),
- expected = Seq(
- Diamond.up,
- Diamond.down.inputs(0),
- Diamond.down.inputs(1),
- Diamond.down
- )
- )
- }
-
- 'groupAroundNamedTargets - {
- def check(target: Target[_], expected: Seq[Seq[Target[_]]]) = {
- val grouped = Evaluator.groupAroundNamedTargets(
- Evaluator.topoSortedTransitiveTargets(Seq(target))
- )
- assert(grouped == expected)
- }
- 'singleton - check(
- Singleton.single,
- Seq(Seq(Singleton.single))
- )
- 'pair - check(
- Pair.down,
- Seq(Seq(Pair.up), Seq(Pair.down))
- )
- 'anonTriple - check(
- AnonTriple.down,
- Seq(Seq(AnonTriple.up), Seq(AnonTriple.down.inputs(0), AnonTriple.down))
- )
- 'diamond - check(
- Diamond.down,
- Seq(Seq(Diamond.up), Seq(Diamond.left), Seq(Diamond.right), Seq(Diamond.down))
- )
- 'anonDiamond - check(
- AnonDiamond.down,
- Seq(
- Seq(AnonDiamond.up),
- Seq(AnonDiamond.down.inputs(1), AnonDiamond.down.inputs(0), AnonDiamond.down)
- )
- )
- }
-
- 'labeling - {
-
- def check(t: Target[_], relPath: String) = {
- val targetLabel = t.defCtx.label
- val expectedLabel = baseCtx.label + relPath
- assert(targetLabel == expectedLabel)
- }
- 'singleton - check(Singleton.single, "Singleton.single")
- 'pair - {
- check(Pair.up, "Pair.up")
- check(Pair.down, "Pair.down")
- }
-
- 'anonTriple - {
- check(AnonTriple.up, "AnonTriple.up")
- check(AnonTriple.down.inputs(0), "AnonTriple.down1")
- check(AnonTriple.down, "AnonTriple.down")
- }
-
- 'diamond - {
- check(Diamond.up, "Diamond.up")
- check(Diamond.left, "Diamond.left")
- check(Diamond.right, "Diamond.right")
- check(Diamond.down, "Diamond.down")
- }
-
- 'anonDiamond - {
- check(AnonDiamond.up, "AnonDiamond.up")
- check(AnonDiamond.down.inputs(0), "AnonDiamond.down1")
- check(AnonDiamond.down.inputs(1), "AnonDiamond.down2")
- check(AnonDiamond.down, "AnonDiamond.down")
- }
-
- }
- 'evaluateSingle - {
- val evaluator = new Evaluator(jnio.Paths.get("target/workspace"), baseCtx)
-
- def check(target: Target[_], expValue: Any, expEvaled: Seq[Target[_]]) = {
- val Evaluator.Results(returnedValues, returnedEvaluated) = evaluator.evaluate(Seq(target))
- assert(
- returnedValues == Seq(expValue),
- returnedEvaluated == expEvaled
- )
- // Second time the value is already cached, so no evaluation needed
- val Evaluator.Results(returnedValues2, returnedEvaluated2) = evaluator.evaluate(Seq(target))
- assert(
- returnedValues2 == returnedValues,
- returnedEvaluated2 == Nil
- )
- }
-
- 'singleton - {
- import Singleton._
- // First time the target is evaluated
- check(single, expValue = 0, expEvaled = Seq(single))
-
- single.counter += 1
- // After incrementing the counter, it forces re-evaluation
- check(single, expValue = 1, expEvaled = Seq(single))
- }
- 'pair - {
- import Pair._
- check(down, expValue = 0, expEvaled = Seq(up, down))
-
- down.counter += 1
- check(down, expValue = 1, expEvaled = Seq(down))
-
- up.counter += 1
- check(down, expValue = 2, expEvaled = Seq(up, down))
- }
- 'anonTriple - {
- import AnonTriple._
- val middle = down.inputs(0)
- check(down, expValue = 0, expEvaled = Seq(up, middle, down))
-
- down.counter += 1
- check(down, expValue = 1, expEvaled = Seq(down))
-
- up.counter += 1
- check(down, expValue = 2, expEvaled = Seq(up, middle, down))
-
- middle.asInstanceOf[Target.Test].counter += 1
-
- check(down, expValue = 3, expEvaled = Seq(middle, down))
- }
- 'diamond - {
- import Diamond._
- check(down, expValue = 0, expEvaled = Seq(up, left, right, down))
-
- down.counter += 1
- check(down, expValue = 1, expEvaled = Seq(down))
-
- up.counter += 1
- // Increment by 2 because up is referenced twice: once by left once by right
- check(down, expValue = 3, expEvaled = Seq(up, left, right, down))
-
- left.counter += 1
- check(down, expValue = 4, expEvaled = Seq(left, down))
-
- right.counter += 1
- check(down, expValue = 5, expEvaled = Seq(right, down))
- }
- 'anonDiamond - {
- import AnonDiamond._
- val left = down.inputs(0).asInstanceOf[Target.Test]
- val right = down.inputs(1).asInstanceOf[Target.Test]
- check(down, expValue = 0, expEvaled = Seq(up, left, right, down))
-
- down.counter += 1
- check(down, expValue = 1, expEvaled = Seq(down))
-
- up.counter += 1
- // Increment by 2 because up is referenced twice: once by left once by right
- check(down, expValue = 3, expEvaled = Seq(up, left, right, down))
-
- left.counter += 1
- check(down, expValue = 4, expEvaled = Seq(left, down))
-
- right.counter += 1
- check(down, expValue = 5, expEvaled = Seq(right, down))
- }
-// 'anonImpureDiamond - {
-// import AnonImpureDiamond._
-// val left = down.inputs(0).asInstanceOf[Target.Test]
-// val right = down.inputs(1).asInstanceOf[Target.Test]
-// check(down, expValue = 0, expEvaled = Seq(up, left, right, down))
-//
-// down.counter += 1
-// check(down, expValue = 1, expEvaled = Seq(left, down))
-// }
- }
-
-
-// 'full - {
-// val sourceRoot = Target.path(jnio.Paths.get("src/test/resources/example/src"))
-// val resourceRoot = Target.path(jnio.Paths.get("src/test/resources/example/resources"))
-// val allSources = list(sourceRoot)
-// val classFiles = compileAll(allSources)
-// val jar = jarUp(resourceRoot, classFiles)
-// Evaluator.apply(jar, jnio.Paths.get("target/workspace"))
-// }
- }
-}
diff --git a/src/test/scala/forge/GraphTests.scala b/src/test/scala/forge/GraphTests.scala
new file mode 100644
index 00000000..85b63131
--- /dev/null
+++ b/src/test/scala/forge/GraphTests.scala
@@ -0,0 +1,203 @@
+package forge
+
+import utest._
+import Target.test
+import java.nio.{file => jnio}
+
+object GraphTests extends TestSuite{
+
+ val tests = Tests{
+
+
+ val (singleton, pair, anonTriple, diamond, anonDiamond, bigSingleTerminal) = TestUtil.makeGraphs()
+
+
+ 'syntaxLimits - {
+ // Make sure that we properly prohibit cases where a `test()` target can
+ // be created more than once with the same `DefCtx`, while still allowing
+ // cases where the `test()` target is created exactly one time, or even
+ // zero-or-one times (since that's ok, as long as it's not more than once)
+
+ 'neg - {
+ 'nakedTest - {
+ compileError("test()")
+ ()
+ }
+ 'notFunctionCall - {
+ compileError("T{ 123 }")
+ ()
+ }
+ 'functionCallWithoutImplicit - {
+ compileError("T{ println() }")
+ ()
+ }
+ // Make sure the snippets without `test()`s compile, but the same snippets
+ // *with* the `test()` calls do not (presumably due to the `@compileTimeOnly`
+ // annotation)
+ //
+ // For some reason, `if(false)` isn't good enough because scalac constant
+ // folds the conditional, eliminates the entire code block, and makes any
+ // `@compileTimeOnly`s annotations disappear...
+
+
+ 'canEvaluateMoreThanOnce - {
+ if (math.random() > 10) T{ Seq(1, 2).map(_ => ???); test() }
+ compileError("T{ Seq(1, 2).map(_ => test()); test() }")
+
+ if (math.random() > 10) T{ class Foo{ ??? }; test() }
+ compileError("T{ class Foo{ test() }; test() }")
+
+ if (math.random() > 10) T{ test({while(true){ }; ???}) }
+ compileError("T{ test({while(true){ test() }; ???}) }")
+
+ if (math.random() > 10) T{ do{ } while(true); test() }
+ compileError("T{ do{ test() } while(true); test() }")
+
+ if (math.random() > 10) T{ def foo() = ???; test() }
+ compileError("T{ def foo() = test(); test() }")
+
+ if (math.random() > 10) T{ None.getOrElse(???); test() }
+ if (math.random() > 10) T{ None.contains(test()); test() }
+ compileError("T{ None.getOrElse(test()); test() }")
+
+ ()
+ }
+ }
+ 'pos - {
+ T{ test({val x = test(); x}) }
+ T{ test({lazy val x = test(); x}) }
+ T { object foo {val x = test()}; test(foo.x) }
+ T{ test({val x = if (math.random() > 0.5) test() else test(); x}) }
+
+ ()
+ }
+ }
+
+
+ 'topoSortedTransitiveTargets - {
+ def check(targets: Seq[Target[_]], expected: Set[Target[_]]) = {
+ val result = Evaluator.topoSortedTransitiveTargets(targets).values
+ TestUtil.checkTopological(result)
+ assert(result.toSet == expected)
+ }
+
+ 'singleton - check(
+ targets = Seq(singleton.single),
+ expected = Set(singleton.single)
+ )
+ 'pair - check(
+ targets = Seq(pair.down),
+ expected = Set(pair.up, pair.down)
+ )
+ 'anonTriple - check(
+ targets = Seq(anonTriple.down),
+ expected = Set(anonTriple.up, anonTriple.down.inputs(0), anonTriple.down)
+ )
+ 'diamond - check(
+ targets = Seq(diamond.down),
+ expected = Set(diamond.up, diamond.left, diamond.right, diamond.down)
+ )
+ 'anonDiamond - check(
+ targets = Seq(diamond.down),
+ expected = Set(
+ diamond.up,
+ diamond.down.inputs(0),
+ diamond.down.inputs(1),
+ diamond.down
+ )
+ )
+ 'bigSingleTerminal - {
+ val result = Evaluator.topoSortedTransitiveTargets(Seq(bigSingleTerminal.j)).values
+ TestUtil.checkTopological(result)
+ assert(result.distinct.length == 28)
+ }
+ }
+
+ 'groupAroundNamedTargets - {
+ def check(target: Target[_], expected: Seq[Set[String]]) = {
+ val grouped = Evaluator.groupAroundNamedTargets(
+ Evaluator.topoSortedTransitiveTargets(Seq(target))
+ )
+ TestUtil.checkTopological(grouped.flatten)
+ val stringified = grouped.map(_.map(_.toString).toSet)
+ assert(stringified == expected.map(_.toSet))
+ }
+ 'singleton - check(
+ singleton.single,
+ Seq(Set("single"))
+ )
+ 'pair - check(
+ pair.down,
+ Seq(Set("up"), Set("down"))
+ )
+ 'anonTriple - check(
+ anonTriple.down,
+ Seq(Set("up"), Set("down1", "down"))
+ )
+ 'diamond - check(
+ diamond.down,
+ Seq(Set("up"), Set("left"), Set("right"), Set("down"))
+ )
+ 'anonDiamond - check(
+ anonDiamond.down,
+ Seq(
+ Set("up"),
+ Set("down2", "down1", "down")
+ )
+ )
+ 'bigSingleTerminal - check(
+ bigSingleTerminal.j,
+ Seq(
+ Set("i1"),
+ Set("e4"),
+ Set("a1"),
+ Set("a2"),
+ Set("a"),
+ Set("b1"),
+ Set("b"),
+ Set("e5", "e2", "e8", "e1", "e7", "e6", "e3", "e"),
+ Set("i2", "i5", "i4", "i3", "i"),
+ Set("f2"),
+ Set("f3", "f1", "f"),
+ Set("j3", "j2", "j1", "j")
+ )
+ )
+ }
+
+ 'labeling - {
+
+ def check(t: Target[_], relPath: String) = {
+ val targetLabel = t.defCtx.label.split(' ').last
+
+ assert(targetLabel == relPath)
+ }
+ 'singleton - check(singleton.single, "singleton.single")
+ 'pair - {
+ check(pair.up, "pair.up")
+ check(pair.down, "pair.down")
+ }
+
+ 'anonTriple - {
+ check(anonTriple.up, "anonTriple.up")
+ check(anonTriple.down.inputs(0), "anonTriple.down1")
+ check(anonTriple.down, "anonTriple.down")
+ }
+
+ 'diamond - {
+ check(diamond.up, "diamond.up")
+ check(diamond.left, "diamond.left")
+ check(diamond.right, "diamond.right")
+ check(diamond.down, "diamond.down")
+ }
+
+ 'anonDiamond - {
+ check(anonDiamond.up, "anonDiamond.up")
+ check(anonDiamond.down.inputs(0), "anonDiamond.down1")
+ check(anonDiamond.down.inputs(1), "anonDiamond.down2")
+ check(anonDiamond.down, "anonDiamond.down")
+ }
+
+ }
+
+ }
+}
diff --git a/src/test/scala/forge/TestUtil.scala b/src/test/scala/forge/TestUtil.scala
new file mode 100644
index 00000000..5a328d87
--- /dev/null
+++ b/src/test/scala/forge/TestUtil.scala
@@ -0,0 +1,78 @@
+package forge
+
+import forge.Target.test
+import utest.assert
+
+import scala.collection.mutable
+
+object TestUtil {
+
+ def checkTopological(targets: Seq[Target[_]]) = {
+ val seen = mutable.Set.empty[Target[_]]
+ for(t <- targets.reverseIterator){
+ seen.add(t)
+ for(upstream <- t.inputs){
+ assert(!seen(upstream))
+ }
+ }
+ }
+
+ def makeGraphs() = {
+ object singleton {
+ val single = T{ test() }
+ }
+ object pair {
+ val up = T{ test() }
+ val down = T{ test(up) }
+ }
+
+ object anonTriple{
+ val up = T{ test() }
+ val down = T{ test(test(up)) }
+ }
+ object diamond{
+ val up = T{ test() }
+ val left = T{ test(up) }
+ val right = T{ test(up) }
+ val down = T{ test(left, right) }
+ }
+ object anonDiamond{
+ val up = T{ test() }
+ val down = T{ test(test(up), test(up)) }
+ }
+
+ // x g-----o
+ // \ \ \
+ // x o h-----I---o
+ // \ / \ / \ / \ \
+ // A---c--o E o-o \ \
+ // / \ / \ / \ o---J
+ // x d o--o o / /
+ // \ / \ / /
+ // o o---F---o
+ // / /
+ // x--B x
+ object bigSingleTerminal{
+ val a = T{ test(test(), test()) }
+ val b = T{ test(test()) }
+ val e = T{
+ val c = test(a)
+ val d = test(a)
+ test(test(test(), test(c)), test(test(c, test(d, b))))
+ }
+ val f = T{
+ test(test(test(), test(e)))
+ }
+ val i = T{
+ val g = test()
+ val h = test(g, e)
+ test(test(g), test(test(h)))
+ }
+ val j = T{
+ test(test(i), test(i, f), test(f))
+ }
+ }
+
+ (singleton, pair, anonTriple, diamond, anonDiamond, bigSingleTerminal)
+ }
+}