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 2578703 Use ArtifactStore to manipulate data in NamespaceBlacklistTests (#3890) 2578703 is described below commit 2578703d67ba693f27309c468b4ca5c62bbbe79e Author: jiangpch <jiangpengch...@navercorp.com> AuthorDate: Mon Aug 20 12:33:32 2018 +0800 Use ArtifactStore to manipulate data in NamespaceBlacklistTests (#3890) Use ArtifactStore abstraction instead of CouchDB specific code to make NamespaceBlacklistTests generic. This enables it to be run against all supported databases --- .../scala/whisk/core/database/test/DbUtils.scala | 22 +++++ .../ArtifactStoreSubjectQueryBehaviors.scala | 37 +------- .../invoker/test/NamespaceBlacklistTests.scala | 103 +++++++-------------- 3 files changed, 59 insertions(+), 103 deletions(-) diff --git a/tests/src/test/scala/whisk/core/database/test/DbUtils.scala b/tests/src/test/scala/whisk/core/database/test/DbUtils.scala index 6d39304..7f83d27 100644 --- a/tests/src/test/scala/whisk/core/database/test/DbUtils.scala +++ b/tests/src/test/scala/whisk/core/database/test/DbUtils.scala @@ -129,6 +129,28 @@ trait DbUtils extends Assertions { } /** + * Wait on a view to update with documents added(don't specify the namespace). This uses retry above, + * where the step performs a direct db query to retrieve the view and check the count + * matches the given value. + */ + def waitOnView[Au](db: ArtifactStore[Au], count: Int, view: View)(implicit context: ExecutionContext, + transid: TransactionId, + timeout: Duration): Unit = { + val success = retry( + () => { + val startKey = List.empty + val endKey = List.empty + db.query(view.name, startKey, endKey, 0, 0, false, true, false, StaleParameter.No) map { l => + if (l.length != count) { + throw RetryOp() + } else true + } + }, + timeout) + assert(success.isSuccess, "wait aborted") + } + + /** * Wait on a view specific to a collection to update with documents added to that collection in namespace. * This uses retry above, where the step performs a collection-specific view query using the collection * factory. The result count from the view is checked against the given value. diff --git a/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreSubjectQueryBehaviors.scala b/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreSubjectQueryBehaviors.scala index a50b29c..06150d5 100644 --- a/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreSubjectQueryBehaviors.scala +++ b/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreSubjectQueryBehaviors.scala @@ -17,16 +17,12 @@ package whisk.core.database.test.behavior -import spray.json.DefaultJsonProtocol._ import spray.json.{JsBoolean, JsObject} import whisk.common.TransactionId -import whisk.core.database.{NoDocumentException, StaleParameter} +import whisk.core.database.NoDocumentException import whisk.core.entity._ -import whisk.core.entity.types.AuthStore import whisk.core.invoker.NamespaceBlacklist -import scala.concurrent.duration.Duration - trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { behavior of s"${storeType}ArtifactStore query subjects" @@ -138,7 +134,7 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { //2 for limits //2 for 2 namespace in user blocked - waitOnBlacklistView(authStore, 2 + 2) + waitOnView(authStore, 2 + 2, NamespaceBlacklist.view) //Use contains assertion to ensure that even if same db is used by other setup //we at least get our expected entries @@ -148,35 +144,6 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { .futureValue should contain allElementsOf Seq(n1, n2, n4, n5).map(_.asString).toSet } - def waitOnBlacklistView(db: AuthStore, count: Int)(implicit transid: TransactionId, timeout: Duration) = { - val success = retry(() => { - blacklistCount().map { listCount => - if (listCount != count) { - throw RetryOp() - } else true - } - }, timeout) - assert(success.isSuccess, "wait aborted after: " + timeout + ": " + success) - } - - private def blacklistCount()(implicit transid: TransactionId) = { - //NamespaceBlacklist uses StaleParameter.UpdateAfter which would lead to race condition - //So use actual call here - authStore - .query( - table = NamespaceBlacklist.view.name, - startKey = List.empty, - endKey = List.empty, - skip = 0, - limit = Int.MaxValue, - includeDocs = false, - descending = true, - reduce = false, - stale = StaleParameter.No) - .map(_.map(_.fields("key").convertTo[String]).toSet) - .map(_.size) - } - private class LimitEntity(name: EntityName, limits: UserLimits) extends WhiskAuth(Subject(), Set.empty) { override def docid = DocId(s"${name.name}/limits") diff --git a/tests/src/test/scala/whisk/core/invoker/test/NamespaceBlacklistTests.scala b/tests/src/test/scala/whisk/core/invoker/test/NamespaceBlacklistTests.scala index 033678c..c9f5a7f 100644 --- a/tests/src/test/scala/whisk/core/invoker/test/NamespaceBlacklistTests.scala +++ b/tests/src/test/scala/whisk/core/invoker/test/NamespaceBlacklistTests.scala @@ -23,13 +23,9 @@ import org.junit.runner.RunWith import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures} import org.scalatest.junit.JUnitRunner import org.scalatest.{FlatSpec, Matchers} -import pureconfig.loadConfigOrThrow -import spray.json.DefaultJsonProtocol._ import spray.json._ import whisk.common.TransactionId -import whisk.core.database.CouchDbConfig -import whisk.core.ConfigKeys -import whisk.core.database.test.{DbUtils, ExtendedCouchDbRestClient} +import whisk.core.database.test.DbUtils import whisk.core.entity._ import whisk.core.invoker.NamespaceBlacklist import whisk.utils.{retry => testRetry} @@ -51,38 +47,13 @@ class NamespaceBlacklistTests implicit val materializer = ActorMaterializer() implicit val tid = TransactionId.testing - val dbConfig = loadConfigOrThrow[CouchDbConfig](ConfigKeys.couchdb) val authStore = WhiskAuthStore.datastore() - val subjectsDb = new ExtendedCouchDbRestClient( - dbConfig.protocol, - dbConfig.host, - dbConfig.port, - dbConfig.username, - dbConfig.password, - dbConfig.databaseFor[WhiskAuth]) - - /* Identities needed for the first test */ - val uuid1 = UUID() - val uuid2 = UUID() - val uuid3 = UUID() - val identities = Seq( - Identity( - Subject(), - Namespace(EntityName("testnamespace1"), uuid1), - BasicAuthenticationAuthKey(uuid1, Secret()), - Set.empty, - UserLimits(invocationsPerMinute = Some(0))), - Identity( - Subject(), - Namespace(EntityName("testnamespace2"), uuid2), - BasicAuthenticationAuthKey(uuid2, Secret()), - Set.empty, - UserLimits(concurrentInvocations = Some(0))), - Identity( - Subject(), - Namespace(EntityName("testnamespace3"), uuid3), - BasicAuthenticationAuthKey(uuid3, Secret()), - Set.empty, + + val limitsAndAuths = Seq( + new LimitEntity(EntityName("testnamespace1"), UserLimits(invocationsPerMinute = Some(0))), + new LimitEntity(EntityName("testnamespace2"), UserLimits(concurrentInvocations = Some(0))), + new LimitEntity( + EntityName("testnamespace3"), UserLimits(invocationsPerMinute = Some(1), concurrentInvocations = Some(1)))) /* Subject document needed for the second test */ @@ -92,49 +63,34 @@ class NamespaceBlacklistTests val ak5 = BasicAuthenticationAuthKey(uuid5, Secret()) val ns4 = Namespace(EntityName("different1"), uuid4) val ns5 = Namespace(EntityName("different2"), uuid5) - val subject = WhiskAuth(Subject(), Set(WhiskNamespace(ns4, ak4), WhiskNamespace(ns5, ak5))) - val blockedSubject = JsObject(subject.toJson.fields + ("blocked" -> true.toJson)) + val blockedSubject = new ExtendedAuth(Subject(), Set(WhiskNamespace(ns4, ak4), WhiskNamespace(ns5, ak5)), true) - val blockedNamespacesCount = 2 + subject.namespaces.size + val blockedNamespacesCount = 2 + blockedSubject.namespaces.size - def authToIdentities(auth: WhiskAuth): Set[Identity] = { + private def authToIdentities(auth: WhiskAuth): Set[Identity] = { auth.namespaces.map { ns => Identity(auth.subject, ns.namespace, ns.authkey, Set.empty, UserLimits()) } } - override protected def withFixture(test: NoArgTest) = { - assume(isCouchStore(authStore)) - super.withFixture(test) + private def limitToIdentity(limit: LimitEntity): Identity = { + val namespace = limit.docid.id.dropRight("/limits".length) + Identity( + limit.subject, + Namespace(EntityName(namespace), UUID()), + BasicAuthenticationAuthKey(UUID(), Secret()), + Set(), + UserLimits()) } override def beforeAll() = { - val documents = identities.map { i => - (i.namespace.name + "/limits", i.limits.toJson.asJsObject) - } :+ (subject.subject.asString, blockedSubject) - - // Add all documents to the database - documents.foreach { case (id, doc) => subjectsDb.putDoc(id, doc).futureValue } - - // Waits for the 2 blocked identities + the namespaces of the blocked subject - waitOnView(subjectsDb, NamespaceBlacklist.view.ddoc, NamespaceBlacklist.view.view, blockedNamespacesCount)( - executionContext, - 1.minute) + limitsAndAuths foreach (put(authStore, _)) + put(authStore, blockedSubject) + waitOnView(authStore, blockedNamespacesCount, NamespaceBlacklist.view) } override def afterAll() = { - val ids = identities.map(_.namespace.name + "/limits") :+ subject.subject.asString - - // Force remove all documents with those ids by first getting and then deleting the documents - ids.foreach { id => - val docE = subjectsDb.getDoc(id).futureValue - docE shouldBe 'right - val doc = docE.right.get - subjectsDb - .deleteDoc(doc.fields("_id").convertTo[String], doc.fields("_rev").convertTo[String]) - .futureValue - } - + cleanup() super.afterAll() } @@ -145,7 +101,18 @@ class NamespaceBlacklistTests blacklist.refreshBlacklist().futureValue should have size blockedNamespacesCount }, 60, Some(1.second)) - identities.map(blacklist.isBlacklisted) shouldBe Seq(true, true, false) - authToIdentities(subject).toSeq.map(blacklist.isBlacklisted) shouldBe Seq(true, true) + limitsAndAuths.map(limitToIdentity).map(blacklist.isBlacklisted) shouldBe Seq(true, true, false) + authToIdentities(blockedSubject).toSeq.map(blacklist.isBlacklisted) shouldBe Seq(true, true) + } + + class LimitEntity(name: EntityName, limits: UserLimits) extends WhiskAuth(Subject(), namespaces = Set.empty) { + override def docid = DocId(s"${name.name}/limits") + + override def toJson = UserLimits.serdes.write(limits).asJsObject + } + + class ExtendedAuth(subject: Subject, namespaces: Set[WhiskNamespace], blocked: Boolean) + extends WhiskAuth(subject, namespaces) { + override def toJson = JsObject(super.toJson.fields + ("blocked" -> JsBoolean(blocked))) } }