2017-04-17 09:20:41 +02:00
|
|
|
package sbt.util
|
2016-06-27 15:27:42 +02:00
|
|
|
|
|
|
|
|
import sbt.io.IO
|
|
|
|
|
import sbt.io.syntax._
|
|
|
|
|
|
|
|
|
|
import CacheImplicits._
|
|
|
|
|
|
|
|
|
|
import sjsonnew.{ Builder, deserializationError, IsoString, JsonFormat, Unbuilder }
|
2016-08-21 19:56:31 +02:00
|
|
|
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter, Parser }
|
2016-06-27 15:27:42 +02:00
|
|
|
|
2017-07-14 21:56:06 +02:00
|
|
|
import sjsonnew.shaded.scalajson.ast.unsafe.JValue
|
2018-02-23 19:16:30 +01:00
|
|
|
import org.scalatest.FlatSpec
|
2016-06-27 15:27:42 +02:00
|
|
|
|
2018-02-23 19:16:30 +01:00
|
|
|
class SingletonCacheSpec extends FlatSpec {
|
2016-06-27 15:27:42 +02:00
|
|
|
|
|
|
|
|
case class ComplexType(val x: Int, y: String, z: List[Int])
|
|
|
|
|
object ComplexType {
|
|
|
|
|
implicit val format: JsonFormat[ComplexType] =
|
|
|
|
|
new JsonFormat[ComplexType] {
|
|
|
|
|
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): ComplexType = {
|
|
|
|
|
jsOpt match {
|
|
|
|
|
case Some(js) =>
|
|
|
|
|
unbuilder.beginObject(js)
|
|
|
|
|
val x = unbuilder.readField[Int]("x")
|
|
|
|
|
val y = unbuilder.readField[String]("y")
|
|
|
|
|
val z = unbuilder.readField[List[Int]]("z")
|
|
|
|
|
unbuilder.endObject()
|
|
|
|
|
ComplexType(x, y, z)
|
|
|
|
|
|
|
|
|
|
case None =>
|
|
|
|
|
deserializationError("Exception JObject but found None")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def write[J](obj: ComplexType, builder: Builder[J]): Unit = {
|
|
|
|
|
builder.beginObject()
|
|
|
|
|
builder.addField("x", obj.x)
|
|
|
|
|
builder.addField("y", obj.y)
|
|
|
|
|
builder.addField("z", obj.z)
|
|
|
|
|
builder.endObject()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 12:24:29 +02:00
|
|
|
implicit val isoString: IsoString[JValue] =
|
|
|
|
|
IsoString.iso(CompactPrinter.apply, Parser.parseUnsafe)
|
2016-06-27 15:27:42 +02:00
|
|
|
|
|
|
|
|
"A singleton cache" should "throw an exception if read without being written previously" in {
|
|
|
|
|
testCache[Int] {
|
|
|
|
|
case (cache, store) =>
|
|
|
|
|
intercept[Exception] {
|
|
|
|
|
cache.read(store)
|
|
|
|
|
}
|
|
|
|
|
()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
it should "write a very simple value" in {
|
|
|
|
|
testCache[Int] {
|
|
|
|
|
case (cache, store) =>
|
|
|
|
|
cache.write(store, 5)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
it should "return the simple value that has been previously written" in {
|
|
|
|
|
testCache[Int] {
|
|
|
|
|
case (cache, store) =>
|
|
|
|
|
val value = 5
|
|
|
|
|
cache.write(store, value)
|
|
|
|
|
val read = cache.read(store)
|
|
|
|
|
|
|
|
|
|
assert(read === value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
it should "write a complex value" in {
|
|
|
|
|
testCache[ComplexType] {
|
|
|
|
|
case (cache, store) =>
|
|
|
|
|
val value = ComplexType(1, "hello, world!", (1 to 10 by 3).toList)
|
|
|
|
|
cache.write(store, value)
|
|
|
|
|
val read = cache.read(store)
|
|
|
|
|
|
|
|
|
|
assert(read === value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 12:24:29 +02:00
|
|
|
private def testCache[T](f: (SingletonCache[T], CacheStore) => Unit)(
|
|
|
|
|
implicit cache: SingletonCache[T]
|
|
|
|
|
): Unit =
|
2016-06-27 15:27:42 +02:00
|
|
|
IO.withTemporaryDirectory { tmp =>
|
|
|
|
|
val store = new FileBasedStore(tmp / "cache-store", Converter)
|
|
|
|
|
f(cache, store)
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 12:24:29 +02:00
|
|
|
}
|