This is an automated email from the ASF dual-hosted git repository.
chetanm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push:
new 6cc6ab4 Add common test codes for ActivationStore (#4031)
6cc6ab4 is described below
commit 6cc6ab4d28fac2afa892f0adb721bc1b228b42a4
Author: jiangpch <[email protected]>
AuthorDate: Fri Feb 15 11:58:29 2019 +0800
Add common test codes for ActivationStore (#4031)
Adds a suite of testcases to validate the implementations of
ActivationStore SPI
---
.../ArtifactActivationStoreBehaviorBase.scala | 33 ++
.../database/ArtifactActivationStoreTests.scala | 57 ++++
.../test/behavior/ActivationStoreBehavior.scala | 23 ++
.../behavior/ActivationStoreBehaviorBase.scala | 106 +++++++
.../behavior/ActivationStoreCRUDBehaviors.scala | 70 ++++
.../behavior/ActivationStoreQueryBehaviors.scala | 353 +++++++++++++++++++++
6 files changed, 642 insertions(+)
diff --git
a/tests/src/test/scala/org/apache/openwhisk/core/database/ArtifactActivationStoreBehaviorBase.scala
b/tests/src/test/scala/org/apache/openwhisk/core/database/ArtifactActivationStoreBehaviorBase.scala
new file mode 100644
index 0000000..070d35e
--- /dev/null
+++
b/tests/src/test/scala/org/apache/openwhisk/core/database/ArtifactActivationStoreBehaviorBase.scala
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.openwhisk.core.database
+
+import akka.stream.ActorMaterializer
+import org.apache.openwhisk.core.controller.test.WhiskAuthHelpers
+import
org.apache.openwhisk.core.database.test.behavior.ActivationStoreBehaviorBase
+import org.scalatest.FlatSpec
+
+trait ArtifactActivationStoreBehaviorBase extends FlatSpec with
ActivationStoreBehaviorBase {
+ override def storeType = "Artifact"
+
+ override val context = UserContext(WhiskAuthHelpers.newIdentity())
+
+ override lazy val activationStore = {
+ ArtifactActivationStoreProvider.instance(actorSystem,
ActorMaterializer.create(actorSystem), logging)
+ }
+}
diff --git
a/tests/src/test/scala/org/apache/openwhisk/core/database/ArtifactActivationStoreTests.scala
b/tests/src/test/scala/org/apache/openwhisk/core/database/ArtifactActivationStoreTests.scala
new file mode 100644
index 0000000..86cb5ad
--- /dev/null
+++
b/tests/src/test/scala/org/apache/openwhisk/core/database/ArtifactActivationStoreTests.scala
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.openwhisk.core.database
+
+import java.time.Instant
+
+import org.apache.openwhisk.common.TransactionId
+import org.apache.openwhisk.core.database.test.behavior.ActivationStoreBehavior
+import org.apache.openwhisk.core.entity.{EntityPath, WhiskActivation}
+import org.apache.openwhisk.utils.retry
+import org.junit.runner.RunWith
+import org.scalatest.FlatSpec
+import org.scalatest.junit.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class ArtifactActivationStoreTests
+ extends FlatSpec
+ with ArtifactActivationStoreBehaviorBase
+ with ActivationStoreBehavior {
+ override def checkQueryActivations(namespace: String,
+ name: Option[String] = None,
+ skip: Int = 0,
+ limit: Int = 1000,
+ includeDocs: Boolean = false,
+ since: Option[Instant] = None,
+ upto: Option[Instant] = None,
+ context: UserContext,
+ expected:
IndexedSeq[WhiskActivation])(implicit transid: TransactionId): Unit = {
+ // This is for compatible with CouchDB as it use option
`StaleParameter.UpdateAfter`
+ retry(super.checkQueryActivations(namespace, name, skip, limit,
includeDocs, since, upto, context, expected), 100)
+ }
+
+ override def checkCountActivations(namespace: String,
+ name: Option[EntityPath] = None,
+ skip: Int = 0,
+ since: Option[Instant] = None,
+ upto: Option[Instant] = None,
+ context: UserContext,
+ expected: Long)(implicit transid:
TransactionId): Unit = {
+ retry(super.checkCountActivations(namespace, name, skip, since, upto,
context, expected), 100)
+ }
+}
diff --git
a/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreBehavior.scala
b/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreBehavior.scala
new file mode 100644
index 0000000..83939eb
--- /dev/null
+++
b/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreBehavior.scala
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.openwhisk.core.database.test.behavior
+
+trait ActivationStoreBehavior
+ extends ActivationStoreBehaviorBase
+ with ActivationStoreCRUDBehaviors
+ with ActivationStoreQueryBehaviors
diff --git
a/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreBehaviorBase.scala
b/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreBehaviorBase.scala
new file mode 100644
index 0000000..f8caad6
--- /dev/null
+++
b/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreBehaviorBase.scala
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.openwhisk.core.database.test.behavior
+
+import java.time.Instant
+
+import akka.stream.ActorMaterializer
+import common.{StreamLogging, WskActorSystem}
+import org.apache.openwhisk.common.TransactionId
+import org.apache.openwhisk.core.database.{ActivationStore,
CacheChangeNotification, UserContext}
+import
org.apache.openwhisk.core.database.test.behavior.ArtifactStoreTestUtil.storeAvailable
+import org.apache.openwhisk.core.entity._
+import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures}
+import org.scalatest.{BeforeAndAfterEach, FlatSpec, Matchers, Outcome}
+
+import scala.collection.mutable.ListBuffer
+import scala.concurrent.Await
+import scala.concurrent.duration.Duration
+import scala.concurrent.duration.DurationInt
+import scala.language.postfixOps
+import scala.util.{Random, Try}
+
+trait ActivationStoreBehaviorBase
+ extends FlatSpec
+ with ScalaFutures
+ with Matchers
+ with StreamLogging
+ with WskActorSystem
+ with IntegrationPatience
+ with BeforeAndAfterEach {
+
+ protected implicit val materializer: ActorMaterializer = ActorMaterializer()
+ protected implicit val notifier: Option[CacheChangeNotification] = None
+
+ def context: UserContext
+ def activationStore: ActivationStore
+ private val docsToDelete = ListBuffer[(UserContext, ActivationId)]()
+
+ def storeType: String
+
+ protected def transId() =
TransactionId(Random.alphanumeric.take(32).mkString)
+
+ override def afterEach(): Unit = {
+ cleanup()
+ stream.reset()
+ }
+
+ override protected def withFixture(test: NoArgTest): Outcome = {
+ assume(storeAvailable(storeAvailableCheck), s"$storeType not configured or
available")
+ val outcome = super.withFixture(test)
+ if (outcome.isFailed) {
+ println(logLines.mkString("\n"))
+ }
+ outcome
+ }
+
+ protected def storeAvailableCheck: Try[Any] = Try(true)
+ //~----------------------------------------< utility methods >
+
+ protected def store(activation: WhiskActivation, context: UserContext)(
+ implicit transid: TransactionId,
+ notifier: Option[CacheChangeNotification]): DocInfo = {
+ val doc = activationStore.store(activation, context).futureValue
+ docsToDelete.append((context, ActivationId(activation.docid.asString)))
+ doc
+ }
+
+ protected def newActivation(ns: String, actionName: String, start: Long):
WhiskActivation = {
+ WhiskActivation(
+ EntityPath(ns),
+ EntityName(actionName),
+ Subject(),
+ ActivationId.generate(),
+ Instant.ofEpochMilli(start),
+ Instant.ofEpochMilli(start + 1000))
+ }
+
+ /**
+ * Deletes all documents added to gc queue.
+ */
+ def cleanup()(implicit timeout: Duration = 10 seconds): Unit = {
+ implicit val tid: TransactionId = transId()
+ docsToDelete.map { e =>
+ Try {
+ Await.result(activationStore.delete(e._2, e._1), timeout)
+ }
+ }
+ docsToDelete.clear()
+ }
+
+}
diff --git
a/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreCRUDBehaviors.scala
b/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreCRUDBehaviors.scala
new file mode 100644
index 0000000..506ccec
--- /dev/null
+++
b/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreCRUDBehaviors.scala
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.openwhisk.core.database.test.behavior
+
+import org.apache.openwhisk.common.TransactionId
+import org.apache.openwhisk.core.database.NoDocumentException
+import org.apache.openwhisk.core.entity.ActivationId
+
+import scala.util.Random
+
+trait ActivationStoreCRUDBehaviors extends ActivationStoreBehaviorBase {
+
+ behavior of s"${storeType}ActivationStore store"
+
+ it should "put activation and get docinfo" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action = s"action1_${Random.alphanumeric.take(4).mkString}"
+ val activation = newActivation(namespace, action, 1L)
+ val doc = store(activation, context)
+ doc shouldBe activation.docinfo
+ }
+
+ behavior of s"${storeType}ActivationStore delete"
+
+ it should "deletes existing activation" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action = s"action1_${Random.alphanumeric.take(4).mkString}"
+ val activation = newActivation(namespace, action, 1L)
+ store(activation, context)
+ activationStore.delete(ActivationId(activation.docid.asString),
context).futureValue shouldBe true
+ }
+
+ it should "throws NoDocumentException when activation does not exist" in {
+ implicit val tid: TransactionId = transId()
+ activationStore.delete(ActivationId("non-existing-doc"),
context).failed.futureValue shouldBe a[NoDocumentException]
+ }
+
+ behavior of s"${storeType}ActivationStore get"
+
+ it should "get existing activation matching id" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action = s"action1_${Random.alphanumeric.take(4).mkString}"
+ val activation = newActivation(namespace, action, 1L)
+ store(activation, context)
+ activationStore.get(ActivationId(activation.docid.asString),
context).futureValue shouldBe activation
+ }
+
+ it should "throws NoDocumentException when activation does not exist" in {
+ implicit val tid: TransactionId = transId()
+ activationStore.get(ActivationId("non-existing-doc"),
context).failed.futureValue shouldBe a[NoDocumentException]
+ }
+}
diff --git
a/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreQueryBehaviors.scala
b/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreQueryBehaviors.scala
new file mode 100644
index 0000000..c8123d5
--- /dev/null
+++
b/tests/src/test/scala/org/apache/openwhisk/core/database/test/behavior/ActivationStoreQueryBehaviors.scala
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.openwhisk.core.database.test.behavior
+
+import java.time.Instant
+
+import org.apache.openwhisk.common.TransactionId
+import org.apache.openwhisk.core.database.UserContext
+import org.apache.openwhisk.core.entity.{EntityPath, WhiskActivation}
+import spray.json.{JsNumber, JsObject}
+
+import scala.util.Random
+
+trait ActivationStoreQueryBehaviors extends ActivationStoreBehaviorBase {
+
+ protected def checkQueryActivations(namespace: String,
+ name: Option[String] = None,
+ skip: Int = 0,
+ limit: Int = 1000,
+ includeDocs: Boolean = false,
+ since: Option[Instant] = None,
+ upto: Option[Instant] = None,
+ context: UserContext,
+ expected:
IndexedSeq[WhiskActivation])(implicit transid: TransactionId): Unit = {
+ val result =
+ name
+ .map { n =>
+ activationStore
+ .listActivationsMatchingName(
+ EntityPath(namespace),
+ EntityPath(n),
+ skip = skip,
+ limit = limit,
+ includeDocs = includeDocs,
+ since = since,
+ upto = upto,
+ context = context)
+ }
+ .getOrElse {
+ activationStore
+ .listActivationsInNamespace(
+ EntityPath(namespace),
+ skip = skip,
+ limit = limit,
+ includeDocs = includeDocs,
+ since = since,
+ upto = upto,
+ context = context)
+ }
+ .map { r =>
+ r.fold(left => left, right => right.map(wa => if (includeDocs)
wa.toExtendedJson() else wa.summaryAsJson))
+ }
+ .futureValue
+
+ result should contain theSameElementsAs expected.map(wa =>
+ if (includeDocs) wa.toExtendedJson() else wa.summaryAsJson)
+ }
+
+ protected def checkCountActivations(namespace: String,
+ name: Option[EntityPath] = None,
+ skip: Int = 0,
+ since: Option[Instant] = None,
+ upto: Option[Instant] = None,
+ context: UserContext,
+ expected: Long)(implicit transid:
TransactionId): Unit = {
+ val result = activationStore
+ .countActivationsInNamespace(
+ EntityPath(namespace),
+ name = name,
+ skip = skip,
+ since = since,
+ upto = upto,
+ context = context)
+ .futureValue
+
+ result shouldBe JsObject(WhiskActivation.collectionName ->
JsNumber(expected))
+ }
+
+ behavior of s"${storeType}ActivationStore listActivationsInNamespace"
+
+ it should "find all entities" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+ val action2 = s"action2_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ val activations2 = (1000 until 1100 by 10).map(newActivation(namespace,
action2, _))
+ activations2 foreach (store(_, context))
+
+ checkQueryActivations(namespace, context = context, expected = activations
++ activations2)
+ }
+
+ it should "support since and upto filters" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkQueryActivations(
+ namespace,
+ since = Some(Instant.ofEpochMilli(1060)),
+ context = context,
+ expected = activations.takeRight(4))
+
+ checkQueryActivations(
+ namespace,
+ upto = Some(Instant.ofEpochMilli(1060)),
+ context = context,
+ expected = activations.take(7))
+
+ checkQueryActivations(
+ namespace,
+ since = Some(Instant.ofEpochMilli(1030)),
+ upto = Some(Instant.ofEpochMilli(1060)),
+ context = context,
+ expected = activations.take(7).takeRight(4))
+ }
+
+ it should "support skipping results" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkQueryActivations(namespace, skip = 5, context = context, expected =
activations.take(5))
+ }
+
+ it should "support limiting results" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkQueryActivations(namespace, limit = 5, context = context, expected =
activations.takeRight(5))
+ }
+
+ it should "support including complete docs" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkQueryActivations(namespace, includeDocs = true, context = context,
expected = activations)
+ }
+
+ it should "throw exception for negative limits and skip" in {
+ implicit val tid: TransactionId = transId()
+
+ a[IllegalArgumentException] should be thrownBy activationStore
+ .listActivationsInNamespace(EntityPath("test"), skip = -1, limit = 10,
context = context)
+
+ a[IllegalArgumentException] should be thrownBy activationStore
+ .listActivationsInNamespace(EntityPath("test"), skip = 0, limit = -1,
context = context)
+ }
+
+ behavior of s"${storeType}ActivationStore listActivationsMatchingName"
+
+ it should "find all entities matching name" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+ val action2 = s"action2_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ val activations2 = (1000 until 1100 by 10).map(newActivation(namespace,
action2, _))
+ activations2 foreach (store(_, context))
+
+ checkQueryActivations(namespace, Some(action1), context = context,
expected = activations)
+ }
+
+ it should "support since and upto filters" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkQueryActivations(
+ namespace,
+ Some(action1),
+ since = Some(Instant.ofEpochMilli(1060)),
+ context = context,
+ expected = activations.takeRight(4))
+
+ checkQueryActivations(
+ namespace,
+ Some(action1),
+ upto = Some(Instant.ofEpochMilli(1060)),
+ context = context,
+ expected = activations.take(7))
+
+ checkQueryActivations(
+ namespace,
+ Some(action1),
+ since = Some(Instant.ofEpochMilli(1030)),
+ upto = Some(Instant.ofEpochMilli(1060)),
+ context = context,
+ expected = activations.take(7).takeRight(4))
+ }
+
+ it should "support skipping results" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkQueryActivations(namespace, Some(action1), skip = 5, context =
context, expected = activations.take(5))
+ }
+
+ it should "support limiting results" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkQueryActivations(namespace, Some(action1), limit = 5, context =
context, expected = activations.takeRight(5))
+ }
+
+ it should "support including complete docs" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkQueryActivations(namespace, Some(action1), includeDocs = true,
context = context, expected = activations)
+ }
+
+ it should "throw exception for negative limits and skip" in {
+ implicit val tid: TransactionId = transId()
+
+ a[IllegalArgumentException] should be thrownBy
activationStore.listActivationsMatchingName(
+ EntityPath("test"),
+ name = EntityPath("testact"),
+ skip = -1,
+ limit = 10,
+ context = context)
+
+ a[IllegalArgumentException] should be thrownBy
activationStore.listActivationsMatchingName(
+ EntityPath("test"),
+ name = EntityPath("testact"),
+ skip = 0,
+ limit = -1,
+ context = context)
+ }
+
+ behavior of s"${storeType}ActivationStore countActivationsInNamespace"
+
+ it should "should count all created activations" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkCountActivations(namespace, None, context = context, expected = 10)
+ }
+
+ it should "count with option name" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+ val action2 = s"action2_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ val activations2 = (1000 until 1100 by 10).map(newActivation(namespace,
action2, _))
+ activations2 foreach (store(_, context))
+
+ checkCountActivations(namespace, Some(EntityPath(action1)), context =
context, expected = 10)
+
+ checkCountActivations(namespace, Some(EntityPath(action2)), context =
context, expected = 10)
+ }
+
+ it should "count with since and upto" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkCountActivations(namespace, None, since =
Some(Instant.ofEpochMilli(1060L)), context = context, expected = 4)
+
+ checkCountActivations(namespace, None, upto =
Some(Instant.ofEpochMilli(1060L)), context = context, expected = 7)
+
+ checkCountActivations(
+ namespace,
+ None,
+ since = Some(Instant.ofEpochMilli(1030L)),
+ upto = Some(Instant.ofEpochMilli(1060L)),
+ context = context,
+ expected = 4)
+ }
+
+ it should "count with skip" in {
+ implicit val tid: TransactionId = transId()
+ val namespace = s"ns_${Random.alphanumeric.take(4).mkString}"
+ val action1 = s"action1_${Random.alphanumeric.take(4).mkString}"
+
+ val activations = (1000 until 1100 by 10).map(newActivation(namespace,
action1, _))
+ activations foreach (store(_, context))
+
+ checkCountActivations(namespace, None, skip = 4, context = context,
expected = 10 - 4)
+ checkCountActivations(namespace, None, skip = 1000, context = context,
expected = 0)
+ }
+
+ it should "throw exception for negative skip" in {
+ implicit val tid: TransactionId = transId()
+
+ a[IllegalArgumentException] should be thrownBy
activationStore.countActivationsInNamespace(
+ namespace = EntityPath("test"),
+ name = None,
+ skip = -1,
+ context = context)
+ }
+}