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

Reply via email to