Skip to content
Permalink
Browse files

Adapted to new package and some tests

  • Loading branch information
raulraja committed Jul 6, 2016
1 parent 300cfdd commit 307849ae05d024b0fb199fbf545cc67e2d529451
@@ -5,7 +5,7 @@ lazy val fetch = (project in file("."))
organization := "org.scala-exercises",
name := "exercises-fetch",
scalaVersion := "2.11.7",
version := "0.1.1",
version := "0.2.1-SNAPSHOT",
resolvers ++= Seq(
Resolver.sonatypeRepo("snapshots"),
Resolver.sonatypeRepo("releases")
@@ -1,2 +1,2 @@
addSbtPlugin("org.scala-exercises" % "sbt-exercise" % "0.1.1", "0.13", "2.10")
addSbtPlugin("org.scala-exercises" % "sbt-exercise" % "0.2.1-SNAPSHOT", "0.13", "2.10")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
@@ -11,6 +11,8 @@ import cats.std.list._
import cats.syntax.cartesian._
import cats.syntax.traverse._

import org.scalaexercises.definitions._

/**
* = Caching =
*
@@ -20,7 +22,7 @@ import cats.syntax.traverse._
*
* @param name caching
*/
object CachingSection extends FlatSpec with Matchers with exercise.Section {
object CachingSection extends FlatSpec with Matchers with Section {

import FetchTutorialHelper._

@@ -9,6 +9,9 @@ import fetch.unsafe.implicits._
import fetch.syntax._
import scala.util.Try


import org.scalaexercises.definitions._

/**
* = cats =
*
@@ -25,7 +28,7 @@ import scala.util.Try
*
* @param name cats
*/
object CatsSection extends FlatSpec with Matchers with exercise.Section {
object CatsSection extends FlatSpec with Matchers with Section {

/**
* = Applicative =
@@ -8,6 +8,8 @@ import cats._
import fetch.syntax._
import scala.util.Try

import org.scalaexercises.definitions._

/**
* = Concurrency monads =
*
@@ -39,7 +41,7 @@ import scala.util.Try
*
* @param name concurrency_monads
*/
object ConcurrencyMonadsSection extends FlatSpec with Matchers with exercise.Section {
object ConcurrencyMonadsSection extends FlatSpec with Matchers with Section {

import FetchTutorialHelper._

@@ -9,6 +9,8 @@ import fetch.unsafe.implicits._
import fetch.syntax._
import scala.util.Try

import org.scalaexercises.definitions._

/**
*
* = Error handling =
@@ -18,7 +20,7 @@ import scala.util.Try
*
* @param name error_handling
*/
object ErrorHandlingSection extends FlatSpec with Matchers with exercise.Section {
object ErrorHandlingSection extends FlatSpec with Matchers with Section {

import FetchTutorialHelper._

@@ -1,10 +1,12 @@
package fetchlib

import org.scalaexercises.definitions._

/** Fetch is a library for making access to data both simple & efficient.
*
* @param name fetch
*/
object FetchLibrary extends exercise.Library {
object FetchLibrary extends Library {
override def owner = "scala-exercises"
override def repository = "exercises-fetch"

@@ -8,14 +8,6 @@ object FetchTutorialHelper {
type UserId = Int
case class User(id: UserId, username: String)

def latency[A](result: A, msg: String) = {
val id = Thread.currentThread.getId
println(s"~~> [$id] $msg")
Thread.sleep(100)
println(s"<~~ [$id] $msg")
result
}

import cats.data.NonEmptyList

val userDatabase: Map[UserId, User] = Map(
@@ -28,12 +20,12 @@ object FetchTutorialHelper {
implicit object UserSource extends DataSource[UserId, User] {
override def fetchOne(id: UserId): Query[Option[User]] = {
Query.sync({
latency(userDatabase.get(id), s"One User $id")
userDatabase.get(id)
})
}
override def fetchMany(ids: NonEmptyList[UserId]): Query[Map[UserId, User]] = {
Query.sync({
latency(userDatabase.filterKeys(ids.unwrap.contains), s"Many Users $ids")
userDatabase.filterKeys(ids.unwrap.contains)
})
}
}
@@ -52,12 +44,12 @@ object FetchTutorialHelper {
implicit object PostSource extends DataSource[PostId, Post] {
override def fetchOne(id: PostId): Query[Option[Post]] = {
Query.sync({
latency(postDatabase.get(id), s"One Post $id")
postDatabase.get(id)
})
}
override def fetchMany(ids: NonEmptyList[PostId]): Query[Map[PostId, Post]] = {
Query.sync({
latency(postDatabase.filterKeys(ids.unwrap.contains), s"Many Posts $ids")
postDatabase.filterKeys(ids.unwrap.contains)
})
}
}
@@ -72,13 +64,13 @@ object FetchTutorialHelper {
override def fetchOne(id: Post): Query[Option[PostTopic]] = {
Query.sync({
val topic = if (id.id % 2 == 0) "monad" else "applicative"
latency(Option(topic), s"One Post Topic $id")
Option(topic)
})
}
override def fetchMany(ids: NonEmptyList[Post]): Query[Map[Post, PostTopic]] = {
Query.sync({
val result = ids.unwrap.map(id => (id, if (id.id % 2 == 0) "monad" else "applicative")).toMap
latency(result, s"Many Post Topics $ids")
result
})
}
}
@@ -97,6 +89,7 @@ object FetchTutorialHelper {
val fetchError: Fetch[User] = (new Exception("Oh noes")).fetch

import cats.syntax.cartesian._
import cats.syntax.traverse._

val postsByAuthor: Fetch[List[Post]] = for {
posts <- List(1, 2).traverse(getPost)
@@ -112,11 +105,11 @@ object FetchTutorialHelper {

val homePage = (postsByAuthor |@| postTopics).tupled

import cats.{Eval, Now, Later, Always}
import monix.eval.Task

import monix.execution.Cancelable
import scala.concurrent.duration._
import fetch.monixTask.implicits._

def queryToTask[A](q: Query[A]): Task[A] = q match {
case Sync(e) => evalToTask(e)
@@ -9,12 +9,14 @@ import fetch.unsafe.implicits._
import fetch.syntax._
import scala.util.Try

import org.scalaexercises.definitions._

/**
* = Syntax =
*
* @param name syntax
*/
object SyntaxSection extends FlatSpec with Matchers with exercise.Section {
object SyntaxSection extends FlatSpec with Matchers with Section {

import FetchTutorialHelper._

@@ -10,6 +10,9 @@ import fetch.syntax._
import cats.std.list._
import cats.syntax.cartesian._
import cats.syntax.traverse._

import org.scalaexercises.definitions._

/**
* = Introduction =
*
@@ -72,17 +75,6 @@ import cats.syntax.traverse._
* case class User(id: UserId, username: String)
* }}}
*
* We'll simulate unpredictable latency with this function.
*
* {{{
* def latency[A](result: A, msg: String) = {
* val id = Thread.currentThread.getId
* println(s"~~> [$id] $msg")
* Thread.sleep(100)
* println(s"<~~ [$id] $msg")
* result
* }
* }}}
*
* And now we're ready to write our user data source; we'll emulate a database with an in-memory map.
*
@@ -102,12 +94,12 @@ import cats.syntax.traverse._
* implicit object UserSource extends DataSource[UserId, User]{
* override def fetchOne(id: UserId): Query[Option[User]] = {
* Query.sync({
* latency(userDatabase.get(id), s"One User $id")
* userDatabase.get(id)
* })
* }
* override def fetchMany(ids: NonEmptyList[UserId]): Query[Map[UserId, User]] = {
* Query.sync({
* latency(userDatabase.filterKeys(ids.unwrap.contains), s"Many Users $ids")
* userDatabase.filterKeys(ids.unwrap.contains)
* })
* }
* }
@@ -122,7 +114,7 @@ import cats.syntax.traverse._
*
* @param name usage
*/
object UsageSection extends FlatSpec with Matchers with exercise.Section {
object UsageSection extends FlatSpec with Matchers with Section {

import FetchTutorialHelper._

@@ -164,7 +156,6 @@ object UsageSection extends FlatSpec with Matchers with exercise.Section {
*/
def creatingAndRunning(res0: User) = {
val fetchUser: Fetch[User] = getUser(1)

fetchUser.runA[Id] should be(res0)
}

@@ -0,0 +1,56 @@
package exercises

import cats.data.Xor

import shapeless._
import shapeless.ops.function._

import org.scalacheck.{ Prop, Arbitrary }
import org.scalacheck.Gen
import Prop.forAll

import org.scalatest.Spec
import org.scalatest.exceptions._
import org.scalatest.prop.Checkers

import org.scalacheck.Shapeless._

object Test {

def testSuccess[F, R, L <: HList](method: F, answer: L)(
implicit
A: Arbitrary[L],
fntop: FnToProduct.Aux[F, L R]
): Prop = {
val rightGen = genRightAnswer(answer)
val rightProp = forAll(rightGen)({ p

val result = Xor.catchOnly[GeneratorDrivenPropertyCheckFailedException]({ fntop(method)(p) })
result match {
case Xor.Left(exc) exc.cause match {
case Some(originalException) throw originalException
case _ false
}
case _ true
}
})

val wrongGen = genWrongAnswer(answer)
val wrongProp = forAll(wrongGen)({ p
Xor.catchNonFatal({ fntop(method)(p) }).isLeft
})

Prop.all(rightProp, wrongProp)
}

def genRightAnswer[L <: HList](answer: L): Gen[L] = {
Gen.const(answer)
}

def genWrongAnswer[L <: HList](l: L)(
implicit
A: Arbitrary[L]
): Gen[L] = {
A.arbitrary.suchThat(_ != l)
}
}
@@ -0,0 +1,33 @@
package exercises

import fetchlib._
import shapeless.HNil

import org.scalatest.Spec
import org.scalatest.prop.Checkers

import org.scalacheck.Shapeless._

class QuickStartSpec extends Spec with Checkers {

import FetchTutorialHelper._
import UsageSection._
import Test._

def `Creating And Running` =
check(testSuccess(creatingAndRunning _, userDatabase(1) :: HNil))

def `Sequencing Strategy` =
check(testSuccess(sequencing _, (userDatabase(1), userDatabase(2)) :: 2 :: HNil))

def `Batching Strategy` =
check(testSuccess(batching _, (userDatabase(1), userDatabase(2)) :: 1 :: HNil))

def `Deduplication Strategy` =
check(testSuccess(deduplication _, (userDatabase(1), userDatabase(1)) :: 1 :: HNil))

def `Caching Strategy` =
check(testSuccess(caching _, (userDatabase(1), userDatabase(1)) :: 1 :: HNil))


}

0 comments on commit 307849a

Please sign in to comment.
You can’t perform that action at this time.