Nir Soffer has uploaded a new change for review.

Change subject: tests: Add RWLock tests
......................................................................

tests: Add RWLock tests

Current RWLock look too complex and has no tests. This patch fixes the
later issue.

Change-Id: If404f0e8c68fcdb2f7643bdd6d5c1f97f230a227
Signed-off-by: Nir Soffer <nsof...@redhat.com>
---
A tests/rwlock_test.py
1 file changed, 219 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/07/42907/1

diff --git a/tests/rwlock_test.py b/tests/rwlock_test.py
new file mode 100644
index 0000000..80d04f1
--- /dev/null
+++ b/tests/rwlock_test.py
@@ -0,0 +1,219 @@
+#
+# Copyright 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+from __future__ import absolute_import, print_function
+import threading
+import time
+
+from testlib import VdsmTestCase
+from testValidation import slowtest, stresstest
+
+from storage.misc import RWLock
+
+
+class RWLockTests(VdsmTestCase):
+
+    @slowtest
+    def test_concurrent_readers(self):
+        lock = RWLock()
+        readers = []
+        log = []
+        with self.assertElapsed(0.1, 0.1):
+            for i in range(5):
+                t = start_thread(reader, lock, log, hold=0.1)
+                readers.append(t)
+            for t in readers:
+                t.join()
+        self.assertEqual(log, ["reader acquired"] * 5)
+
+    @slowtest
+    def test_wakeup_blocked_writer(self):
+        lock = RWLock()
+        readers = []
+        log = []
+        try:
+            for i in range(5):
+                t = start_thread(reader, lock, log, hold=0.2)
+                readers.append(t)
+            time.sleep(0.1)
+            # All readers should hold the lock now
+            with self.assertElapsed(0.1, 0.02):
+                # Should block until last reader release the lock
+                lock.acquireWrite()
+                lock.release()
+        finally:
+            for t in readers:
+                t.join()
+
+    @slowtest
+    def test_wakeup_blocked_readers(self):
+        lock = RWLock()
+        readers = []
+        log = []
+        lock.acquireWrite()
+        try:
+            for i in range(10):
+                t = start_thread(reader, lock, log)
+                readers.append(t)
+            time.sleep(0.1)
+            # All readers should be blocked now
+        finally:
+            lock.release()
+            # Should wake up all readers, taking a read lock
+            for t in readers:
+                t.join()
+        self.assertEqual(log, ["reader acquired"] * 10)
+
+    @slowtest
+    def test_release_other_thread_write_lock(self):
+        lock = RWLock()
+        t = start_thread(writer, lock, [], hold=0.2)
+        try:
+            time.sleep(0.1)
+            self.assertRaises(RuntimeError, lock.release)
+        finally:
+            t.join()
+
+    @slowtest
+    def test_release_other_thread_read_lock(self):
+        lock = RWLock()
+        t = start_thread(reader, lock, [], hold=0.2)
+        try:
+            time.sleep(0.1)
+            self.assertRaises(RuntimeError, lock.release)
+        finally:
+            t.join()
+
+    @slowtest
+    def test_fifo(self):
+        lock = RWLock()
+        log = []
+        lock.acquireRead()
+        try:
+            # t1 is waiting on the first reader...
+            t1 = start_thread(writer, lock, log)
+            time.sleep(0.1)
+            # t2 joined after t1, so it should get the lock after it
+            t2 = start_thread(reader, lock, log)
+            time.sleep(0.1)
+        finally:
+            lock.release()
+        t1.join()
+        t2.join()
+        self.assertEqual(log, ["writer acquired", "reader acquired"])
+
+    @stresstest
+    def test_fairness(self):
+        lock = RWLock()
+        ready = threading.Event()
+        done = threading.Event()
+        reads = [0]
+        writes = [0]
+
+        def read():
+            ready.wait()
+            while not done.is_set():
+                lock.acquireRead()
+                try:
+                    reads[0] += 1
+                finally:
+                    lock.release()
+
+        def write():
+            ready.wait()
+            while not done.is_set():
+                lock.acquireWrite()
+                try:
+                    writes[0] += 1
+                finally:
+                    lock.release()
+
+        t1 = start_thread(read)
+        t2 = start_thread(write)
+        try:
+            time.sleep(0.1)
+            ready.set()
+            time.sleep(1)
+        finally:
+            done.set()
+            t1.join()
+            t2.join()
+
+        print('reads: ', reads[0], 'writes:', writes[0])
+        self.assertTrue(abs(reads[0] - writes[0]) < reads[0] / 10)
+
+
+class HelpersTests(VdsmTestCase):
+    """
+    Test helpers used in the RWLock tests.
+    """
+
+    def test_writer(self):
+        lock = RWLock()
+        log = []
+        start_thread(writer, lock, log).join()
+        self.assertEqual(log, ["writer acquired"])
+
+    @slowtest
+    def test_writer_hold(self):
+        lock = RWLock()
+        log = []
+        with self.assertElapsed(0.1, 0.05):
+            start_thread(writer, lock, log, hold=0.1).join()
+        self.assertEqual(log, ["writer acquired"])
+
+    def test_reader(self):
+        lock = RWLock()
+        log = []
+        start_thread(reader, lock, log, hold=0).join()
+        self.assertEqual(log, ["reader acquired"])
+
+    @slowtest
+    def test_reader_hold(self):
+        lock = RWLock()
+        log = []
+        with self.assertElapsed(0.1, 0.05):
+            start_thread(reader, lock, log, hold=0.1).join()
+        self.assertEqual(log, ["reader acquired"])
+
+
+def writer(lock, log, hold=0):
+    lock.acquireWrite()
+    try:
+        log.append("writer acquired")
+        time.sleep(hold)
+    finally:
+        lock.release()
+
+
+def reader(lock, log, hold=0):
+    lock.acquireRead()
+    try:
+        log.append("reader acquired")
+        time.sleep(hold)
+    finally:
+        lock.release()
+
+
+def start_thread(func, *args, **kwargs):
+    t = threading.Thread(target=func, args=args, kwargs=kwargs)
+    t.daemon = True
+    t.start()
+    return t


-- 
To view, visit https://gerrit.ovirt.org/42907
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If404f0e8c68fcdb2f7643bdd6d5c1f97f230a227
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsof...@redhat.com>
_______________________________________________
vdsm-patches mailing list
vdsm-patches@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches

Reply via email to