Attached please find a patch for poker-network that currently reflects the differences between r5683 on coverage-poker-network branch and trunk at the same revision.
This patch implements test necessary to get full test coverage for the files currencyclient.py, pokerdatabase.py, pokermemcache.py. If there are no objections, I will merge this patch into trunk on Saturday 2009-04-25. Please respond by then if you have objections. The attached patch is copyrighted by me and licensed under AGPLv3-or-later.
diff --git a/poker-network/ChangeLog b/poker-network/ChangeLog index d9152bb..f0b1526 100644 --- a/poker-network/ChangeLog +++ b/poker-network/ChangeLog @@ -1,3 +1,33 @@ +2009-04-19 Bradley M. Kuhn <[email protected]> + + * tests/run.in (COVERAGE_100_PERCENT): Added pokermemchache.py. + + * tests/test-pokermemcache.py.in + (MemcacheTestCase.test03_checkKeyNoString): Wrote test. + +2009-04-18 Bradley M. Kuhn <[email protected]> + + * tests/run.in (COVERAGE_100_PERCENT): added currencyclient! + + * tests/test-currencyclient.py.in + (CurrencyClientTestCase.test07_1_breakNote_oddLeftOver): Wrote test. + (Run): Test classes were not loaded correctly. + (ErrorCondtionsCurrencyClientTestCase): Created additional test class. + (ErrorCondtionsCurrencyClientTestCase.test01_parseResultNote_InvalidResult): + Wrote test. + (ErrorCondtionsCurrencyClientTestCase.test02_commit_multiLineResult): + Wrote test. + (FakeCurrencyClientTestCase.test10_breakNote_FakeCurrencyFailure): + Wrote test. + (ErrorCondtionsCurrencyClientTestCase.test03_checkNote_checkNoteResultIsFalse): + Wrote test. + (ErrorCondtionsCurrencyClientTestCase.test04_commit_commitResultIsFalse): + Wrote test. + + * tests/test-pokerdatabase.py.in + (PokerDatabaseTestCase.test11_confirmLiteralMethodPassThrough): + Wrote test, yielding 100% coverage. + 2009-04-12 Loic Dachary <[email protected]> * Release 1.7.4 diff --git a/poker-network/LICENSE b/poker-network/LICENSE index b57e5e1..233aac4 100644 --- a/poker-network/LICENSE +++ b/poker-network/LICENSE @@ -27,10 +27,10 @@ copyrighted by the authors who have chosen AGPLv3-or-later. The =========================================================================== Authors licensing under AGPLv3-or-later: - Copyright (C) 2002, 2005, 2006, 2007, 2008 Loic Dachary <[email protected]> + Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009 Loic Dachary <[email protected]> # The 2002 copyrights are only in ./config directory for build system Copyright (C) 2008 Johan Euphrosine <[email protected]> - Copyright (C) 2008 Bradley M. Kuhn <[email protected]> + Copyright (C) 2008, 2009 Bradley M. Kuhn <[email protected]> Copyright (C) 2006 Jerome Jeannin <[email protected]> # Jerome's copyrights only in ./config directory for build system Copyright (C) 2004, 2005, 2006 Mekensleep <[email protected]> diff --git a/poker-network/tests/run.in b/poker-network/tests/run.in index 8ace540..bdd3be5 100644 --- a/poker-network/tests/run.in +++ b/poker-network/tests/run.in @@ -69,9 +69,12 @@ COVERAGE_100_PERCENT=" ../pokernetwork/pokergameclient ../pokernetwork/pokernetworkconfig ../pokernetwork/pokerclientpackets +../pokernetwork/currencyclient ../pokernetwork/pokerpackets ../pokernetwork/pokeravatar ../pokernetwork/pokertable +../pokernetwork/pokerdatabase +../pokernetwork/pokermemcache ../pokernetwork/pokerservice ../pokernetwork/pokerauth ../pokernetwork/protocol diff --git a/poker-network/tests/test-currencyclient.py.in b/poker-network/tests/test-currencyclient.py.in index 60a1f98..0831fcf 100644 --- a/poker-network/tests/test-currencyclient.py.in +++ b/poker-network/tests/test-currencyclient.py.in @@ -2,8 +2,9 @@ # -*- mode: python -*- # # Copyright (C) 2007, 2008 Loic Dachary <[email protected]> -# Copyright (C) 2006 Mekensleep <[email protected]> -# 24 rue vieille du temple, 75004 Paris +# Copyright (C) 2009 Bradley M. Kuhn <[email protected]> +# Copyright (C) 2006 Mekensleep <[email protected]> +# 24 rue vieille du temple, 75004 Paris # # This software's license gives you freedom; you can copy, convey, # propagate, redistribute and/or modify this program under the terms of @@ -22,12 +23,16 @@ # # 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 import testclock + from types import * from twisted.python import failure @@ -53,18 +58,18 @@ class CurrencyClientTestCase(unittest.TestCase): os.system("@MYSQL@ -u @MYSQL_TEST_DBROOT@ --password='@MYSQL_TEST_DBROOT_PASSWORD@' -h '@MYSQL_TEST_DBHOST@' -e 'DROP DATABASE IF EXISTS currencytest'") else: os.system("@MYSQL@ -u @MYSQL_TEST_DBROOT@ -h '@MYSQL_TEST_DBHOST@' -e 'DROP DATABASE IF EXISTS currencytest'") - + # ----------------------------------------------------------------------------- def setUp(self): self.destroyDb() self.client = currencyclient.CurrencyClient() self.client.getPage = self.getPage - - # ----------------------------------------------------------------------------- + + # ----------------------------------------------------------------------------- def tearDown(self): del self.client self.destroyDb() - + def getPage(self, url): ( scheme, netloc, path, parameters, query, fragement ) = urlparse(url) cmd = """ @@ -89,7 +94,7 @@ EOF reactor.callLater(0, lambda: d.callback(result)) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def getNote(self, url, value): d = self.client.getNote(url, value) if "?" in url: @@ -106,11 +111,10 @@ EOF d.addBoth(validate) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def getCommitedNote(self, url, value): return self.commit(self.getNote(url, value)) - - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def commit(self, d): def commit(result): if isinstance(result, failure.Failure): raise result @@ -121,7 +125,7 @@ EOF d.addBoth(commit) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test01_getNote(self): d = self.getNote('http://fake/', 100) def validate(result): @@ -131,11 +135,11 @@ EOF d.addCallback(validate) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test02_commit(self): return self.getCommitedNote('http://fake/', 100) - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test03_checkNote(self): d = self.getCommitedNote('http://fake/', 100) @@ -154,7 +158,7 @@ EOF d.addCallback(checkNote) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test04_changeNote(self): d = self.getCommitedNote('http://fake/', 100) @@ -176,10 +180,10 @@ EOF d.addCallback(changeNote) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test05_mergeNotes(self): notes = [] - def addnote(result): + def addnote(result): notes.append(result[0]) return result @@ -209,10 +213,10 @@ EOF d.addCallback(mergeNotes) return self.commit(d) - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test06_meltNotes(self): notes = [] - def addnote(result): + def addnote(result): notes.append(result[0]) return result @@ -242,7 +246,7 @@ EOF d.addCallback(meltNotes) return self.commit(d) - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test07_breakNote(self): d = self.getCommitedNote('http://fake/', 100) @@ -266,7 +270,43 @@ EOF d.addCallback(breakNote) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- + def test07_1_breakNote_oddLeftOver(self): + d = self.getCommitedNote('http://fake/', 100) + + def breakNote(result): + #print "breakNote " + str(result) + note_to_break = result[0] + d = self.client.breakNote(note_to_break, 15, 3, 2) + def validate(result): + if isinstance(result, failure.Failure): raise result + #print "broken notes " + str(result) + notes = result + self.assertEqual(10, len(notes)) + for ii in [ 0, 1, 2, 3, 4, 5 ]: + self.assertEqual(ii+1, notes[ii][1]) + self.assertEqual(15, notes[ii][3]) + self.assertEqual(40, len(notes[ii][2])) + for ii in [ 6, 7, 8 ]: + self.assertEqual(ii+1, notes[ii][1]) + self.assertEqual(3, notes[ii][3]) + self.assertEqual(40, len(notes[ii][2])) + + lastNote = 1 + lastVal = 1 + if isinstance(self.client, currencyclient.FakeCurrencyClient): + lastNote = 10 + lastVal = 2 + self.assertEqual(lastNote, notes[9][1]) + self.assertEqual(lastVal, notes[9][3]) + self.assertEqual(40, len(notes[9][2])) + return result + d.addBoth(validate) + return d + + d.addCallback(breakNote) + return d + # ----------------------------------------------------------------------------- def test08_breakNote_zero(self): d = self.getCommitedNote('http://fake/', 100) @@ -288,7 +328,7 @@ EOF d.addCallback(breakNote) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test09_getNote_with_id(self): d = self.getNote('http://fake/?id=1', 100) def validate(result): @@ -309,7 +349,8 @@ class FakeCurrencyClientTestCase(CurrencyClientTestCase): # tests completely from the previous test class. self.client.serial = 0 self.client.getPage = self.getPage - # ----------------------------------------------------------------------------- + currencyclient.FakeCurrencyFailure = False + # ----------------------------------------------------------------------------- def getNote(self, url, value): clear_all_messages() d = self.client.getNote(url, value) @@ -342,7 +383,7 @@ class FakeCurrencyClientTestCase(CurrencyClientTestCase): ret = CurrencyClientTestCase.getCommitedNote(self, url, value) ret.addCallback(checkCommitVerboseOutput) return ret - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- # Had to ovveride all of test03, for the same reason discussed above, that # there is another layer of list indirection missing in FakeCurrencyClient. def test03_checkNote(self): @@ -363,10 +404,10 @@ class FakeCurrencyClientTestCase(CurrencyClientTestCase): d.addCallback(checkNote) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test05_mergeNotes(self): notes = [] - def addnote(result): + def addnote(result): notes.append(result[0]) return result @@ -397,10 +438,10 @@ class FakeCurrencyClientTestCase(CurrencyClientTestCase): d.addCallback(mergeNotes) return self.commit(d) - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test06_meltNotes(self): notes = [] - def addnote(result): + def addnote(result): notes.append(result[0]) return result @@ -457,26 +498,198 @@ class FakeCurrencyClientTestCase(CurrencyClientTestCase): def checkOutput(result): self.assertEquals(search_output("breakNote vaues"), True) return True - + d.addCallback(checkOutput) return d - # ----------------------------------------------------------------------------- + # ----------------------------------------------------------------------------- def test09_getNote_with_id(self): return True + # ----------------------------------------------------------------------------- + def test10_breakNote_FakeCurrencyFailure(self): + currencyclient.FakeCurrencyFailure = True + + d = self.getCommitedNote('http://fake/', 100) + + mustBeCalledBackForSuccess = defer.Deferred() + + def breakNote(result): + def failIfCalledBack(result): + self.fail("should not have a normal callback in this situation") + + def expectedError(err): + self.assertEquals(err.check(twisted.web.error.Error), + twisted.web.error.Error) + self.assertEquals(err.getErrorMessage(), + "500 breakNote: fake error") + mustBeCalledBackForSuccess.callback(True) + + d = self.client.breakNote(result[0], 30, 10, 5) + d.addCallback(failIfCalledBack) + d.addErrback(expectedError) + return d + + d.addCallback(breakNote) + return defer.DeferredList((d, mustBeCalledBackForSuccess)) +# ----------------------------------------------------------------------------- +class ErrorCondtionsCurrencyClientTestCase(unittest.TestCase): + def destroyDb(self): + if len("@MYSQL_TEST_DBROOT_PASSWORD@") > 0: + os.system("@MYSQL@ -u @MYSQL_TEST_DBROOT@ --password='@MYSQL_TEST_DBROOT_PASSWORD@' -h '@MYSQL_TEST_DBHOST@' -e 'DROP DATABASE IF EXISTS currencytest'") + else: + os.system("@MYSQL@ -u @MYSQL_TEST_DBROOT@ -h '@MYSQL_TEST_DBHOST@' -e 'DROP DATABASE IF EXISTS currencytest'") + # ----------------------------------------------------------------------------- + def setUp(self): + self.destroyDb() + # ----------------------------------------------------------------------------- + def tearDown(self): + del self.client + self.destroyDb() + # ----------------------------------------------------------------------------- + def test01_parseResultNote_InvalidResult(self): + from cStringIO import StringIO + + self.client = currencyclient.RealCurrencyClient() + caughtIt = False + + oldStdio = sys.stdout + sys.stdout = StringIO() + try: + self.client.parseResultNote("two\tfield") + self.fail("Previous line should have caused exception") + except Exception, e: + self.assertEquals(e.__str__(), "expected notes got something else") + caughtIt = True + value = sys.stdout.getvalue() + sys.stdout = oldStdio + + self.assertEquals(value, "RealCurrencyClient::parseResultNote ignore line: two\tfield\n") + self.failUnless(caughtIt, "Should have caught an exception") + # ----------------------------------------------------------------------------- + def test02_commit_multiLineResult(self): + self.client = currencyclient.RealCurrencyClient() + + oldRequest = self.client.request + requestDeferred = defer.Deferred() + def myRequest(url = None, command = None, transaction_id = None): + self.assertEquals(command, 'commit') + self.assertEquals(url, "url_dummy") + self.assertEquals(transaction_id, "transaction_dummy") + return requestDeferred + self.client.request = myRequest + + self.assertEquals(self.client.commit("url_dummy", "transaction_dummy"), + requestDeferred) + + + confirmErrorFoundDeferred = defer.Deferred() + def catchException(err): + self.assertEquals(err.check(Exception), Exception) + self.assertEquals(err.getErrorMessage(), + "expected a single line got two\nlines instead") + confirmErrorFoundDeferred.callback(True) + requestDeferred.addErrback(catchException) + + requestDeferred.callback("two\nlines") + + self.client.request = oldRequest + return confirmErrorFoundDeferred + # ----------------------------------------------------------------------------- + def test03_checkNote_checkNoteResultIsFalse(self): + """test03_checkNote_checkNoteResultIsFalse + + The goal of this test is to cover the setting of result to + failure.Failure() in checkNote(). We have to get a bit tricky + with deferreds to cause this to happen. Our chainBegin deferred + is set up to raise an exception immediately in its callback, which + will chain off to its own errBack. Its errBack then calls + checkNote. Since there is already an error propogating through, + the failure.Failure() will work properly to then, in turn, trigger + the errBack of checkNotesDeferred. Finally, we make sure the + point is reached by having the usual rougue deferred that only + gets called back by the verification process.""" + + class PropogatedException(Exception): pass + self.client = currencyclient.FakeCurrencyClient() + self.client.check_note_result = False + + forceTimeoutErrorIfNotCalledBack = defer.Deferred() + def verifyError(err): + self.assertEquals(err.check(PropogatedException), PropogatedException) + self.assertEquals(err.getErrorMessage(), + "this exception ends up in checknotes errback") + forceTimeoutErrorIfNotCalledBack.callback(True) + self.client.check_note_result = True + + def executeCheckNote(value): + self.assertEquals(value.check(PropogatedException), PropogatedException) + self.assertEquals(value.getErrorMessage(), + "this exception ends up in checknotes errback") + + checkNotesDeferred = self.client.checkNote(None) + checkNotesDeferred.addErrback(verifyError) + return checkNotesDeferred + + def propogateError(value): + raise PropogatedException("this exception ends up in checknotes errback") + + chainBegin = defer.Deferred() + chainBegin.addCallback(propogateError) + chainBegin.addErrback(executeCheckNote) + chainBegin.callback(True) + + return forceTimeoutErrorIfNotCalledBack + # ----------------------------------------------------------------------------- + def test04_commit_commitResultIsFalse(self): + """test04_commit_commitResultIsFalse + This test is nearly identical to + test03_checkNote_checkNoteResultIsFalse, since the methods work + very similarily.""" + + class PropogatedException(Exception): pass + + self.client = currencyclient.FakeCurrencyClient() + self.client.commit_result = False + + forceTimeoutErrorIfNotCalledBack = defer.Deferred() + def verifyError(err): + self.assertEquals(err.check(PropogatedException), PropogatedException) + self.assertEquals(err.getErrorMessage(), + "this exception ends up in commit errback") + forceTimeoutErrorIfNotCalledBack.callback(True) + self.client.commit_result = True + + def executeCommit(value): + self.assertEquals(value.check(PropogatedException), PropogatedException) + self.assertEquals(value.getErrorMessage(), + "this exception ends up in commit errback") + + commitDeferred = self.client.commit(None, None) + commitDeferred.addErrback(verifyError) + return commitDeferred + + def propogateError(value): + raise PropogatedException("this exception ends up in commit errback") + + chainBegin = defer.Deferred() + chainBegin.addCallback(propogateError) + chainBegin.addErrback(executeCommit) + chainBegin.callback(True) + return forceTimeoutErrorIfNotCalledBack # ----------------------------------------------------------------------------- def Run(): loader = runner.TestLoader() # loader.methodPrefix = "test07" suite = loader.suiteFactory() - suite = loader.loadClass(CurrencyClientTestCase) - suite = loader.loadClass(FakeCurrencyClientTestCase) + suite.addTest(loader.loadClass(CurrencyClientTestCase)) + suite.addTest(loader.loadClass(FakeCurrencyClientTestCase)) + suite.addTest(loader.loadClass(ErrorCondtionsCurrencyClientTestCase)) return runner.TrialRunner(reporter.TextReporter, # tracebackFormat='verbose', tracebackFormat='default', ).run(suite) - + # ----------------------------------------------------------------------------- if __name__ == '__main__': if Run().wasSuccessful(): diff --git a/poker-network/tests/test-pokerdatabase.py.in b/poker-network/tests/test-pokerdatabase.py.in index 77ecf99..25159d4 100644 --- a/poker-network/tests/test-pokerdatabase.py.in +++ b/poker-network/tests/test-pokerdatabase.py.in @@ -2,7 +2,7 @@ # -*- mode: python -*- # # Copyright (C) 2007, 2008 Loic Dachary <[email protected]> -# Copyright (C) 2008 Bradley M. Kuhn <[email protected]> +# Copyright (C) 2008, 2009 Bradley M. Kuhn <[email protected]> # Copyright (C) 2006 Mekensleep <[email protected]> # 24 rue vieille du temple, 75004 Paris # @@ -295,6 +295,21 @@ class PokerDatabaseTestCase(unittest.TestCase): except pokerdatabase.ExceptionUpgradeFailed, euf: self.assertEquals(euf.args[0], "upgrade failed") self.assertEquals(self.db.getVersion(), "0.0.5") + # ---------------------------------------------------------------------------- + def test11_confirmLiteralMethodPassThrough(self): + """test11_confirmLiteralMethodPassThrough + The method "literal" in the database class should simply pass + through to the internal representation method of the same name.""" + class MockDatabaseWithOnlyLiteral(): + def literal(mdSelf, args): return "LITERAL TEST " + args + + self.db = pokerdatabase.PokerDatabase(self.settings) + saveRealDb = self.db.db + self.db.db = MockDatabaseWithOnlyLiteral() + + self.assertEquals(self.db.literal("ahoy hoy!"), "LITERAL TEST ahoy hoy!") + self.db.db = saveRealDb + # -------------------------------------------------------------------------------- def GetTestSuite(): suite = runner.TestSuite(PokerDatabaseTestCase) diff --git a/poker-network/tests/test-pokermemcache.py.in b/poker-network/tests/test-pokermemcache.py.in index 8b7229c..5d36881 100644 --- a/poker-network/tests/test-pokermemcache.py.in +++ b/poker-network/tests/test-pokermemcache.py.in @@ -2,6 +2,7 @@ # -*- mode: python -*- # # Copyright (C) 2008 Loic Dachary <[email protected]> +# Copyright (C) 2009 Bradley M. Kuhn <[email protected]> # # This software's license gives you freedom; you can copy, convey, # propagate, redistribute and/or modify this program under the terms of @@ -56,7 +57,19 @@ class MemcacheTestCase(unittest.TestCase): self.assertEqual(1, memcache.expiration['A']) memcache.add('C', 'x', time = 3) self.assertEqual(3, memcache.expiration['C']) - + def test03_checkKeyNoString(self): + from pokernetwork.pokermemcache import MemcachedStringEncodingError + from pokernetwork.pokermemcache import check_key + caughtIt = False + try: + check_key(u'\ufeff') + self.fail("Previous line should have caused exception") + except MemcachedStringEncodingError, mse: + self.assertEquals(mse.__str__(), + "Keys must be str()'s, notunicode. Convert your unicode strings using mystring.encode(charset)!") + caughtIt = True + self.failUnless(caughtIt, "MemcachedStringEncodingError was not caught") + #-------------------------------------------------------------- def GetTestSuite(): suite = unittest.TestSuite()
-- -- bkuhn
_______________________________________________ Pokersource-users mailing list [email protected] https://mail.gna.org/listinfo/pokersource-users
