summaryrefslogtreecommitdiff
path: root/core/src/test
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2017-11-05 08:18:46 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2017-11-05 08:18:46 -0800
commit8a873f3336400035a9fae5ed64a57b022d9b48da (patch)
treefc6b9a982b5a3573bd3b3eb694c11619bcdb4289 /core/src/test
parent3ebb8788b8fb3d09dedb7ac11956d780dfadb34b (diff)
downloadmill-8a873f3336400035a9fae5ed64a57b022d9b48da.tar.gz
mill-8a873f3336400035a9fae5ed64a57b022d9b48da.tar.bz2
mill-8a873f3336400035a9fae5ed64a57b022d9b48da.zip
First set of standalone tests for the gnarly `Applicative` logic
Diffstat (limited to 'core/src/test')
-rw-r--r--core/src/test/scala/forge/ApplicativeMacrosTests.scala41
-rw-r--r--core/src/test/scala/forge/ApplicativeTests.scala88
2 files changed, 88 insertions, 41 deletions
diff --git a/core/src/test/scala/forge/ApplicativeMacrosTests.scala b/core/src/test/scala/forge/ApplicativeMacrosTests.scala
deleted file mode 100644
index daeaa9b4..00000000
--- a/core/src/test/scala/forge/ApplicativeMacrosTests.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package forge
-import forge.define.{Applicative, Target}
-import utest._
-import language.experimental.macros
-
-object ApplicativeMacrosTests extends TestSuite /*with define.Applicative.Applyer[Option]*/ {
-
-// def apply[T](t: Option[T]): Option[T] = macro Applicative.impl0[Option, T]
-// def apply[T](t: T): Option[T] = macro Applicative.impl[Option, T]
-//
-// type O[+T] = Option[T]
-// def map[A, B](a: O[A], f: A => B) = a.map(f)
-// def zip() = Some(())
-// def zip[A](a: O[A]) = a.map(Tuple1(_))
-// def zip[A, B](a: O[A], b: O[B]) = {
-// for(a <- a; b <- b) yield (a, b)
-// }
-// def zip[A, B, C](a: O[A], b: O[B], c: O[C]) = {
-// for(a <- a; b <- b; c <- c) yield (a, b, c)
-// }
-// def zip[A, B, C, D](a: O[A], b: O[B], c: O[C], d: O[D]) = {
-// for(a <- a; b <- b; c <- c; d <- d) yield (a, b, c, d)
-// }
-// def zip[A, B, C, D, E](a: O[A], b: O[B], c: O[C], d: O[D], e: O[E]) = {
-// for(a <- a; b <- b; c <- c; d <- d; e <- e) yield (a, b, c, d, e)
-// }
-// def zip[A, B, C, D, E, F](a: O[A], b: O[B], c: O[C], d: O[D], e: O[E], f: O[F]) ={
-// for(a <- a; b <- b; c <- c; d <- d; e <- e; f <- f) yield (a, b, c, d, e, f)
-// }
-// def zip[A, B, C, D, E, F, G](a: O[A], b: O[B], c: O[C], d: O[D], e: O[E], f: O[F], g: O[G]) = {
-// for(a <- a; b <- b; c <- c; d <- d; e <- e; f <- f; g <- g) yield (a, b, c, d, e, f, g)
-// }
- val tests = Tests{
- 'hello - {
-// assert(
-// apply("lol " + 1) == Some("lol 1"),
-// apply("lol " + None()) == None
-// )
- }
- }
-}
diff --git a/core/src/test/scala/forge/ApplicativeTests.scala b/core/src/test/scala/forge/ApplicativeTests.scala
new file mode 100644
index 00000000..462cb180
--- /dev/null
+++ b/core/src/test/scala/forge/ApplicativeTests.scala
@@ -0,0 +1,88 @@
+package forge
+import forge.define.Applicative
+import utest._
+import language.experimental.macros
+
+
+object ApplicativeTests extends TestSuite {
+ implicit def optionToOpt[T](o: Option[T]): Opt[T] = new Opt(o)
+ class Opt[T](val o: Option[T]) extends Applicative.Applyable[T]
+ object Opt extends define.Applicative.Applyer[Opt, Option]{
+
+ def underlying[A](v: Opt[A]) = v.o
+ def apply[T](t: Option[T]): Option[T] = macro Applicative.impl0[Option, T]
+ def apply[T](t: T): Option[T] = macro Applicative.impl[Option, T]
+
+ type O[+T] = Option[T]
+ def map[A, B](a: O[A], f: A => B) = a.map(f)
+ def zip() = Some(())
+ def zip[A](a: O[A]) = a.map(Tuple1(_))
+ def zip[A, B](a: O[A], b: O[B]) = {
+ for(a <- a; b <- b) yield (a, b)
+ }
+ def zip[A, B, C](a: O[A], b: O[B], c: O[C]) = {
+ for(a <- a; b <- b; c <- c) yield (a, b, c)
+ }
+ def zip[A, B, C, D](a: O[A], b: O[B], c: O[C], d: O[D]) = {
+ for(a <- a; b <- b; c <- c; d <- d) yield (a, b, c, d)
+ }
+ def zip[A, B, C, D, E](a: O[A], b: O[B], c: O[C], d: O[D], e: O[E]) = {
+ for(a <- a; b <- b; c <- c; d <- d; e <- e) yield (a, b, c, d, e)
+ }
+ def zip[A, B, C, D, E, F](a: O[A], b: O[B], c: O[C], d: O[D], e: O[E], f: O[F]) ={
+ for(a <- a; b <- b; c <- c; d <- d; e <- e; f <- f) yield (a, b, c, d, e, f)
+ }
+ def zip[A, B, C, D, E, F, G](a: O[A], b: O[B], c: O[C], d: O[D], e: O[E], f: O[F], g: O[G]) = {
+ for(a <- a; b <- b; c <- c; d <- d; e <- e; f <- f; g <- g) yield (a, b, c, d, e, f, g)
+ }
+ }
+ class Counter{
+ var value = 0
+ def apply() = {
+ value += 1
+ value
+ }
+ }
+
+ val tests = Tests{
+
+ 'selfContained - {
+
+ 'simple - assert(Opt("lol " + 1) == Some("lol 1"))
+ 'singleSome - assert(Opt("lol " + Some("hello")()) == Some("lol hello"))
+ 'twoSomes - assert(Opt(Some("lol ")() + Some("hello")()) == Some("lol hello"))
+ 'singleNone - assert(Opt("lol " + None()) == None)
+ 'twoNones - assert(Opt("lol " + None() + None()) == None)
+ }
+ 'capturing - {
+ val lol = "lol "
+ def hell(o: String) = "hell" + o
+ 'simple - assert(Opt(lol + 1) == Some("lol 1"))
+ 'singleSome - assert(Opt(lol + Some(hell("o"))()) == Some("lol hello"))
+ 'twoSomes - assert(Opt(Some(lol)() + Some(hell("o"))()) == Some("lol hello"))
+ 'singleNone - assert(Opt(lol + None()) == None)
+ 'twoNones - assert(Opt(lol + None() + None()) == None)
+ }
+ 'allowedLocalDef - {
+ // Although x is defined inside the Opt{...} block, it is also defined
+ // within the LHS of the Applyable#apply call, so it is safe to life it
+ // out into the `zipMap` arguments list.
+ val res = Opt{ "lol " + Some("hello").flatMap(x => Some(x)).apply() }
+ assert(res == Some("lol hello"))
+ }
+ 'upstreamAlwaysEvaluated - {
+ // Validate the assumption that whether or not control-flow reaches the
+ // Applyable#apply call inside an Opt{...} block, we always evaluate the
+ // LHS of the Applyable#apply because it gets lifted out of any control
+ // flow statements
+ val counter = new Counter()
+ def up = Opt{ "lol " + counter() }
+ val down = Opt{ if ("lol".length > 10) up() else "fail" }
+ assert(
+ down == Some("fail"),
+ counter.value == 1
+ )
+ }
+ }
+}
+