[ovs-dev] [RFC 06/10] ovs-thread-stats: Added simple testcase

Daniele Di Proietto ddiproietto at vmware.com
Wed Oct 8 21:09:52 UTC 2014


Signed-off-by: Daniele Di Proietto <ddiproietto at vmware.com>
---
 tests/automake.mk    |   2 +
 tests/test-stats.c   | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/testsuite.at   |   1 +
 tests/threadstats.at |   4 ++
 4 files changed, 169 insertions(+)
 create mode 100644 tests/test-stats.c
 create mode 100644 tests/threadstats.at

diff --git a/tests/automake.mk b/tests/automake.mk
index 1f13230..37c232f 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -30,6 +30,7 @@ TESTSUITE_AT = \
 	tests/aes128.at \
 	tests/unixctl-py.at \
 	tests/uuid.at \
+	tests/threadstats.at \
 	tests/json.at \
 	tests/jsonrpc.at \
 	tests/jsonrpc-py.at \
@@ -237,6 +238,7 @@ tests_ovstest_SOURCES = \
 	tests/test-rstp.c \
 	tests/test-sflow.c \
 	tests/test-sha1.c \
+	tests/test-stats.c \
 	tests/test-stp.c \
 	tests/test-util.c \
 	tests/test-uuid.c \
diff --git a/tests/test-stats.c b/tests/test-stats.c
new file mode 100644
index 0000000..f009bcf
--- /dev/null
+++ b/tests/test-stats.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2014 Nicira, Inc.
+ *
+ * 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.
+ */
+
+#include <config.h>
+
+#include "fatal-signal.h"
+#include "ovstest.h"
+#include "ovs-thread.h"
+#include "ovs-thread-stats.h"
+
+enum {N_WRITES = 100000};
+enum {N_READS = 100};
+struct info_thread
+{
+    int n_create; /* How many stats buckets should I create? */
+    int n_waste; /* How many stats buckets should I create and destroy? */
+    int n_total; /* How many stats buckets are there(minimum)? */
+    struct ovs_barrier barrier;
+};
+
+static void
+aggr_cb(void *aux, struct ovsthread_stats_bucket *b)
+{
+    uint64_t *i = (uint64_t *)aux;
+    *i += b->data[0];
+}
+
+static void *
+stats_writer(void *aux_)
+{
+    struct info_thread *aux = aux_;
+    int *buckets;
+    int i,j;
+
+    buckets = xmalloc(aux->n_create * sizeof(*buckets));
+
+    for (i = 0; i < aux->n_create; i++) {
+        buckets[i] = ovsthread_stats_create_bucket();
+    }
+
+    ovs_barrier_block(&aux->barrier);
+
+    for (j = 0; j < N_WRITES; j++) {
+        for (i = 0; i < aux->n_create; i++) {
+            struct ovsthread_stats_bucket *b;
+            uint32_t seq;
+
+            b = ovsthread_stats_get_bucket(buckets[i], &seq);
+            b->data[0]++;
+            ovsthread_stats_bucket_done(b, seq);
+        }
+    }
+
+    for (i = 0; i < aux->n_create; i++) {
+        uint64_t v = 0;
+        ovsthread_stats_aggregate(buckets[i], &v, aggr_cb);
+        ovs_assert(v == N_WRITES);
+    }
+
+    ovs_barrier_block(&aux->barrier);
+
+    for (i = 0; i < aux->n_create; i++) {
+        ovsthread_stats_destroy_bucket(buckets[i]);
+    }
+
+    ovsthread_stats_create_bucket();
+    return NULL;
+}
+
+static void *
+stats_reader(void *aux_)
+{
+    struct info_thread *aux = aux_;
+    int i,j;
+
+    for (i = 0; i < aux->n_waste; i++) {
+        int b = ovsthread_stats_create_bucket();
+        ovsthread_stats_destroy_bucket(b);
+    }
+
+    ovs_barrier_block(&aux->barrier);
+
+    /* XXX this works because buckets id are small numbers. */
+    for (j = 0; j < N_READS; j++) {
+        for (i = 0; i < aux->n_total; i++) {
+            uint64_t v = 0;
+            ovsthread_stats_aggregate(i, &v, aggr_cb);
+            ovs_assert(v <= N_WRITES);
+        }
+    }
+
+    ovs_barrier_block(&aux->barrier);
+
+    for (j = 0; j < N_READS; j++) {
+        for (i = 0; i < aux->n_total; i++) {
+            uint64_t v = 0;
+            ovsthread_stats_aggregate(i, &v, aggr_cb);
+            ovs_assert(v == N_WRITES || v == 0);
+        }
+    }
+
+    return NULL;
+}
+
+static void
+test_stats(int n_readers, int n_writers)
+{
+    int i;
+    pthread_t *readers, *writers;
+    struct info_thread t;
+
+    t.n_create = 20;
+    t.n_total = 20 * n_writers;
+    t.n_waste = 5;
+
+    ovs_barrier_init(&t.barrier, n_readers + n_writers + 1);
+
+    readers = xmalloc(n_readers * sizeof *readers);
+    writers = xmalloc(n_writers * sizeof *writers);
+
+    for (i = 0; i < n_writers; i++) {
+        writers[i] = ovs_thread_create("writer", stats_writer, &t);
+    }
+    for (i = 0; i < n_readers; i++) {
+        readers[i] = ovs_thread_create("reader", stats_reader, &t);
+    }
+
+    ovs_barrier_block(&t.barrier);
+
+    ovs_barrier_block(&t.barrier);
+
+    for (i = 0; i < n_writers; i++) {
+        xpthread_join(writers[i], NULL);
+    }
+    for (i = 0; i < n_readers; i++) {
+        xpthread_join(readers[i], NULL);
+    }
+
+    ovs_barrier_destroy(&t.barrier);
+}
+
+static void
+test_stats_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+{
+    fatal_signal_init();
+    test_stats(5, 5);
+}
+
+OVSTEST_REGISTER("test-stats", test_stats_main);
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 8712277..2fddcc9 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -139,6 +139,7 @@ m4_include([tests/file_name.at])
 m4_include([tests/aes128.at])
 m4_include([tests/unixctl-py.at])
 m4_include([tests/uuid.at])
+m4_include([tests/threadstats.at])
 m4_include([tests/json.at])
 m4_include([tests/jsonrpc.at])
 m4_include([tests/jsonrpc-py.at])
diff --git a/tests/threadstats.at b/tests/threadstats.at
new file mode 100644
index 0000000..24f7982
--- /dev/null
+++ b/tests/threadstats.at
@@ -0,0 +1,4 @@
+AT_BANNER([Per thread statistics])
+AT_SETUP([multiple readers/writers])
+AT_CHECK([ovstest test-stats], [0], [], [])
+AT_CLEANUP
-- 
2.1.0.rc1




More information about the dev mailing list