blob: 190b4ce5cdd65d209de273ff8ccbb39ff0db26bc [file] [log] [blame]
package io.prediction.commons.settings
import io.prediction.commons.Spec
import org.specs2._
import org.specs2.specification.Step
import com.mongodb.casbah.Imports._
import com.github.nscala_time.time.Imports._
class OfflineEvalsSpec extends Specification {
def is = s2"""
PredictionIO OfflineEvals Specification
OfflineEvals can be implemented by:
- MongoOfflineEvals ${mongoOfflineEvals}
"""
def mongoOfflineEvals = s2"""
MongoOfflineEvals should
- behave like any OfflineEvals implementation ${offlineEvalsTest(newMongoOfflineEvals)}
- (database cleanup) ${Step(Spec.mongoClient(mongoDbName).dropDatabase())}
"""
def offlineEvalsTest(offlineEvals: OfflineEvals) = s2"""
create an OfflineEval ${insert(offlineEvals)}
get two OfflineEvals by Engineid ${getByEngineid(offlineEvals)}
get two OfflineEvals by Tuneid ${getByTuneid(offlineEvals)}
get by id and engineid ${getByIdAndEngineid(offlineEvals)}
update an OfflineEval ${update(offlineEvals)}
delete an OfflineEval ${delete(offlineEvals)}
backup and restore OfflineEvals ${backuprestore(offlineEvals)}
"""
val mongoDbName = "predictionio_mongoofflineevals_test"
def newMongoOfflineEvals = new mongodb.MongoOfflineEvals(Spec.mongoClient(mongoDbName))
/**
* insert and get by id
*/
def insert(offlineEvals: OfflineEvals) = {
val eval1 = OfflineEval(
id = -1,
engineid = 4,
name = "offline-eval-insert1",
tuneid = None,
createtime = Some(DateTime.now),
starttime = Some(DateTime.now),
endtime = None
)
val insertid = offlineEvals.insert(eval1)
offlineEvals.get(insertid) must beSome(eval1.copy(id = insertid))
}
/**
* insert a few and get by engineid
*/
def getByEngineid(offlineEvals: OfflineEvals) = {
val eval1 = OfflineEval(
id = -1,
engineid = 11,
name = "offline-eval-getByEngineid1",
tuneid = Some(3),
createtime = None,
starttime = None,
endtime = None
)
val eval2 = OfflineEval(
id = -1,
engineid = 11,
name = "offline-eval-getByEngineid2",
tuneid = None,
createtime = Some(DateTime.now.hour(1).minute(12).second(34)),
starttime = Some(DateTime.now.hour(2).minute(45).second(10)),
endtime = Some(DateTime.now.hour(4).minute(56).second(35))
)
val id1 = offlineEvals.insert(eval1)
val id2 = offlineEvals.insert(eval2)
val it = offlineEvals.getByEngineid(11)
val it1 = it.next()
val it2 = it.next()
val left = it.hasNext // make sure it has 2 only
it1 must be equalTo (eval1.copy(id = id1)) and
(it2 must be equalTo (eval2.copy(id = id2))) and
(left must be_==(false))
}
/**
* insert a few and get by offline tune id
*/
def getByTuneid(offlineEvals: OfflineEvals) = {
val eval1 = OfflineEval(
id = -1,
engineid = 12,
name = "offline-eval-getByEngineid1",
tuneid = Some(31),
createtime = None,
starttime = None,
endtime = None
)
val eval2 = OfflineEval(
id = -1,
engineid = 12,
name = "offline-eval-getByEngineid2",
tuneid = Some(31),
createtime = Some(DateTime.now.hour(1).minute(12).second(34)),
starttime = Some(DateTime.now.hour(2).minute(45).second(10)),
endtime = Some(DateTime.now.hour(4).minute(56).second(35))
)
val eval3 = OfflineEval(
id = -1,
engineid = 12,
name = "offline-eval-getByEngineid2",
tuneid = Some(32), // note: this one has different tuneid
createtime = Some(DateTime.now.hour(1).minute(12).second(34)),
starttime = Some(DateTime.now.hour(2).minute(45).second(10)),
endtime = Some(DateTime.now.hour(4).minute(56).second(35))
)
val id1 = offlineEvals.insert(eval1)
val id2 = offlineEvals.insert(eval2)
val id3 = offlineEvals.insert(eval3)
val it = offlineEvals.getByTuneid(31)
val it1 = it.next()
val it2 = it.next()
val left = it.hasNext // make sure it has 2 only
it1 must be equalTo (eval1.copy(id = id1)) and
(it2 must be equalTo (eval2.copy(id = id2))) and
(left must be_==(false))
}
def getByIdAndEngineid(offlineEvals: OfflineEvals) = {
val obj1 = OfflineEval(
id = -1,
engineid = 2345,
name = "getByIdAndEngineid",
tuneid = Some(3),
createtime = None,
starttime = None,
endtime = None
)
val obj2 = obj1.copy()
val obj3 = obj1.copy(engineid = 2346, name = "getByIdAndEngineid3")
val id1 = offlineEvals.insert(obj1)
val id2 = offlineEvals.insert(obj2)
val id3 = offlineEvals.insert(obj3)
val eval1 = offlineEvals.getByIdAndEngineid(id1, 2345)
val eval1b = offlineEvals.getByIdAndEngineid(id1, 2346)
val eval2 = offlineEvals.getByIdAndEngineid(id2, 2345)
val eval2b = offlineEvals.getByIdAndEngineid(id2, 2346)
val eval3b = offlineEvals.getByIdAndEngineid(id3, 2345)
val eval3 = offlineEvals.getByIdAndEngineid(id3, 2346)
eval1 must beSome(obj1.copy(id = id1)) and
(eval1b must beNone) and
(eval2 must beSome(obj2.copy(id = id2))) and
(eval2b must beNone) and
(eval3 must beSome(obj3.copy(id = id3))) and
(eval3b must beNone)
}
/**
* insert one and then update with new data and get back
*/
def update(offlineEvals: OfflineEvals) = {
val eval1 = OfflineEval(
id = -1,
engineid = 9,
name = "offline-eval-update1",
tuneid = None,
createtime = None,
starttime = Some(DateTime.now.hour(3).minute(15).second(8)),
endtime = None
)
val updateid = offlineEvals.insert(eval1)
val data1 = offlineEvals.get(updateid)
val eval2 = eval1.copy(
id = updateid,
engineid = 10,
name = "new-offline-eval-update1",
tuneid = Some(44),
createtime = Some(DateTime.now.hour(1).minute(2).second(3)),
starttime = None,
endtime = Some(DateTime.now)
)
offlineEvals.update(eval2)
val data2 = offlineEvals.get(updateid)
data1 must beSome(eval1.copy(id = updateid)) and
(data2 must beSome(eval2))
}
/**
* insert one and delete and get back
*/
def delete(offlineEvals: OfflineEvals) = {
val eval1 = OfflineEval(
id = -1,
engineid = 18,
name = "offline-eval-delete",
tuneid = None,
createtime = Some(DateTime.now),
starttime = Some(DateTime.now),
endtime = None
)
val id1 = offlineEvals.insert(eval1)
val data1 = offlineEvals.get(id1)
offlineEvals.delete(id1)
val data2 = offlineEvals.get(id1)
data1 must beSome(eval1.copy(id = id1)) and
(data2 must beNone)
}
def backuprestore(offlineEvals: OfflineEvals) = {
val eval1 = OfflineEval(
id = -1,
engineid = 20,
name = "backuprestore",
tuneid = None,
createtime = Some(DateTime.now),
starttime = Some(DateTime.now),
endtime = None
)
val id1 = offlineEvals.insert(eval1)
val fn = "evals.json"
val fos = new java.io.FileOutputStream(fn)
try {
fos.write(offlineEvals.backup())
} finally {
fos.close()
}
offlineEvals.restore(scala.io.Source.fromFile(fn)(scala.io.Codec.UTF8).mkString.getBytes("UTF-8")) map { data =>
// For some reason inserting Joda DateTime to DB and getting them back will make test pass
val feval1 = data.find(_.id == id1).get
offlineEvals.update(feval1)
offlineEvals.get(id1) must beSome(eval1.copy(id = id1))
} getOrElse 1 === 2
}
}