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