I have written full coverage for poker-network/pokerlock.py. I have just committed the changes to the coverage-poker-network branch. I plan to merge it in tomorrow (Sunday) night (US/Eastern) unless there are any objections.
The patch is attached. It's licensed under AGPLv3-or-later.
diff --git a/poker-network/ChangeLog b/poker-network/ChangeLog index b720675..3ed71e2 100644 --- a/poker-network/ChangeLog +++ b/poker-network/ChangeLog @@ -1,5 +1,35 @@ +2008-10-25 Bradley M. Kuhn <[EMAIL PROTECTED]> + + * tests/test-pokerlock.py.in + (PokerLockTestCase.test12_mainTests_makeSureDBCloses): Wrote test. + + * tests/run.in (DEFAULT_COVERAGE_FILES): Added pokerlock. + + * tests/test-pokerlock.py.in + (PokerLockTestCase.test10_mainTests_notRunningForCallback): + Wrote test. + (PokerLockTestCase.test11_mainTests_raiseForceRelease): Wrote + test. + +2008-10-20 Bradley M. Kuhn <[EMAIL PROTECTED]> + + * tests/test-pokerlock.py.in (PokerLockTestCase.test07_mainTests_stopped): + Wrote test. + (PokerLockTestCase.test08_mainTests_emptyQueue): Wrote test. + (PokerLockTestCase.test09_mainTests_wrongRaise): Wrote test. + (PokerLockTestCase.test06_aquireTimeout.lockTimeoutExpected_failed): + Fixed overzealous search_output. + 2008-10-19 Bradley M. Kuhn <[EMAIL PROTECTED]> + * tests/test-pokerlock.py.in (PokerLockTestCase.test01_simple): + Added message asserts. + (PokerLockTestCase.test02_wait): Added message asserts. + (PokerLockTestCase.test03_acquire_dead): Added message asserts. + (PokerLockTestCase.test04_release_twice.validate): Added message + asserts. + (PokerLockTestCase.test06_aquireTimeout): Wrote test. + * tests/run.in (DEFAULT_COVERAGE_FILES): Added ../pokernetwork/pokercashier.py diff --git a/poker-network/tests/run.in b/poker-network/tests/run.in index 45cb163..cda9ac5 100644 --- a/poker-network/tests/run.in +++ b/poker-network/tests/run.in @@ -74,6 +74,7 @@ COVERAGE_100_PERCENT=" ../pokernetwork/pokerclientpackets ../pokernetwork/pokerpackets ../pokernetwork/pokeravatar +../pokernetwork/pokerlock ../pokernetwork/pokerauth ../pokernetwork/protocol ../pokernetwork/server diff --git a/poker-network/tests/test-pokerlock.py.in b/poker-network/tests/test-pokerlock.py.in index 6f89b0c..6836f78 100644 --- a/poker-network/tests/test-pokerlock.py.in +++ b/poker-network/tests/test-pokerlock.py.in @@ -1,13 +1,14 @@ [EMAIL PROTECTED]@ # -*- mode: python -*- # -# Copyright (C) 2007, 2008 Loic Dachary <[EMAIL PROTECTED]> -# Copyright (C) 2006 Mekensleep +# Note: this file is copyrighted by multiple entities; some license their +# copyrights under GPLv3-or-later and some under AGPLv3-or-later. Read +# below for details. # -# Mekensleep -# 24 rue vieille du temple -# 75004 Paris -# [EMAIL PROTECTED] +# Copyright (C) 2007, 2008 Loic Dachary <[EMAIL PROTECTED]> +# Copyright (C) 2006 Mekensleep +# 24 rue vieille du temple, 75004 Paris +# <[EMAIL PROTECTED]> # # 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 @@ -23,14 +24,35 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. # +# Copyright (C) 2008 Bradley M. Kuhn <[EMAIL PROTECTED]> +# +# This program gives you software freedom; you can copy, convey, +# propogate, redistribute and/or modify this program under the terms of +# the GNU Affero General Public License (AGPL) as published by the Free +# Software Foundation, either version 3 of the License, or (at your +# option) any later version of the AGPL. +# +# 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 Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program in a file in the toplevel directory called +# "AGPLv3". If not, see <http://www.gnu.org/licenses/>. +# +# # Authors: # Loic Dachary <[EMAIL PROTECTED]> +# Bradley M. Kuhn <[EMAIL PROTECTED]> # import sys, os sys.path.insert(0, "@top_srcdir@") sys.path.insert(0, "..") +from tests.testmessages import silence_all_messages, get_messages, clear_all_messages, search_output + from twisted.python import failure from twisted.trial import unittest, runner, reporter import twisted.internet.base @@ -46,9 +68,10 @@ from pokernetwork import pokerlock class PokerLockTestCase(unittest.TestCase): # ---------------------------------------------------------------- - def setUp(self): + def setUp(self, verbose = 6): pokerlock.PokerLock.acquire_sleep = 1 - verbose = int(os.environ.get('VERBOSE_T', '-1')) +# verbose = int(os.environ.get('VERBOSE_T', '-1')) + silence_all_messages() if verbose < 0: pokerlock.PokerLock.message = lambda self, string: True self.parameters = {'host': '@MYSQL_TEST_DBHOST@', 'user': '@MYSQL_TEST_DBROOT@', 'password': '@MYSQL_TEST_DBROOT_PASSWORD@'} @@ -59,23 +82,26 @@ class PokerLockTestCase(unittest.TestCase): self.locker2 = pokerlock.PokerLock(self.parameters) if verbose >= 0: self.locker2.verbose = verbose; self.locker2.start() - # ---------------------------------------------------------------- def tearDown(self): self.locker2.close() self.locker.close() - + # ---------------------------------------------------------------- def test01_simple(self): d = self.locker.acquire('lock01') def validate(result): if isinstance(result, failure.Failure): raise result + for str in ['loop, queue size', '__acquire lock01', + '__acquire got MySQL lock', 'acquired' ]: + self.failUnless(search_output(str)) self.assertEqual("lock01", result) self.locker.release('lock01') return result d.addBoth(validate) + clear_all_messages() return d - + # ---------------------------------------------------------------- def test02_wait(self): def locker2_succeeded(result): self.locker.release('lock01') @@ -83,87 +109,339 @@ class PokerLockTestCase(unittest.TestCase): self.locker2.close() def locker2_failed(result): + msgs = get_messages() + for str in [ '__acquire lock01', 'acquired', 'exception in function', + 'release because exception', 'loop, queue size']: + self.failUnless(search_output(str)) + self.locker.release('lock01') self.assertTrue(isinstance(result, failure.Failure)) self.assertEqual(result.value[0], pokerlock.PokerLock.TIMED_OUT) + clear_all_messages() def locker2(): d = self.locker2.acquire('lock01', 5) + self.assertEquals(get_messages(), ['acquire']) + clear_all_messages() d.addCallback(locker2_succeeded) d.addErrback(locker2_failed) return d def validate(result): if isinstance(result, failure.Failure): raise result + + for str in ['loop, queue size', '__acquire lock01', 'acquired', '__acquire got MySQL lock']: + self.failUnless(search_output(str)) self.assertEqual("lock01", result) + clear_all_messages() return locker2() - + d = self.locker.acquire('lock01') + clear_all_messages() d.addBoth(validate) return d - + # ---------------------------------------------------------------- def test03_acquire_dead(self): self.locker.close() + clear_all_messages() try: self.locker.acquire('lock01') problem = True except Exception, e: problem = False self.assertEqual(e[0], pokerlock.PokerLock.DEAD) + self.assertEqual(get_messages(), ['acquire']) if problem: self.fail("acquire on dead PokerLock did not raise exception") - + # ---------------------------------------------------------------- def test04_release_twice(self): def validate(result): if isinstance(result, failure.Failure): raise result self.assertEqual("lock01", result) + for str in ['loop, queue size', '__acquire lock01', + 'acquired', '__acquire got MySQL lock']: + self.failUnless(search_output(str)) + + clear_all_messages() self.locker.release("lock01") + self.assertEquals(get_messages(), ['release lock01']) + clear_all_messages() try: self.locker.release("lock01") problem = True except Exception, e: problem = False self.assertEqual(e[0], pokerlock.PokerLock.RELEASE) + self.assertEquals(get_messages(), ['release lock01']) if problem: self.fail("double release did not raise exception") - + + clear_all_messages() d = self.locker.acquire('lock01') + self.assertEqual(get_messages(), ['acquire']) + clear_all_messages() d.addBoth(validate) return d - + # ---------------------------------------------------------------- def test05_many(self): + self.locker.message = lambda self, string: True + self.locker.verbose = 0 + # Runs too slow if you have messages on dl = [] def show(x): self.locker.release('lock01') + pokerlock.PokerLock.acquire_sleep = 0.01 + for i in xrange(1,500): d = self.locker.acquire('lock01', 3) d.addBoth(show) dl.append(d) + clear_all_messages() return defer.DeferredList(dl) + # ---------------------------------------------------------------- + def test06_aquireTimeout(self): + pokerlock.PokerLock.acquire_sleep = 0.01 + + def lockTimeoutExpected_succeeded(result): + self.locker.release('lock01') + self.fail("lock timeout succeeded with result = %s : should have failed with timeout" + % result) + + def lockTimeoutExpected_failed(result): + msgs = get_messages() + self.failUnless(search_output('__acquire TIMED OUT')) + + self.assertTrue(isinstance(result, failure.Failure)) + self.assertEqual(result.value[0], pokerlock.PokerLock.TIMED_OUT) + clear_all_messages() + + def lockFastTimeout(): + pokerlock.PokerLock.acquire_sleep = 60 + d = self.locker.acquire('lock01', 5) + self.assertEquals(get_messages(), ['acquire']) + clear_all_messages() + d.addCallback(lockTimeoutExpected_succeeded) + d.addErrback(lockTimeoutExpected_failed) + return d + + def validate(result): + if isinstance(result, failure.Failure): raise result + for str in ['loop, queue size', '__acquire lock01', + '__acquire got MySQL lock', 'acquired' ]: + self.failUnless(search_output(str)) + self.assertEqual("lock01", result) + clear_all_messages() + return lockFastTimeout() + pokerlock.PokerLock.acquire_sleep = 0.01 + d = self.locker.acquire('lock01', 1) + clear_all_messages() + d.addBoth(validate) + return d + # ---------------------------------------------------------------- + def test07_mainTests_stopped(self): + clear_all_messages() + self.locker.stopping() + self.assertEquals(get_messages(), [ "stopping" ]) + d = defer.Deferred() + def checker(val): + self.failIf(self.locker.running) + self.assertEquals(get_messages(), [ "stopped" ]) + clear_all_messages() + reactor.callLater(pokerlock.PokerLock.acquire_sleep*3, lambda: d.callback(True)) + return d + # ---------------------------------------------------------------- + def test08_mainTests_emptyQueue(self): + import Queue + class MockQueue(): + def qsize(qSelf): + return 1 + def get(qSelf, timeout = 1): + raise Queue.Empty("MOCK") + def empty(qSelf): + return False + def put(qSelf, val): + pass + self.locker.q = MockQueue() + d = defer.Deferred() + def checker(val): + search_output("timeout") + d.addCallback(checker) + reactor.callLater(pokerlock.PokerLock.acquire_sleep*2, lambda: d.callback(True)) + return d + # ---------------------------------------------------------------- + def test09_mainTests_wrongRaise(self): + import Queue + import time + from cStringIO import StringIO + class MockException(Exception): pass + class MockQueue(): + def qsize(qSelf): + return 1 + def get(qSelf, timeout = 1): + raise MockException("MOCK") + def empty(qSelf): + return False + def put(qSelf, val): + pass + oldStderr = sys.stderr + sys.stderr = StringIO() + anotherLock = pokerlock.PokerLock(self.parameters) + anotherLock.q = MockQueue() + anotherLock.start() + time.sleep(2) + value = sys.stderr.getvalue() + sys.stderr = oldStderr + self.failUnless(value.find('raise MockException("MOCK")\nMockException: MOCK') >= 0) + # ---------------------------------------------------------------- + def test10_mainTests_notRunningForCallback(self): + import Queue + import time + + global myLock + def setNotRunning(name, timeout): + global myLock + myLock.running = False + + d = defer.Deferred() + def succeeded(result): + self.failIf(True) + + def failed(result): + self.failIf(True) + d.addErrback(failed) + d.addCallback(succeeded) + + class MockQueue(): + def __init__(qSelf): + qSelf.count = 1 + def qsize(qSelf): + return qSelf.count + def get(qSelf, timeout = 1): + if qSelf.count > 0: + qSelf.count = 0 + return ("Mocky", setNotRunning, 10, d) + else: + raise Queue.Empty + def empty(qSelf): + return qSelf.count <= 0 + def put(qSelf, val): + pass + class MockLock(): + def __init__(lSelf): + lSelf.calledReleaseCount = 0 + def release(lSelf): + lSelf.calledReleaseCount += 1 + + silence_all_messages() + clear_all_messages() + anotherLock = pokerlock.PokerLock(self.parameters) + anotherLock.q = MockQueue() + anotherLock.lock = MockLock() + anotherLock.verbose = 6 + myLock = anotherLock + anotherLock.start() + time.sleep(2) + self.failUnless(search_output('release because not running')) + self.assertEquals(anotherLock.running, False) + self.assertEquals(anotherLock.lock.calledReleaseCount, 1) + # ---------------------------------------------------------------- + def test11_mainTests_raiseForceRelease(self): + import Queue + import time + class MockException(Exception): pass + + def raiseForceRelease(name, timeout): + raise MockException() + + def succeeded(result): + self.failIf(True) + + def failed(result): + self.failUnless(issinstance(result, MockException)) + # FIXME: this callback never happens; it should, however. I + # am not completely sure why; I assume it's because the + # reactor.callFromThread() errback call in the main() doesn't + # get executed before the reactor dies. OTOH, I don't fully + # understand the thread/reactor interaction issues . If + # someone can figure out and make sure this callback happens, + # I'd appreciate it. + d = defer.Deferred() + d.addErrback(failed) + d.addCallback(succeeded) + + class MockQueue(): + def __init__(qSelf): + qSelf.count = 1 + def qsize(qSelf): + return qSelf.count + def get(qSelf, timeout = 1): + if qSelf.count > 0: + qSelf.count = 0 + return ("Mocky", raiseForceRelease, 10, d) + else: + raise Queue.Empty + def empty(qSelf): + return qSelf.count <= 0 + def put(qSelf, val): + pass + class MockLock(): + def release(lSelf): + raise MockException("MOCKY NO LOCK RELEASE") + + silence_all_messages() + clear_all_messages() + anotherLock = pokerlock.PokerLock(self.parameters) + + anotherLock.q = MockQueue() + anotherLock.lock = MockLock() + anotherLock.verbose = 6 + anotherLock.start() + time.sleep(2) + + self.assertEquals(anotherLock.running, True) + self.failUnless(search_output('exception in function Traceback')) + self.failUnless(search_output('release because exception')) + self.failUnless(search_output('raise MockException("MOCKY NO LOCK RELEASE")')) + # ---------------------------------------------------------------- + def test12_mainTests_makeSureDBCloses(self): + class MockDB(): + def __init__(dbSelf): + dbSelf.closeCount = 0 + def close(dbSelf): + dbSelf.closeCount += 1 + db = MockDB() + oldIsAlive = self.locker.isAlive + def mockIsAlive(): return False + self.locker.isAlive = mockIsAlive + oldDb = self.locker.db + self.locker.db = db + self.locker.close() + self.assertEquals(self.locker.db, None) + self.locker.db = oldDb + self.assertEquals(db.closeCount, 1) + self.locker.isAlive = oldIsAlive # ---------------------------------------------------------------- def GetTestSuite(): suite = runner.TestSuite(PokerLockTestCase) suite.addTest(unittest.makeSuite(PokerLockTestCase)) return suite - # ---------------------------------------------------------------- def GetTestedModule(): return currencyclient - # ---------------------------------------------------------------- def Run(): loader = runner.TestLoader() -# loader.methodPrefix = "test05" +# loader.methodPrefix = "test12" suite = loader.loadClass(PokerLockTestCase) return runner.TrialRunner( - reporter.VerboseTextReporter, -# reporter.TextReporter, -# tracebackFormat='verbose', - tracebackFormat='default', - ).run(suite) - + reporter.VerboseTextReporter, + # reporter.TextReporter, + # tracebackFormat='verbose', + tracebackFormat='default', + ).run(suite) + # ---------------------------------------------------------------- if __name__ == '__main__': if Run().wasSuccessful():
-- -- bkuhn
_______________________________________________ Pokersource-users mailing list [email protected] https://mail.gna.org/listinfo/pokersource-users
