Skip to content
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

Add StreamingT tests and fix some uncovered bugs #656

Merged
merged 3 commits into from
Nov 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions core/src/main/scala/cats/data/StreamingT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ sealed abstract class StreamingT[F[_], A] extends Product with Serializable { lh
* element to be calculated.
*/
def isEmpty(implicit ev: Monad[F]): F[Boolean] =
uncons.map(_.isDefined)
uncons.map(_.isEmpty)

/**
* Return true if the stream is non-empty, false otherwise.
Expand All @@ -116,7 +116,7 @@ sealed abstract class StreamingT[F[_], A] extends Product with Serializable { lh
* element to be calculated.
*/
def nonEmpty(implicit ev: Monad[F]): F[Boolean] =
uncons.map(_.isEmpty)
uncons.map(_.isDefined)

/**
* Prepend an A value to the current stream.
Expand Down Expand Up @@ -205,7 +205,7 @@ sealed abstract class StreamingT[F[_], A] extends Product with Serializable { lh
*/
def drop(n: Int)(implicit ev: Functor[F]): StreamingT[F, A] =
if (n <= 0) this else this match {
case Cons(a, ft) => Wait(ft.map(_.take(n - 1)))
case Cons(a, ft) => Wait(ft.map(_.drop(n - 1)))
case Wait(ft) => Wait(ft.map(_.drop(n)))
case Empty() => Empty()
}
Expand Down Expand Up @@ -249,7 +249,7 @@ sealed abstract class StreamingT[F[_], A] extends Product with Serializable { lh
*/
def dropWhile(f: A => Boolean)(implicit ev: Functor[F]): StreamingT[F, A] =
this match {
case Cons(a, ft) => if (f(a)) Empty() else Cons(a, ft.map(_.takeWhile(f)))
case Cons(a, ft) => if (f(a)) Empty() else Cons(a, ft.map(_.dropWhile(f)))
case Wait(ft) => Wait(ft.map(_.dropWhile(f)))
case Empty() => Empty()
}
Expand Down Expand Up @@ -439,6 +439,9 @@ private[data] sealed trait StreamingTInstances extends StreamingTInstances1 {
fa.filter(f)
def coflatMap[A, B](fa: StreamingT[F, A])(f: StreamingT[F, A] => B): StreamingT[F, B] =
fa.coflatMap(f)

override def map[A, B](fa: StreamingT[F, A])(f: A => B): StreamingT[F, B] =
fa.map(f)
}

implicit def streamingTOrder[F[_], A](implicit ev: Monad[F], eva: Order[F[List[A]]]): Order[StreamingT[F, A]] =
Expand Down
108 changes: 108 additions & 0 deletions tests/src/test/scala/cats/tests/StreamingTTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import algebra.laws.OrderLaws
import cats.data.StreamingT
import cats.laws.discipline.{CoflatMapTests, MonadCombineTests, SerializableTests}
import cats.laws.discipline.arbitrary._
import cats.laws.discipline.eq._

class StreamingTTests extends CatsSuite {

Expand All @@ -23,6 +24,113 @@ class StreamingTTests extends CatsSuite {
checkAll("StreamingT[List, ?]", CoflatMapTests[StreamingT[List, ?]].coflatMap[Int, Int, Int])
checkAll("StreamingT[List, Int]", OrderLaws[StreamingT[List, Int]].order)
checkAll("Monad[StreamingT[List, ?]]", SerializableTests.serializable(Monad[StreamingT[List, ?]]))

test("uncons with Id consistent with List headOption/tail") {
forAll { (s: StreamingT[Id, Int]) =>
val sList = s.toList
s.uncons.map{ case (h, t) =>
(h, t.toList)
} should === (sList.headOption.map{ h =>
(h, sList.tail)
})
}
}

test("map with Id consistent with List.map") {
forAll { (s: StreamingT[Id, Int], f: Int => Long) =>
s.map(f).toList should === (s.toList.map(f))
}
}

test("flatMap with Id consistent with List.flatMap") {
forAll { (s: StreamingT[Id, Int], f: Int => StreamingT[Id, Long]) =>
s.flatMap(f).toList should === (s.toList.flatMap(f(_).toList))
}
}

test("filter with Id consistent with List.filter") {
forAll { (s: StreamingT[Id, Int], f: Int => Boolean) =>
s.filter(f).toList should === (s.toList.filter(f))
}
}

test("foldLeft with Id consistent with List.foldLeft") {
forAll { (s: StreamingT[Id, Int], l: Long, f: (Long, Int) => Long) =>
s.foldLeft(l)(f) should === (s.toList.foldLeft(l)(f))
}
}

test("find with Id consistent with List.find") {
forAll { (s: StreamingT[Id, Int], f: Int => Boolean) =>
s.find(f) should === (s.toList.find(f))
}
}

test("isEmpty with Id consistent with List.isEmpty") {
forAll { (s: StreamingT[Id, Int]) =>
s.isEmpty should === (s.toList.isEmpty)
}
}

test("nonEmpty with Id consistent with List.nonEmpty") {
forAll { (s: StreamingT[Id, Int]) =>
s.nonEmpty should === (s.toList.nonEmpty)
}
}

test("%:: with Id consistent with List.::") {
forAll { (i: Int, s: StreamingT[Id, Int]) =>
(i %:: s).toList should === (i :: s.toList)
}
}

test("%::: with Id consistent with List.:::") {
forAll { (s1: StreamingT[Id, Int], s2: StreamingT[Id, Int]) =>
(s1 %::: s2).toList should === (s1.toList ::: s2.toList)
}
}

test("concat with Id consistent with List.++") {
forAll { (s1: StreamingT[Id, Int], s2: StreamingT[Id, Int]) =>
(s1 concat s2).toList should === (s1.toList ++ s2.toList)
}
}

test("exists with Id consistent with List.exists") {
forAll { (s: StreamingT[Id, Int], f: Int => Boolean) =>
s.exists(f) should === (s.toList.exists(f))
}
}

test("forall with Id consistent with List.forall") {
forAll { (s: StreamingT[Id, Int], f: Int => Boolean) =>
s.forall(f) should === (s.toList.forall(f))
}
}

test("takeWhile with Id consistent with List.takeWhile") {
forAll { (s: StreamingT[Id, Int], f: Int => Boolean) =>
s.takeWhile(f).toList should === (s.toList.takeWhile(f))
}
}

test("dropWhile with Id consistent with List.dropWhile") {
forAll { (s: StreamingT[Id, Int], f: Int => Boolean) =>
s.dropWhile(f).toList should === (s.toList.dropWhile(f))
}
}

test("take with Id consistent with List.take") {
forAll { (s: StreamingT[Id, Int], i: Int) =>
s.take(i).toList should === (s.toList.take(i))
}
}

test("drop with Id consistent with List.drop") {
forAll { (s: StreamingT[Id, Int], i: Int) =>
s.drop(i).toList should === (s.toList.drop(i))
}
}
}

class SpecificStreamingTTests extends CatsSuite {
Expand Down