You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by ma...@apache.org on 2018/08/28 11:21:06 UTC

[incubator-openwhisk] branch master updated: Make tests with CouchDB-views more stable. (#3982)

This is an automated email from the ASF dual-hosted git repository.

markusthoemmes 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 1cc3832  Make tests with CouchDB-views more stable. (#3982)
1cc3832 is described below

commit 1cc38322dfbf2b8628a27cd3b85851d8a0de6e3b
Author: Christian Bickel <gi...@cbickel.de>
AuthorDate: Tue Aug 28 13:21:01 2018 +0200

    Make tests with CouchDB-views more stable. (#3982)
    
    This commit enhances the method `waitOnView` to be successful at least 5 times. The reason for this is, that there could be some inconsistency between several CouchDB-nodes.
    Querying the view more often successful, increases the probability, that the view is computed on all nodes before the test continues.
---
 .../scala/whisk/core/database/test/DbUtils.scala   | 124 +++++++++++----------
 1 file changed, 64 insertions(+), 60 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 7f83d27..f4a1aac 100644
--- a/tests/src/test/scala/whisk/core/database/test/DbUtils.scala
+++ b/tests/src/test/scala/whisk/core/database/test/DbUtils.scala
@@ -55,6 +55,10 @@ trait DbUtils extends Assertions {
   val cnt = new AtomicInteger(0)
   def transid() = TransactionId(cnt.incrementAndGet().toString)
 
+  // Call each few successfully 5 before the test continues to increase probability, that each node of the
+  // CouchDB/Cloudant cluster is updated.
+  val successfulViewCalls = 5
+
   /**
    * Retry an operation 'step()' awaiting its result up to 'timeout'.
    * Attempt the operation up to 'count' times. The future from the
@@ -93,7 +97,8 @@ trait DbUtils extends Assertions {
   def waitOnView[Au](db: ArtifactStore[Au], namespace: EntityName, count: Int, view: View)(
     implicit context: ExecutionContext,
     transid: TransactionId,
-    timeout: Duration): Unit = waitOnViewImpl(db, namespace.asString, count, view)
+    timeout: Duration): Unit =
+    waitOnViewImpl(db, List(namespace.asString), List(namespace.asString, WhiskEntityQueries.TOP), count, view)
 
   /**
    * Wait on a view to update with documents added to namespace. This uses retry above,
@@ -103,51 +108,41 @@ trait DbUtils extends Assertions {
   def waitOnView[Au](db: ArtifactStore[Au], path: EntityPath, count: Int, view: View)(
     implicit context: ExecutionContext,
     transid: TransactionId,
-    timeout: Duration): Unit = waitOnViewImpl(db, path.asString, count, view)
+    timeout: Duration): Unit =
+    waitOnViewImpl(db, List(path.asString), List(path.asString, WhiskEntityQueries.TOP), count, view)
 
   /**
-   * Wait on a view to update with documents added to namespace. This uses retry above,
+   * 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.
    */
-  private def waitOnViewImpl[Au](db: ArtifactStore[Au], key: String, count: Int, view: View)(
-    implicit context: ExecutionContext,
-    transid: TransactionId,
-    timeout: Duration): Unit = {
-    val success = retry(
-      () => {
-        val startKey = List(key)
-        val endKey = List(key, WhiskEntityQueries.TOP)
-        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")
-  }
+  def waitOnView[Au](db: ArtifactStore[Au], count: Int, view: View)(implicit context: ExecutionContext,
+                                                                    transid: TransactionId,
+                                                                    timeout: Duration): Unit =
+    waitOnViewImpl(db, List.empty, List.empty, count, view)
 
   /**
-   * Wait on a view to update with documents added(don't specify the namespace). This uses retry above,
+   * Wait on a view to update with documents added to 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
+  private def waitOnViewImpl[Au](
+    db: ArtifactStore[Au],
+    startKey: List[String],
+    endKey: List[String],
+    count: Int,
+    view: View)(implicit context: ExecutionContext, transid: TransactionId, timeout: Duration): Unit = {
+    // Query the view at least `successfulViewCalls` times successfully, to handle inconsistency between several CouchDB-nodes.
+    (0 until successfulViewCalls).map { _ =>
+      val success = retry(() => {
         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")
+      }, timeout)
+      assert(success.isSuccess, "wait aborted")
+    }
   }
 
   /**
@@ -161,14 +156,17 @@ trait DbUtils extends Assertions {
     namespace: EntityPath,
     count: Int,
     includeDocs: Boolean = false)(implicit context: ExecutionContext, transid: TransactionId, timeout: Duration) = {
-    val success = retry(() => {
-      factory.listCollectionInNamespace(db, namespace, 0, 0, includeDocs) map { l =>
-        if (l.fold(_.length, _.length) < count) {
-          throw RetryOp()
-        } else true
-      }
-    }, timeout)
-    assert(success.isSuccess, "wait aborted")
+    // Query the view at least `successfulViewCalls` times successfully, to handle inconsistency between several CouchDB-nodes.
+    (0 until successfulViewCalls).map { _ =>
+      val success = retry(() => {
+        factory.listCollectionInNamespace(db, namespace, 0, 0, includeDocs) map { l =>
+          if (l.fold(_.length, _.length) < count) {
+            throw RetryOp()
+          } else true
+        }
+      }, timeout)
+      assert(success.isSuccess, "wait aborted")
+    }
   }
 
   /**
@@ -178,14 +176,17 @@ trait DbUtils extends Assertions {
   def waitOnView(db: AuthStore, authkey: BasicAuthenticationAuthKey, count: Int)(implicit context: ExecutionContext,
                                                                                  transid: TransactionId,
                                                                                  timeout: Duration) = {
-    val success = retry(() => {
-      Identity.list(db, List(authkey.uuid.asString, authkey.key.asString)) map { l =>
-        if (l.length != count) {
-          throw RetryOp()
-        } else true
-      }
-    }, timeout)
-    assert(success.isSuccess, "wait aborted after: " + timeout + ": " + success)
+    // Query the view at least `successfulViewCalls` times successfully, to handle inconsistency between several CouchDB-nodes.
+    (0 until successfulViewCalls).map { _ =>
+      val success = retry(() => {
+        Identity.list(db, List(authkey.uuid.asString, authkey.key.asString)) map { l =>
+          if (l.length != count) {
+            throw RetryOp()
+          } else true
+        }
+      }, timeout)
+      assert(success.isSuccess, "wait aborted after: " + timeout + ": " + success)
+    }
   }
 
   /**
@@ -194,20 +195,23 @@ trait DbUtils extends Assertions {
   def waitOnView(db: CouchDbRestClient, designDocName: String, viewName: String, count: Int)(
     implicit context: ExecutionContext,
     timeout: Duration) = {
-    val success = retry(
-      () => {
-        db.executeView(designDocName, viewName)().map {
-          case Right(doc) =>
-            val length = doc.fields("rows").convertTo[List[JsObject]].length
-            if (length != count) {
+    // Query the view at least `successfulViewCalls` times successfully, to handle inconsistency between several CouchDB-nodes.
+    (0 until successfulViewCalls).map { _ =>
+      val success = retry(
+        () => {
+          db.executeView(designDocName, viewName)().map {
+            case Right(doc) =>
+              val length = doc.fields("rows").convertTo[List[JsObject]].length
+              if (length != count) {
+                throw RetryOp()
+              } else true
+            case Left(_) =>
               throw RetryOp()
-            } else true
-          case Left(_) =>
-            throw RetryOp()
-        }
-      },
-      timeout)
-    assert(success.isSuccess, "wait aborted after: " + timeout + ": " + success)
+          }
+        },
+        timeout)
+      assert(success.isSuccess, "wait aborted after: " + timeout + ": " + success)
+    }
   }
 
   /**