BIND 10 trac2202, updated. ff7d2f5f77fab130de8db0d59ce48a483a0a8b45 [2202] Tests for mutex

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Sep 3 13:10:22 UTC 2012


The branch, trac2202 has been updated
       via  ff7d2f5f77fab130de8db0d59ce48a483a0a8b45 (commit)
      from  99767bbe7b2a278ffa88086c24dcd6363d2ed0e5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit ff7d2f5f77fab130de8db0d59ce48a483a0a8b45
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Mon Sep 3 15:10:06 2012 +0200

    [2202] Tests for mutex

-----------------------------------------------------------------------

Summary of changes:
 src/lib/util/threads/tests/Makefile.am      |    1 +
 src/lib/util/threads/tests/lock_unittest.cc |  122 +++++++++++++++++++++++++++
 2 files changed, 123 insertions(+)
 create mode 100644 src/lib/util/threads/tests/lock_unittest.cc

-----------------------------------------------------------------------
diff --git a/src/lib/util/threads/tests/Makefile.am b/src/lib/util/threads/tests/Makefile.am
index 435e8e8..e86aedc 100644
--- a/src/lib/util/threads/tests/Makefile.am
+++ b/src/lib/util/threads/tests/Makefile.am
@@ -22,6 +22,7 @@ if HAVE_GTEST
 TESTS += run_unittests
 run_unittests_SOURCES  = run_unittests.cc
 run_unittests_SOURCES += thread_unittest.cc
+run_unittests_SOURCES += lock_unittest.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
diff --git a/src/lib/util/threads/tests/lock_unittest.cc b/src/lib/util/threads/tests/lock_unittest.cc
new file mode 100644
index 0000000..2d90ee7
--- /dev/null
+++ b/src/lib/util/threads/tests/lock_unittest.cc
@@ -0,0 +1,122 @@
+// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "../lock.h"
+#include "../thread.h"
+
+#include <gtest/gtest.h>
+
+#include <boost/bind.hpp>
+
+using namespace std;
+using namespace isc::util::thread;
+
+namespace {
+
+// Test a recursive mutex can be locked multiple times
+TEST(MutexTest, recursiveLockMultiple) {
+    Mutex mutex(true);
+    Mutex::Locker l1(mutex);
+    Mutex::Locker l2(mutex);
+    Mutex::Locker l3(mutex);
+    Mutex::Locker l4(mutex);
+    Mutex::Locker l5(mutex);
+}
+
+// If we try to lock the debug mutex multiple times, it should throw.
+TEST(MutexTest, lockMultiple) {
+    // TODO: Once we support non-debug mutexes, disable the test if we compile
+    // with them.
+    Mutex mutex;
+    Mutex::Locker l1(mutex);
+    EXPECT_THROW({
+        Mutex::Locker l2(mutex); // Attempt to lock again.
+    }, isc::InvalidOperation);
+}
+
+// Destroying a locked mutex is a bad idea as well
+TEST(MutexTest, destroyLocked) {
+    // TODO: This probably won't work for non-debug mutexes. Disable on non-debug
+    // compilation.
+    auto_ptr<Mutex> mutex(new Mutex);
+    Mutex::Locker locker(*mutex);
+    // Note: This maybe leaks somewhere. But this is a test for development aid
+    // exception. The exception won't happen in normal build anyway and seeing
+    // it means there's a bug.
+    EXPECT_THROW(mutex.reset(), isc::InvalidOperation);
+}
+
+// This test tries if a mutex really locks. We could try that with a deadlock,
+// but that's not practical (the test would not end).
+//
+// So instead, we try to do some operations from multiple threads that are
+// likely to break if not locked. Also, they must run for some time so all
+// threads are started and the operation must be complicated enough so the
+// compiler won't turn it into some kind of single atomic instruction.
+//
+// So, we'll have an array of numbers. Each thread will try to repeatedly
+// find a number large at least as half of the average, take the number,
+// distribute the value across the rest of the positions of the array and
+// zero the found position. This operation keeps the sum of the array
+// the same. But if two threads access it at the same time, it is likely
+// one will add something to the position another one have chosen and
+// the other one will then zero it, not taking the new value into account.
+// That'd lower the total value of the array.
+const unsigned long long length = 100000;
+const unsigned long long iterations = 1000000;
+const unsigned long long value = 200000;
+void
+performStrangeOperation(long long unsigned* array, int direction,
+                        Mutex* mutex)
+{
+    unsigned long long position = 0;
+    for (size_t i = 0; i < iterations; i ++) {
+        Mutex::Locker lock(*mutex);
+        while (array[position % length] < value) {
+            position += direction;
+        }
+        unsigned long long value = array[position % length];
+        unsigned long long p2 = position;
+        while (value > 0) {
+            p2 += direction;
+            if (p2 == position) {
+                continue;
+            }
+            array[p2 % length] ++;
+            value --;
+        }
+        array[position % length] = 0;
+    }
+}
+
+TEST(MutexTest, swarm) {
+    // This type has a low chance of being atomic itself, further raising
+    // the chance of problems appearing.
+    long long unsigned array[length];
+    for (size_t i = 0; i < length; ++ i) {
+        array[i] = value;
+    }
+    Mutex mutex;
+    Thread t1(boost::bind(&performStrangeOperation, array, 1, &mutex));
+    Thread t2(boost::bind(&performStrangeOperation, array, -1, &mutex));
+    t1.wait();
+    t2.wait();
+    long long unsigned sum = 0;
+    for (size_t i = 0; i < length; ++ i) {
+        sum += array[i];
+    }
+    EXPECT_EQ(length * value, sum) << "Threads are badly synchronized";
+}
+
+}



More information about the bind10-changes mailing list