Skip to content

Instantly share code, notes, and snippets.

@tomasherman
Created February 3, 2012 15:39
Show Gist options
  • Save tomasherman/1730782 to your computer and use it in GitHub Desktop.
Save tomasherman/1730782 to your computer and use it in GitHub Desktop.
Got 99 problems, but unit testing ain't one of them!
package net.tomasherman.replayvault.server.util
import org.scalacheck._
import Gen._
import Prop._
import cc.spray.json._
import com.mongodb.casbah.Imports._
import mongo._
trait JsonGen extends DefaultJsonProtocol{
implicit def jsobjectGen = Arbitrary { sized(depth => jsonType(4)) }
def jsonType(depth: Int):Gen[JsValue] = oneOf(jsonObject(depth),jsonArray(5,depth))
def jsonObject(depth: Int) = {
for { n <- choose(1,5)
k <- keys(n)
v <- values(k.length,depth)
} yield {
JsObject((k zip v) map (v => JsField(v._1,v._2)))
}
}
def jsonArray(n: Int,depth: Int):Gen[JsArray] = values(n,depth).map(JsArray(_))
def keys(n: Int) = listOfN(n,alphaStr).map(_.distinct)
def values(n: Int, depth: Int): Gen[List[JsValue]] = listOfN(n,value(depth))
def value(depth: Int) = {
if(depth == 0) {
literal
} else {
oneOf(literal,jsonType(depth - 1))
}
}
def literal = oneOf(chooseNum(-100000,100000).map(_.toJson),alphaStr.map(_.toJson),JsTrue,JsFalse)
}
object Json2MongoSpec extends Properties("Implicit json to mongodb conversion") with JsonGen {
property("convert stuff properly") = forAll{ p: JsValue =>
p match {
case pp: JsObject => cmpTwo(pp,pp.toMongo.asInstanceOf[BasicDBObject])
case pp: JsArray => cmpTwo(pp,pp.toMongo.asInstanceOf[List[Any]])
}
}
def cmpObj(o: JsObject, m: BasicDBObject): Boolean = {
(o.fields.length == m.keySet.size) && (true /: o.fields)({ (res,fld) =>
res && cmpTwo(fld.value,m(fld.name))
})
}
def cmpArray(f: JsArray,m: List[Any]) = (true /: (f.elements zip m))((res,el) => res && cmpTwo(el._1,el._2))
def cmpTwo(f: JsValue,m: Any): Boolean = {
(f,m) match {
case (f: JsObject, m: BasicDBObject) => cmpObj(f,m)
case (f: JsArray , m: List[Any]) => cmpArray(f,m)
case (f,m) => cmpLiteral(f,m)
}
}
def cmpLiteral(f: JsValue,m: Any) = realValue(f) == m
def realValue(f: JsValue) = {
f match {
case JsTrue => true
case JsFalse => false
case JsNull => null
case f: JsString => f.value
case f: JsNumber => f.value
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment