MB-21029: ep_test_apis: make wait_for_stat_XXX functions templated 42/67942/6
authorDave Rigby <daver@couchbase.com>
Fri, 23 Sep 2016 10:12:36 +0000 (11:12 +0100)
committerDave Rigby <daver@couchbase.com>
Tue, 27 Sep 2016 14:11:32 +0000 (14:11 +0000)
There is a range of helper functions to wait for a stat to meet some
criteria (equal, not equal, greater, ...), and currently these are
duplicated for each type (int, string, ...) required.

As the subsequent fix for MB-21029 needs a wait_for_stat_to_change for
the std::string type, genericize the current wait_for_stat function so
it can be used with any type.

Change-Id: I681218d31c4dcd1ef8b34de225efd13e99bbf8db
Reviewed-on: http://review.couchbase.org/67942
Reviewed-by: Manu Dhundi <manu@couchbase.com>
Tested-by: buildbot <build@couchbase.com>
tests/ep_test_apis.cc
tests/ep_test_apis.h
tests/ep_testsuite.cc
tests/ep_testsuite_dcp.cc

index 8dbe1c2..35acbd5 100644 (file)
@@ -1136,28 +1136,20 @@ public:
  * If the given statname doesn't exist under the given statname, throws a
  * std::out_of_range exception.
  */
-int get_int_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
-                 const char *statkey) {
+template<>
+int get_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
+             const char *statname, const char *statkey) {
     return std::stoi(get_str_stat(h, h1, statname, statkey));
 }
-
-float get_float_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
-                     const char *statkey) {
-    return std::stof(get_str_stat(h, h1, statname, statkey));
-}
-
-uint32_t get_ul_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
-                      const char *statkey) {
-    return std::stoul(get_str_stat(h, h1, statname, statkey));
-}
-
-uint64_t get_ull_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
-                      const char *statkey) {
+template<>
+uint64_t get_stat(ENGINE_HANDLE* h, ENGINE_HANDLE_V1* h1,
+                  const char* statname, const char* statkey) {
     return std::stoull(get_str_stat(h, h1, statname, statkey));
 }
 
-std::string get_str_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
-                         const char *statname, const char *statkey) {
+template<>
+std::string get_stat(ENGINE_HANDLE* h, ENGINE_HANDLE_V1* h1,
+                     const char* statname, const char* statkey) {
     std::lock_guard<std::mutex> lh(vals_mutex);
 
     requested_stat_name = statname;
@@ -1179,6 +1171,32 @@ std::string get_str_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
     return actual_stat_value;
 }
 
+/// Backward-compatible functions (encode type name in function name).
+int get_int_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
+             const char *statkey) {
+    return get_stat<int>(h, h1, statname, statkey);
+}
+
+float get_float_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
+                     const char *statkey) {
+    return std::stof(get_str_stat(h, h1, statname, statkey));
+}
+
+uint32_t get_ul_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
+                      const char *statkey) {
+    return std::stoul(get_str_stat(h, h1, statname, statkey));
+}
+
+uint64_t get_ull_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
+                      const char *statkey) {
+    return get_stat<uint64_t>(h, h1, statname, statkey);
+}
+
+std::string get_str_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
+                         const char *statname, const char *statkey) {
+    return get_stat<std::string>(h, h1, statname, statkey);
+}
+
 bool get_bool_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
                    const char *statkey) {
     const auto s = get_str_stat(h, h1, statname, statkey);
@@ -1276,84 +1294,6 @@ void verify_curr_items(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, int exp,
     }
 }
 
-/** Helper class used when waiting on statistics to reach a certain value -
- * aggregates how long we have been waiting and aborts if the maximum wait time
- * is exceeded.
- */
-template <typename T>
-class WaitTimeAccumulator
-{
-public:
-    WaitTimeAccumulator(const char* compare_name,
-                        const char* stat_, const char* stat_key,
-                        const T final_, const time_t wait_time_in_secs)
-    : compareName(compare_name),
-      stat(stat_),
-      statKey(stat_key),
-      final(final_),
-      maxWaitTime(wait_time_in_secs * 1000 * 1000),
-      totalSleepTime(0) {}
-
-    void incrementAndAbortIfLimitReached(T last_value,
-                                         const useconds_t sleep_time)
-    {
-        totalSleepTime += sleep_time;
-        if (totalSleepTime >= maxWaitTime) {
-            std::cerr << "Exceeded maximum wait time of " << maxWaitTime
-                      << "us waiting for stat '" << stat;
-            if (statKey != NULL) {
-                std::cerr << "(" << statKey << ")";
-            }
-            std::cerr << "' " << compareName << " " << final
-                      << " (last value:" << last_value << ") - aborting."
-                      << std::endl;
-            abort();
-        }
-    }
-
-private:
-    const char* compareName;
-    const char* stat;
-    const char* statKey;
-    const T final;
-    const useconds_t maxWaitTime;
-    useconds_t totalSleepTime;
-};
-
-
-void wait_for_stat_change(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
-                          const char *stat, int initial,
-                          const char *stat_key,
-                          const time_t max_wait_time_in_secs) {
-    useconds_t sleepTime = 128;
-    WaitTimeAccumulator<int> accumulator("to change from", stat, stat_key,
-                                         initial, max_wait_time_in_secs);
-    for (;;) {
-        auto current = get_int_stat(h, h1, stat, stat_key);
-        if (current != initial) {
-            break;
-        }
-        accumulator.incrementAndAbortIfLimitReached(current, sleepTime);
-        decayingSleep(&sleepTime);
-    }
-}
-
-void wait_for_stat_to_be(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
-                         const char *stat, int final, const char* stat_key,
-                         const time_t max_wait_time_in_secs) {
-    useconds_t sleepTime = 128;
-    WaitTimeAccumulator<int> accumulator("to be", stat, stat_key, final,
-                                         max_wait_time_in_secs);
-    for (;;) {
-        auto current = get_int_stat(h, h1, stat, stat_key);
-        if (current == final) {
-            break;
-        }
-        accumulator.incrementAndAbortIfLimitReached(current, sleepTime);
-        decayingSleep(&sleepTime);
-    }
-}
-
 void wait_for_stat_to_be_gte(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
                              const char *stat, int final,
                              const char* stat_key,
@@ -1409,25 +1349,6 @@ void wait_for_expired_items_to_be(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
     }
 }
 
-void wait_for_str_stat_to_be(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
-                             const char *stat, const char* final,
-                             const char* stat_key,
-                             const time_t max_wait_time_in_secs) {
-    useconds_t sleepTime = 128;
-    WaitTimeAccumulator<const char*> accumulator("to be", stat, stat_key,
-                                                 final,
-                                                 max_wait_time_in_secs);
-    for (;;) {
-        auto current = get_str_stat(h, h1, stat, stat_key);
-        if (current == final) {
-            break;
-        }
-        accumulator.incrementAndAbortIfLimitReached(current.c_str(),
-                                                    sleepTime);
-        decayingSleep(&sleepTime);
-    }
-}
-
 void wait_for_memory_usage_below(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
                                  int mem_threshold,
                                  const time_t max_wait_time_in_secs) {
index 12c7d04..f01faeb 100644 (file)
@@ -107,6 +107,50 @@ enum class Histo_stat_info {
     NUM_BINS
 };
 
+/**
+ * Helper class used when waiting on statistics to reach a certain value -
+ * aggregates how long we have been waiting and aborts if the maximum wait time
+ * is exceeded.
+ */
+template <typename T>
+class WaitTimeAccumulator
+{
+public:
+    WaitTimeAccumulator(const char* compare_name,
+                        const char* stat_, const char* stat_key,
+                        const T final_, const time_t wait_time_in_secs)
+        : compareName(compare_name),
+          stat(stat_),
+          statKey(stat_key),
+          final(final_),
+          maxWaitTime(wait_time_in_secs * 1000 * 1000),
+          totalSleepTime(0) {}
+
+    void incrementAndAbortIfLimitReached(T last_value,
+                                         const useconds_t sleep_time)
+    {
+        totalSleepTime += sleep_time;
+        if (totalSleepTime >= maxWaitTime) {
+            std::cerr << "Exceeded maximum wait time of " << maxWaitTime
+                    << "us waiting for stat '" << stat;
+            if (statKey != NULL) {
+                std::cerr << "(" << statKey << ")";
+            }
+            std::cerr << "' " << compareName << " " << final << " (last value:"
+            << last_value << ") - aborting." << std::endl;
+            abort();
+        }
+    }
+
+private:
+    const char* compareName;
+    const char* stat;
+    const char* statKey;
+    const T final;
+    const useconds_t maxWaitTime;
+    useconds_t totalSleepTime;
+};
+
 void decayingSleep(useconds_t *sleepTime);
 
 
@@ -243,15 +287,40 @@ int get_int_stat_or_default(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
                             int default_value, const char *statname,
                             const char *statkey = NULL);
 
+/**
+ * Templated function prototype to return a stat of the given type.
+ * Should replace above uses of get_XXX_stat with this.
+ */
+template<typename T>
+T get_stat(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *statname,
+           const char *statkey);
+
+// Explicit template instantiations declarations of get_stat<T>
+template<>
+std::string get_stat(ENGINE_HANDLE* h, ENGINE_HANDLE_V1* h1,
+                     const char *statname, const char *statkey);
+template<>
+int get_stat(ENGINE_HANDLE* h, ENGINE_HANDLE_V1* h1,
+             const char *statname, const char *statkey);
+
+template<>
+uint64_t get_stat(ENGINE_HANDLE* h, ENGINE_HANDLE_V1* h1,
+                  const char *statname, const char *statkey);
+
 void verify_curr_items(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, int exp,
                        const char *msg);
-void wait_for_stat_change(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
-                          const char *stat, int initial,
-                          const char *statkey = NULL,
+template<typename T>
+void wait_for_stat_change(ENGINE_HANDLE* h, ENGINE_HANDLE_V1* h1,
+                          const char* stat, T initial,
+                          const char* stat_key = nullptr,
                           const time_t max_wait_time_in_secs = 60);
-void wait_for_stat_to_be(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1, const char *stat,
-                         int final, const char* stat_key = NULL,
+
+template<typename T>
+void wait_for_stat_to_be(ENGINE_HANDLE* h, ENGINE_HANDLE_V1* h1,
+                         const char* stat, T final,
+                         const char* stat_key = nullptr,
                          const time_t max_wait_time_in_secs = 60);
+
 void wait_for_stat_to_be_gte(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
                              const char *stat, int final,
                              const char* stat_key = NULL,
@@ -263,10 +332,6 @@ void wait_for_stat_to_be_lte(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
 void wait_for_expired_items_to_be(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
                                   int final,
                                   const time_t max_wait_time_in_secs = 60);
-void wait_for_str_stat_to_be(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
-                             const char *stat, const char* final,
-                             const char* stat_key,
-                             const time_t max_wait_time_in_secs = 60);
 bool wait_for_warmup_complete(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1);
 void wait_for_flusher_to_settle(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1);
 void wait_for_rollback_to_finish(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1);
@@ -353,4 +418,40 @@ int write_items_upto_mem_perc(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
                               int mem_thresh_perc, int start_seqno = 0,
                               const char *key_prefix = "key",
                               const char *value = "data");
+
+template<typename T>
+inline void wait_for_stat_change(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
+                                 const char *stat, T initial,
+                                 const char *stat_key,
+                                 const time_t max_wait_time_in_secs) {
+    useconds_t sleepTime = 128;
+    WaitTimeAccumulator<T> accumulator("to change from", stat, stat_key,
+                                         initial, max_wait_time_in_secs);
+    for (;;) {
+        auto current = get_stat<T>(h, h1, stat, stat_key);
+        if (current != initial) {
+            break;
+        }
+        accumulator.incrementAndAbortIfLimitReached(current, sleepTime);
+        decayingSleep(&sleepTime);
+    }
+}
+
+template<typename T>
+void wait_for_stat_to_be(ENGINE_HANDLE *h, ENGINE_HANDLE_V1 *h1,
+                         const char *stat, T final, const char* stat_key,
+                         const time_t max_wait_time_in_secs) {
+    useconds_t sleepTime = 128;
+    WaitTimeAccumulator<T> accumulator("to be", stat, stat_key, final,
+                                       max_wait_time_in_secs);
+    for (;;) {
+        auto current = get_stat<T>(h, h1, stat, stat_key);
+        if (current == final) {
+            break;
+        }
+        accumulator.incrementAndAbortIfLimitReached(current, sleepTime);
+        decayingSleep(&sleepTime);
+    }
+}
+
 #endif  // TESTS_EP_TEST_APIS_H_
index a11cfc2..9533efd 100644 (file)
@@ -1478,7 +1478,7 @@ test_multi_vb_compactions_with_workload(ENGINE_HANDLE *h,
             ++count;
         }
     }
-    wait_for_str_stat_to_be(h, h1, "ep_workload_pattern", "read_heavy", NULL);
+    wait_for_stat_to_be(h, h1, "ep_workload_pattern", std::string{"read_heavy"});
 
     // Compact multiple vbuckets.
     const int n_threads = 4;
index 21a595d..14e8468 100644 (file)
@@ -4000,8 +4000,8 @@ static enum test_result test_dcp_consumer_end_stream(ENGINE_HANDLE *h,
             h1->dcp.stream_end(h, cookie, stream_opaque, vbucket, end_flag),
             "Expected success");
 
-    wait_for_str_stat_to_be(h, h1, "eq_dcpq:unittest:stream_0_state", "dead",
-                            "dcp");
+    wait_for_stat_to_be(h, h1, "eq_dcpq:unittest:stream_0_state",
+                        std::string{"dead"}, "dcp");
 
     testHarness.destroy_cookie(cookie);
     return SUCCESS;