blob: 7527b2c7f9bbb7071bd75d785306ee935cd66d2f [file] [log] [blame]
/*
* Copyright 2015-2016 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package whisk.core.entity.test
import java.time.Instant
import scala.Vector
import scala.concurrent.Await
import org.junit.runner.RunWith
import org.scalatest.BeforeAndAfter
import org.scalatest.BeforeAndAfterAll
import org.scalatest.FlatSpec
import org.scalatest.junit.JUnitRunner
import akka.event.Logging.InfoLevel
import whisk.core.WhiskConfig
import whisk.core.database.DocumentConflictException
import whisk.core.database.NoDocumentException
import whisk.core.database.test.DbUtils
import whisk.core.entity._
import common.WskActorSystem
@RunWith(classOf[JUnitRunner])
class DatastoreTests extends FlatSpec
with BeforeAndAfter
with BeforeAndAfterAll
with WskActorSystem
with DbUtils {
val namespace = EntityPath("test namespace")
val config = new WhiskConfig(WhiskAuthStore.requiredProperties ++ WhiskEntityStore.requiredProperties)
val datastore = WhiskEntityStore.datastore(config)
val authstore = WhiskAuthStore.datastore(config)
datastore.setVerbosity(InfoLevel)
authstore.setVerbosity(InfoLevel)
override def afterAll() {
println("Shutting down store connections")
datastore.shutdown()
authstore.shutdown()
super.afterAll()
}
@volatile var counter = 0
def aname(implicit n: EntityName) = {
counter = counter + 1
EntityName(s"$n$counter")
}
after {
cleanup()
}
behavior of "Datastore"
it should "CRD auth" in {
implicit val tid = transid()
val auth = WhiskAuth(Subject(), AuthKey())
putGetCheck(authstore, auth, WhiskAuth)
}
it should "lookup key by uuid" in {
implicit val tid = transid()
val auth = WhiskAuth(Subject(), AuthKey())
put(authstore, auth)
val confirm = waitOnView(authstore, auth.uuid, 1)
val result = retry(() => WhiskAuth.get(authstore, auth.uuid), dbOpTimeout).get
assert(result != null)
assert(result == auth)
}
it should "CRD action blackbox" in {
implicit val tid = transid()
implicit val basename = EntityName("create action blackbox")
val exec = Exec.bb("image")
val actions = Seq(
WhiskAction(namespace, aname, exec),
WhiskAction(namespace, aname, exec, Parameters("x", "y")),
WhiskAction(namespace, aname, exec, Parameters("x", "y")),
WhiskAction(namespace, aname, exec, Parameters("x", "y") ++ Parameters("x", "y")),
WhiskAction(namespace, aname, exec, Parameters("x", "y") ++ Parameters("y", "x")))
val docs = actions.map { entity =>
putGetCheck(datastore, entity, WhiskAction)
}
}
it should "CRD action js" in {
implicit val tid = transid()
implicit val basename = EntityName("create action js")
val exec = Exec.js("code")
val actions = Seq(
WhiskAction(namespace, aname, exec, Parameters()),
WhiskAction(namespace, aname, exec, Parameters("x", "y")),
WhiskAction(namespace, aname, exec, Parameters("x", "y")),
WhiskAction(namespace, aname, exec, Parameters("x", "y") ++ Parameters("x", "y")),
WhiskAction(namespace, aname, exec, Parameters("x", "y") ++ Parameters("y", "x")))
val docs = actions.map { entity =>
putGetCheck(datastore, entity, WhiskAction)
}
}
it should "CRD trigger" in {
implicit val tid = transid()
implicit val basename = EntityName("create trigger")
val triggers = Seq(
WhiskTrigger(namespace, aname),
WhiskTrigger(namespace, aname, Parameters("x", "y")),
WhiskTrigger(namespace, aname, Parameters("x", "y")))
val docs = triggers.map { entity =>
putGetCheck(datastore, entity, WhiskTrigger)
}
}
it should "CRD rule" in {
implicit val tid = transid()
implicit val basename = EntityName("create rule")
val rules = Seq(
WhiskRule(namespace, aname, EntityName("a trigger"), EntityName("an action")),
WhiskRule(namespace, aname, EntityName("a trigger"), EntityName("an action")))
val docs = rules.map { entity =>
putGetCheck(datastore, entity, WhiskRule)
}
}
it should "CRD activation" in {
implicit val tid = transid()
implicit val basename = EntityName("create action blackbox")
val activations = Seq(
WhiskActivation(namespace, aname, Subject(), ActivationId(), start = Instant.now, end = Instant.now),
WhiskActivation(namespace, aname, Subject(), ActivationId(), start = Instant.now, end = Instant.now))
val docs = activations.map { entity =>
putGetCheck(datastore, entity, WhiskActivation)
}
}
ignore should "CRD activation with utf8 characters" in {
implicit val tid = transid()
implicit val basename = EntityName("create action blackbox")
val activations = Seq(
WhiskActivation(namespace, aname, Subject(), ActivationId(), start = Instant.now, end = Instant.now, logs = ActivationLogs(Vector("Prote\u00EDna"))))
val docs = activations.map { entity =>
putGetCheck(datastore, entity, WhiskActivation)
}
}
it should "reject action with null arguments" in {
val name = EntityName("bad action")
intercept[IllegalArgumentException] {
WhiskAction(namespace, name, Exec.bb("i"), Parameters(), null)
}
}
it should "reject trigger with null arguments" in {
val name = EntityName("bad trigger")
intercept[IllegalArgumentException] {
WhiskTrigger(namespace, name, Parameters(), null)
}
}
it should "reject rule with null arguments" in {
val name = EntityName("bad rule")
intercept[IllegalArgumentException] {
WhiskRule(namespace, name, EntityName(null), EntityName(null))
}
intercept[IllegalArgumentException] {
WhiskRule(namespace, name, EntityName(""), EntityName(null))
}
intercept[IllegalArgumentException] {
WhiskRule(namespace, name, EntityName(" "), EntityName(null))
}
}
it should "update auth with a revision" in {
implicit val tid = transid()
val auth = WhiskAuth(Subject(), AuthKey())
val docinfo = putGetCheck(authstore, auth, WhiskAuth, false)._2.docinfo
val revAuth = auth.revoke.revision[WhiskAuth](docinfo.rev)
putGetCheck(authstore, revAuth, WhiskAuth)
}
it should "update action with a revision" in {
implicit val tid = transid()
implicit val basename = EntityName("update action")
val exec = Exec.js("update")
val action = WhiskAction(namespace, aname, exec, Parameters(), ActionLimits())
val docinfo = putGetCheck(datastore, action, WhiskAction, false)._2.docinfo
val revAction = WhiskAction(namespace, action.name, exec, Parameters(), ActionLimits()).revision[WhiskAction](docinfo.rev)
putGetCheck(datastore, revAction, WhiskAction)
}
it should "update trigger with a revision" in {
implicit val tid = transid()
implicit val basename = EntityName("update trigger")
val trigger = WhiskTrigger(namespace, aname)
val docinfo = putGetCheck(datastore, trigger, WhiskTrigger, false)._2.docinfo
val revTrigger = WhiskTrigger(namespace, trigger.name).revision[WhiskTrigger](docinfo.rev)
putGetCheck(datastore, revTrigger, WhiskTrigger)
}
it should "update rule with a revision" in {
implicit val tid = transid()
implicit val basename = EntityName("update rule")
val rule = WhiskRule(namespace, aname, EntityName("a trigger"), EntityName("an action"))
val docinfo = putGetCheck(datastore, rule, WhiskRule, false)._2.docinfo
val revRule = WhiskRule(namespace, rule.name, rule.trigger, rule.action).revision[WhiskRule](docinfo.rev)
putGetCheck(datastore, revRule, WhiskRule)
}
it should "update activation with a revision" in {
implicit val tid = transid()
implicit val basename = EntityName("update activation")
val activation = WhiskActivation(namespace, aname, Subject(), ActivationId(), start = Instant.now, end = Instant.now)
val docinfo = putGetCheck(datastore, activation, WhiskActivation, false)._2.docinfo
val revActivation = WhiskActivation(namespace, aname, activation.subject, activation.activationId, start = Instant.now, end = Instant.now).revision[WhiskActivation](docinfo.rev)
putGetCheck(datastore, revActivation, WhiskActivation)
}
it should "fail with document conflict when trying to write the same auth twice without a revision" in {
implicit val tid = transid()
val auth = WhiskAuth(Subject(), AuthKey())
putGetCheck(authstore, auth, WhiskAuth)
intercept[DocumentConflictException] {
putGetCheck(authstore, auth, WhiskAuth)
}
}
it should "fail with document conflict when trying to write the same action twice without a revision" in {
implicit val tid = transid()
implicit val basename = EntityName("create action twice")
val exec = Exec.js("twice")
val action = WhiskAction(namespace, aname, exec)
putGetCheck(datastore, action, WhiskAction)
intercept[DocumentConflictException] {
putGetCheck(datastore, action, WhiskAction)
}
}
it should "fail with document conflict when trying to write the same trigger twice without a revision" in {
implicit val tid = transid()
implicit val basename = EntityName("create trigger twice")
val trigger = WhiskTrigger(namespace, aname, Parameters("x", "y"))
putGetCheck(datastore, trigger, WhiskTrigger)
intercept[DocumentConflictException] {
putGetCheck(datastore, trigger, WhiskTrigger)
}
}
it should "fail with document conflict when trying to write the same rule twice without a revision" in {
implicit val tid = transid()
implicit val basename = EntityName("create rule twice")
val rule = WhiskRule(namespace, aname, EntityName("a trigger"), EntityName("an action"))
putGetCheck(datastore, rule, WhiskRule)
intercept[DocumentConflictException] {
putGetCheck(datastore, rule, WhiskRule)
}
}
it should "fail with document conflict when trying to write the same activation twice without a revision" in {
implicit val tid = transid()
implicit val basename = EntityName("create activation twice")
val activation = WhiskActivation(namespace, aname, Subject(), ActivationId(), start = Instant.now, end = Instant.now)
putGetCheck(datastore, activation, WhiskActivation)
intercept[DocumentConflictException] {
putGetCheck(datastore, activation, WhiskActivation)
}
}
it should "fail with document does not exist when trying to delete the same auth twice" in {
implicit val tid = transid()
val auth = WhiskAuth(Subject(), AuthKey())
val doc = putGetCheck(authstore, auth, WhiskAuth, false)._1
assert(Await.result(WhiskAuth.del(authstore, doc), dbOpTimeout))
intercept[NoDocumentException] {
assert(Await.result(WhiskAuth.del(authstore, doc), dbOpTimeout))
assert(false)
}
}
it should "fail with document does not exist when trying to delete the same action twice" in {
implicit val tid = transid()
implicit val basename = EntityName("delete action twice")
val exec = Exec.js("twice")
val action = WhiskAction(namespace, aname, exec)
val doc = putGetCheck(datastore, action, WhiskAction, false)._1
assert(Await.result(WhiskAction.del(datastore, doc), dbOpTimeout))
intercept[NoDocumentException] {
Await.result(WhiskAction.del(datastore, doc), dbOpTimeout)
assert(false)
}
}
it should "fail with document does not exist when trying to delete the same trigger twice" in {
implicit val tid = transid()
implicit val basename = EntityName("delete trigger twice")
val trigger = WhiskTrigger(namespace, aname, Parameters("x", "y"))
val doc = putGetCheck(datastore, trigger, WhiskTrigger, false)._1
assert(Await.result(WhiskTrigger.del(datastore, doc), dbOpTimeout))
intercept[NoDocumentException] {
Await.result(WhiskTrigger.del(datastore, doc), dbOpTimeout)
assert(false)
}
}
it should "fail with document does not exist when trying to delete the same rule twice" in {
implicit val tid = transid()
implicit val basename = EntityName("delete rule twice")
val rule = WhiskRule(namespace, aname, EntityName("a trigger"), EntityName("an action"))
val doc = putGetCheck(datastore, rule, WhiskRule, false)._1
assert(Await.result(WhiskRule.del(datastore, doc), dbOpTimeout))
intercept[NoDocumentException] {
Await.result(WhiskRule.del(datastore, doc), dbOpTimeout)
assert(false)
}
}
it should "fail with document does not exist when trying to delete the same activation twice" in {
implicit val tid = transid()
implicit val basename = EntityName("delete activation twice")
val activation = WhiskActivation(namespace, aname, Subject(), ActivationId(), start = Instant.now, end = Instant.now)
val doc = putGetCheck(datastore, activation, WhiskActivation, false)._1
assert(Await.result(WhiskActivation.del(datastore, doc), dbOpTimeout))
intercept[NoDocumentException] {
Await.result(WhiskActivation.del(datastore, doc), dbOpTimeout)
assert(false)
}
}
it should "fail to CRD with undefined argument" in {
implicit val tid = transid()
intercept[IllegalArgumentException] {
Await.result(WhiskAction.del(null, null), dbOpTimeout)
assert(false)
}
intercept[IllegalArgumentException] {
Await.result(WhiskAction.put(null, null), dbOpTimeout)
assert(false)
}
}
}