I have 100% coverage written for user.py, pokerauth.py, and
pokerauthmysql.py.  I have attached a patch, which is r4663 in the
coverage-poker-network branch currently.  I plan to merge this into
trunk sometime tomorrow unless someone objects.

This patch is licensed AGPLv3-or-later.

diff --git a/.gitignore b/.gitignore
index eb0b311..c332832 100644
--- a/.gitignore
+++ b/.gitignore
@@ -147,6 +147,7 @@ poker-network/tests/test-javascript.py
 poker-network/tests/test-packets.py
 poker-network/tests/test-poker2d.py
 poker-network/tests/test-pokerauth.py
+poker-network/tests/test-user.py
 poker-network/tests/test-pokeravatar.py
 poker-network/tests/test-pokerbotlogic.py
 poker-network/tests/test-pokercashier.py
diff --git a/poker-network/ChangeLog b/poker-network/ChangeLog
index 1ccb6e3..a499a24 100644
--- a/poker-network/ChangeLog
+++ b/poker-network/ChangeLog
@@ -1,3 +1,46 @@
+2008-09-30  Bradley M. Kuhn  <[EMAIL PROTECTED]>
+
+	* tests/test-user.py.in: Created file.
+	(PokerUserTestCase.test01_init): Wrote test.
+	(PokerUserTestCase.test02_logout): Wrote test.
+	(PokerUserTestCase.test03_hasPrivilege): Wrote test.
+	(PokerUserTestCase.test04_checkName): Wrote test.
+	(PokerUserTestCase.test05_checkPassword): Wrote test.
+	(PokerUserTestCase.test06_checkNameAndPassword): Wrote test.
+
+	* tests/Makefile.am (TESTS): Added tests/test-user.py.
+
+	* configure.ac (AC_CONFIG_FILES): Added tests/test-user.py.
+
+	* tests/test-pokerauth.py.in: Added pokerauthmysql.py to
+	LocalVariables coverage list.  Rewrote fallback pokerauth test to
+	a better common denominator for deriving.
+	(PokerAuthMysqlTestCase.checkIfUserExistsInDB): Derived method.
+	(PokerAuthMysqlTestCase.test04_authWithoutAutoCreate): Derived
+	method.
+	(PokerAuthMysqlTestCase.test07_mysql11userCreate): Overrode method
+	for pass.
+	(PokerAuthMysqlTestCase.test08_mysqlbeyond11userCreate): Overrode
+	method for pass.
+	(PokerAuthMysqlTestCase.test05_authWhenDoubleEntry): Overrode
+	method.
+	(PokerAuthMysqlTestCase.test06_validAuthWhenEntryExists): Overrode
+	method.
+
+	* tests/run.in (DEFAULT_COVERAGE_FILES): Added
+	pokernetwork/pokerauth to list.
+
+	* tests/test-pokerauth.py.in
+	(PokerAuthTestCase.test03_authWithAutoCreate): Added db check.
+	(PokerAuthTestCase.test04_authWithoutAutoCreate): Added db check.
+	(PokerAuthTestCase.checkIfUserExistsInDB): Wrote method.
+	(PokerAuthTestCase.test05_authWhenDoubleEntry): Wrote test.
+	(PokerAuthTestCase.test06_validAuthWhenEntryExists): Wrote test.
+	(PokerAuthTestCase.test07_mysql11userCreate): Wrote test.
+	(PokerAuthTestCase.test08_mysqlbeyond11userCreate.MockCursor):
+	Wrote test.
+	(PokerAuthTestCase.test09_setAndGetLevel): Wrote test.
+
 2008-09-28  Bradley M. Kuhn  <[EMAIL PROTECTED]>
 
 	* pokernetwork/tourneyattrs.py
diff --git a/poker-network/configure.ac b/poker-network/configure.ac
index 967084a..49d851d 100644
--- a/poker-network/configure.ac
+++ b/poker-network/configure.ac
@@ -316,6 +316,7 @@ AC_CONFIG_FILES([
         tests/test-pokeravatar.py
         tests/test-attrpack.py
         tests/test-userstats.py
+        tests/test-user.py
         tests/test-tourneyattrs.py
         tests/test-pokercashier.py
         tests/test-pokerclient.py
diff --git a/poker-network/tests/Makefile.am b/poker-network/tests/Makefile.am
index 6ba4c59..2e822a6 100644
--- a/poker-network/tests/Makefile.am
+++ b/poker-network/tests/Makefile.am
@@ -88,6 +88,7 @@ TESTS = coverage-reset \
 	test-pokerdatabase.py \
 	test-pokerservice.py \
 	test-pokerauth.py \
+	test-user.py \
 	test-pokertable.py \
 	test-pokerchildren.py \
 	test-pokerclient.py \
diff --git a/poker-network/tests/run.in b/poker-network/tests/run.in
index 3ceb2f7..7f7bd31 100644
--- a/poker-network/tests/run.in
+++ b/poker-network/tests/run.in
@@ -74,6 +74,9 @@ COVERAGE_100_PERCENT="
 ../pokernetwork/pokerclientpackets
 ../pokernetwork/pokerpackets
 ../pokernetwork/pokeravatar
+../pokernetwork/pokerauth
+../pokernetwork/pokerauthmysql
+../pokernetwork/user
 ../pokernetwork/userstats
 ../pokernetwork/attrpack
 ../pokernetwork/tourneyattrs
diff --git a/poker-network/tests/test-pokerauth.py.in b/poker-network/tests/test-pokerauth.py.in
index c04693d..73de693 100644
--- a/poker-network/tests/test-pokerauth.py.in
+++ b/poker-network/tests/test-pokerauth.py.in
@@ -1,12 +1,13 @@
 # -*- mode: python -*-
-# Copyright (C) 2008 Bradley M. Kuhn <[EMAIL PROTECTED]>
+#
+# 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.
+#
 # Copyright (C) 2008 Johan Euphrosine <[EMAIL PROTECTED]>
 # Copyright (C) 2006 Mekensleep
-#
-# Mekensleep
-# 24 rue vieille du temple
-# 75004 Paris
-#       [EMAIL PROTECTED]
+#                    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
@@ -22,10 +23,28 @@
 # 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:
 #  Pierre-Andre (05/2006)
 #  Loic Dachary <[EMAIL PROTECTED]>
 #  Johan Euphrosine <[EMAIL PROTECTED]>
+#  Bradley M. Kuhn <[EMAIL PROTECTED]>
 #
 
 import sys, os
@@ -38,6 +57,8 @@ import types
 from tests.testmessages import silence_all_messages, clear_all_messages, get_messages
 silence_all_messages()
 
+from twisted.python.runtime import seconds
+
 from pokernetwork import pokerauth
 from pokernetwork.user import User
 from pokernetwork import pokernetworkconfig
@@ -45,7 +66,7 @@ from pokernetwork.pokerdatabase import PokerDatabase
 import libxml2
 
 settings_xml = """<?xml version="1.0" encoding="ISO-8859-1"?>
-<server verbose="6" ping="300000" autodeal="yes" simultaneous="4" chat="yes" >
+<server auto_create_account="no" verbose="6" ping="300000" autodeal="yes" simultaneous="4" chat="yes" >
   <database name="pokernetworktest" host="@MYSQL_TEST_DBHOST@" user="pokernetworktest" password="pokernetwork"
             root_user="@MYSQL_TEST_DBROOT@" root_password="@MYSQL_TEST_DBROOT_PASSWORD@" schema="@srcdir@/../database/schema.sql" command="@MYSQL@" />
   <delays autodeal="18" round="12" position="60" showdown="30" finish="18" />
@@ -96,10 +117,10 @@ class PokerAuthTestCase(unittest.TestCase):
     # -----------------------------------------------------------------------------------------------------    
     def tearDown(self):
         pokerauth._get_auth_instance = None
-        
     # -----------------------------------------------------------------------------------------------------    
     def test01_Init(self):
-        """Test Poker auth : get_auth_instance"""
+        """test01_Init
+        Test Poker auth : get_auth_instance"""
         db = None
         settings = pokernetworkconfig.Config([])
         settings.doc = libxml2.parseMemory(settings_xml, len(settings_xml))
@@ -108,7 +129,8 @@ class PokerAuthTestCase(unittest.TestCase):
         
     # -----------------------------------------------------------------------------------------------------    
     def test02_AlternatePokerAuth(self):
-        """Test Poker auth : get_auth_instance alternate PokerAuth"""
+        """test02_AlternatePokerAuth
+        Test Poker auth : get_auth_instance alternate PokerAuth"""
         db = None
         settings = pokernetworkconfig.Config([])
         settings.doc = libxml2.parseMemory(settings_alternate_xml, len(settings_alternate_xml))
@@ -116,34 +138,135 @@ class PokerAuthTestCase(unittest.TestCase):
         auth = pokerauth.get_auth_instance(db, settings)
         self.failUnless(hasattr(auth, 'gotcha'))
     # -----------------------------------------------------------------------------------------------------    
+    def checkIfUserExistsInDB(self, name, selectString = "SELECT serial from users where name = '%s'"):
+        cursor = self.db.cursor()
+        cursor.execute(selectString % name)
+        if cursor.rowcount == 1:
+            (serial,) = cursor.fetchone()
+            cursor.close()
+            return [serial]
+        elif cursor.rowcount == 0:
+            cursor.close()
+            return []
+        else:
+            serials = []
+            for row in cursor.fetchall(): serials.append(row['serial'])
+            cursor.close()
+            return serials
+    # -----------------------------------------------------------------------------------------------------    
     def test03_authWithAutoCreate(self):
-        """Test Poker auth : Try basic auth with autocreate on"""
+        """test03_authWithAutoCreate
+        Test Poker auth : Try basic auth with autocreate on"""
         db = self.db
         settings = pokernetworkconfig.Config([])
-        settings.doc = libxml2.parseMemory(settings_xml, len(settings_xml))
+        autocreate_xml = settings_xml.replace('<server auto_create_account="no" ', '<server ')
+        settings.doc = libxml2.parseMemory(autocreate_xml, len(autocreate_xml))
         settings.header = settings.doc.xpathNewContext()
         auth = pokerauth.get_auth_instance(db, settings)
 
         clear_all_messages()
-        auth.auth('joe_schmoe', 'foo')
+        self.assertEquals(auth.auth('joe_schmoe', 'foo'), ((4, 'joe_schmoe', 1), None))
         self.assertEquals(get_messages(), ['user joe_schmoe does not exist, create it',
                                        'creating user joe_schmoe', 'create user with serial 4'])
-        # FIXME: check DB!
+        self.failUnless(len(self.checkIfUserExistsInDB('joe_schmoe')) == 1)
     # -----------------------------------------------------------------------------------------------------    
-    def test04_authWithoutAutoCreate(self):
-        """Test Poker auth : Try basic auth with autocreate off"""
-        db = self.db
-        settings = pokernetworkconfig.Config([])
-        noautocreate_xml = settings_xml.replace('<server ', '<server auto_create_account="no" ')
-        settings.doc = libxml2.parseMemory(noautocreate_xml, len(noautocreate_xml))
-        settings.header = settings.doc.xpathNewContext()
-        auth = pokerauth.get_auth_instance(db, settings)
+    def test04_authWithoutAutoCreate(self, expectedMessages = ['user john_smith does not exist']):
+        """test04_authWithoutAutoCreate
+        Test Poker auth : Try basic auth with autocreate on"""
+        auth = pokerauth.get_auth_instance(self.db, self.settings)
+
+        clear_all_messages()
+
+        self.assertEquals(auth.auth('john_smith', 'blah'), (False, 'Invalid login or password'))
+        self.assertEquals(get_messages(), expectedMessages)
+        self.failUnless(len(self.checkIfUserExistsInDB('john_smith')) == 0)
+    # -----------------------------------------------------------------------------------------------------    
+    def test05_authWhenDoubleEntry(self):
+        """test05_authWhenDoubleEntry
+        Tests case in fallback authentication where more than one entry exists.
+        """
+        cursor = self.db.cursor()
+        cursor.execute("DROP TABLE users")
+        cursor.execute("""CREATE TABLE users (
+ 	    serial int unsigned not null auto_increment,
+	    name varchar(32), password varchar(32), privilege int default 1,
+            primary key (serial))""")
+        for ii in [ 1 , 2 ]:
+            cursor.execute("INSERT INTO users (name, password) values ('%s', '%s')" %
+                           ('doyle_brunson', 'foo'))
+        cursor.close()
+
+        auth = pokerauth.get_auth_instance(self.db, self.settings)
+
+        clear_all_messages()
+        self.assertEquals(auth.auth('doyle_brunson', 'foo'), (False, "Invalid login or password"))
+        self.assertEquals(get_messages(), ['*ERROR* more than one row for doyle_brunson'])
+    # -----------------------------------------------------------------------------------------------------    
+    def test06_validAuthWhenEntryExists(self):
+        """test06_validAuthWhenEntryExists
+        Tests case for single-row returned existing auth, both success and failure.
+        """
+        cursor = self.db.cursor()
+        cursor.execute("INSERT INTO users (created, name, password) values (%d, '%s', '%s')" %
+                       (seconds(), 'dan_harrington', 'bar'))
+        cursor.close()
+
+        auth = pokerauth.get_auth_instance(self.db, self.settings)
+
+        clear_all_messages()
+        self.assertEquals(auth.auth('dan_harrington', 'bar'), ((4L, 'dan_harrington', 1L), None))
+        self.assertEquals(get_messages(), [])
+
+        clear_all_messages()
+        self.assertEquals(auth.auth('dan_harrington', 'wrongpass'), (False, 'Invalid login or password'))
+        self.assertEquals(get_messages(), ['password mismatch for dan_harrington'])
+    # -----------------------------------------------------------------------------------------------------    
+    def test07_mysql11userCreate(self):
+        """test07_mysql11userCreate
+        Tests userCreate() as it will behave under MySQL 1.1 by mocking up
+        the situation.
+        """
+        class MockCursor:
+            def execute(self, str): pass
+            def insert_id(self):    return 4815
+            def close(self):        pass
+        class MockDatabase:
+            def cursor(self):    return MockCursor()
+
+        clear_all_messages()
+        auth = pokerauth.get_auth_instance(MockDatabase(), self.settings)
+        self.assertEquals(auth.userCreate("nobody", "nothing"), 4815)
+        self.assertEquals(get_messages(), ['creating user nobody', 'create user with serial 4815'])
+    # -----------------------------------------------------------------------------------------------------    
+    def test08_mysqlbeyond11userCreate(self):
+        """test08_mysqlbeyond11userCreate
+        Tests userCreate() as it will behave under MySQL > 1.1 by mocking up
+        the situation.
+        """
+        class MockCursor:
+            def __init__(self):
+                self.lastrowid = 162342
+            def execute(self, str): pass
+            def insert_id(self):    self.failIf(1)
+            def close(self):        pass
+        class MockDatabase:
+            def cursor(self):    return MockCursor()
 
         clear_all_messages()
+        auth = pokerauth.get_auth_instance(MockDatabase(), self.settings)
+        self.assertEquals(auth.userCreate("somebody", "something"), 162342)
+        self.assertEquals(get_messages(), ['creating user somebody', 'create user with serial 162342'])
+    # -----------------------------------------------------------------------------------------------------    
+    def test09_setAndGetLevel(self):
+        """test09_setAndGetLevel
+        Tests the SetLevel and GetLevel methods.
+        """
+        auth = pokerauth.get_auth_instance(self.db, self.settings)
 
-        auth.auth('john_smith', 'blah')
-        self.assertEquals(get_messages(), ['user john_smith does not exist'])
-        # FIXME: check DB!
+        self.assertEquals(auth.GetLevel('first'), False)
+        self.assertEquals(auth.SetLevel('first', 7), None)
+        self.assertEquals(auth.GetLevel('first'), 7)
+        self.assertEquals(auth.GetLevel('second'), False)
 # -----------------------------------------------------------------------------------------------------    
 settings_mysql_xml = """<?xml version="1.0" encoding="ISO-8859-1"?>
 <server verbose="6" ping="300000" autodeal="yes" simultaneous="4" chat="yes" >
@@ -162,11 +285,9 @@ settings_mysql_xml = """<?xml version="1.0" encoding="ISO-8859-1"?>
   <auth script="@srcdir@/../pokernetwork/pokerauthmysql.py" host="@MYSQL_TEST_DBHOST@" user="@MYSQL_TEST_DBROOT@" password="@MYSQL_TEST_DBROOT_PASSWORD@" db="testpokerauthmysql" table="users"/>
 </server>
 """
-
 import MySQLdb
 
-class PokerAuthMysqlTestCase(unittest.TestCase):
-        
+class PokerAuthMysqlTestCase(PokerAuthTestCase):
     # -----------------------------------------------------------------------------------------------------
     def setUp(self):
         self.settings = pokernetworkconfig.Config([])
@@ -174,40 +295,98 @@ class PokerAuthMysqlTestCase(unittest.TestCase):
         self.settings.header = self.settings.doc.xpathNewContext()
 
         self.parameters = self.settings.headerGetProperties("/server/auth")[0]
-        self.auth_db = MySQLdb.connect(host = self.parameters["host"],
+        self.db = MySQLdb.connect(host = self.parameters["host"],
                                   port = int(self.parameters.get("port", '3306')),
                                   user = self.parameters["user"],
                                   passwd = self.parameters["password"])
-        self.auth_db.query("CREATE DATABASE %s" % self.parameters["db"])
-        self.auth_db.query("USE %s" % self.parameters["db"])
-        self.auth_db.query("CREATE TABLE %s (username varchar(20), password varchar(20), privilege int)" % self.parameters["table"])
-        self.auth_db.query("INSERT INTO users (username, password, privilege) VALUES ('testuser', 'testpassword', %i)" % User.REGULAR)
-        
-
+        self.db.query("CREATE DATABASE %s" % self.parameters["db"])
+        self.db.query("USE %s" % self.parameters["db"])
+        self.db.query("CREATE TABLE %s (username varchar(20), password varchar(20), privilege int)" % self.parameters["table"])
+        self.db.query("INSERT INTO users (username, password, privilege) VALUES ('testuser', 'testpassword', %i)" % User.REGULAR)
     # -----------------------------------------------------------------------------------------------------    
     def tearDown(self):
-        self.auth_db.query("DROP DATABASE %s" % self.parameters["db"])
+        self.db.query("DROP DATABASE %s" % self.parameters["db"])
         pokerauth._get_auth_instance = None
-        
     # -----------------------------------------------------------------------------------------------------    
-    def test01(self):
-        """Test Poker mysql auth : get_auth_instance"""
+    def checkIfUserExistsInDB(self, name, selectString = ""):
+        return PokerAuthTestCase.checkIfUserExistsInDB(self, name,
+                             selectString = "SELECT username from " + self.parameters["table"] 
+                                                +  " where username = '%s'")
+    # -----------------------------------------------------------------------------------------------------    
+    def test01_Init(self):
+        """test01_Init
+        Test initalizing pokerauthmysql"""
         db = None
         auth = pokerauth.get_auth_instance(db, self.settings)
         result, message = auth.auth("testuser", "testpassword")
         self.assertNotEquals(False, result)
-                
+    # -----------------------------------------------------------------------------------------------------    
+    def test03_authWithAutoCreate(self):
+        """test03_authWithAutoCreateis not needed for MySQLAUTH"""
+        pass
+    # -----------------------------------------------------------------------------------------------------    
+    def test04_authWithoutAutoCreate(self):
+        """test04_authWithoutAutoCreate
+        Test Poker auth : Try basic auth with autocreate on"""
+        PokerAuthTestCase.test04_authWithoutAutoCreate(self, expectedMessages = [])
+    # -----------------------------------------------------------------------------------------------------    
+    def test05_authWhenDoubleEntry(self):
+        """test05_authWhenDoubleEntry
+        Tests case in fallback authentication where more than one entry exists.
+        """
+        cursor = self.db.cursor()
+        for ii in [ 1 , 2 ]:
+            cursor.execute("INSERT INTO %s (username, password, privilege) values ('%s', '%s', %i)" %
+                           (self.parameters["table"], 'doyle_brunson', 'foo', User.REGULAR))
+        cursor.close()
+
+        auth = pokerauth.get_auth_instance(self.db, self.settings)
+
+        clear_all_messages()
+        self.assertEquals(auth.auth('doyle_brunson', 'foo'), (False, "Invalid login or password"))
+        self.assertEquals(get_messages(), [])
+    # -----------------------------------------------------------------------------------------------------    
+    def test06_validAuthWhenEntryExists(self):
+        """test06_validAuthWhenEntryExists
+        Tests case for single-row returned existing auth, both success and failure.
+        """
+        cursor = self.db.cursor()
+        cursor.execute("INSERT INTO %s (username, password, privilege) values ('%s', '%s', %i)" %
+                           (self.parameters["table"], 'dan_harrington', 'bar', User.REGULAR))
+        cursor.close()
+
+        auth = pokerauth.get_auth_instance(self.db, self.settings)
+
+        clear_all_messages()
+        self.assertEquals(auth.auth('dan_harrington', 'bar'), (('dan_harrington', 'dan_harrington', 1L), None))
+        self.assertEquals(get_messages(), [])
+
+        clear_all_messages()
+        self.assertEquals(auth.auth('dan_harrington', 'wrongpass'), (False, 'Invalid login or password'))
+        self.assertEquals(get_messages(), [])
+    # -----------------------------------------------------------------------------------------------------    
+    def test07_mysql11userCreate(self):
+        """test08_mysqlbeyond11userCreate is not needed for MySQLAUTH"""
+        pass
+    # -----------------------------------------------------------------------------------------------------    
+    def test08_mysqlbeyond11userCreate(self):
+        """test08_mysqlbeyond11userCreate is not needed for MySQLAUTH"""
+        pass
 # -----------------------------------------------------------------------------------------------------
 def GetTestSuite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(PokerAuthTestCase))
     suite.addTest(unittest.makeSuite(PokerAuthMysqlTestCase))
+    # Comment out above and use line below this when you wish to run just
+    # one test by itself (changing prefix as needed).
+#    suite.addTest(unittest.makeSuite(PokerAuthTestCase, prefix = "test09"))
     return suite
     
 # -----------------------------------------------------------------------------------------------------
-# -----------------------------------------------------------------------------------------------------
 def Run(verbose):
-    return unittest.TextTestRunner(verbosity=verbose).run(GetTestSuite())
+    suite = GetTestSuite()
+    verbosity = int(os.environ.get('VERBOSE_T', 2))
+    return unittest.TextTestRunner(verbosity=verbose).run(suite)
     
 # -----------------------------------------------------------------------------------------------------
 if __name__ == '__main__':
@@ -218,5 +397,5 @@ if __name__ == '__main__':
 
 # Interpreted by emacs
 # Local Variables:
-# compile-command: "( cd .. ; ./config.status tests/test-pokerauth.py ) ; ( cd ../tests ; make COVERAGE_FILES='../pokernetwork/pokerauth.py' TESTS='coverage-reset test-pokerauth.py coverage-report' check )"
+# compile-command: "( cd .. ; ./config.status tests/test-pokerauth.py ) ; ( cd ../tests ; make COVERAGE_FILES='../pokernetwork/pokerauth.py ../pokernetwork/pokerauthmysql.py' TESTS='coverage-reset test-pokerauth.py coverage-report' check )"
 # End:
diff --git a/poker-network/tests/test-user.py.in b/poker-network/tests/test-user.py.in
new file mode 100644
index 0000000..9e125fa
--- /dev/null
+++ b/poker-network/tests/test-user.py.in
@@ -0,0 +1,244 @@
+# -*- mode: python -*-
+#
+# 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:
+#  Bradley M. Kuhn <[EMAIL PROTECTED]>
+#
+
+import sys, os
+sys.path.insert(0, "@top_srcdir@")
+
+import unittest
+import os.path
+import types
+
+from tests.testmessages import silence_all_messages, clear_all_messages, get_messages
+silence_all_messages()
+
+from pokernetwork.user import User
+from pokernetwork import user as userClass
+from pokernetwork.pokerpackets import PacketPokerSetAccount as mylimits
+
+class PokerUserTestCase(unittest.TestCase):
+        
+    # -----------------------------------------------------------------------------------------------------
+    def setUp(self):
+        pass
+    # -----------------------------------------------------------------------------------------------------    
+    def tearDown(self):
+        pass
+    # -----------------------------------------------------------------------------------------------------    
+    def test01_init(self):
+        """test01_init
+        test initialization of object"""
+
+        user = User(4815162342)
+        self.assertEquals(user.isLogged(), True)
+        self.assertEquals(user.serial, 4815162342)
+        self.assertEquals(user.name, 'anonymous')
+        self.assertEquals(user.url, 'random')
+        self.assertEquals(user.outfit, 'random')
+        self.assertEquals(user.privilege, None)
+    # -----------------------------------------------------------------------------------------------------    
+    def test02_logout(self):
+        """test02_logout
+        test logout, isLogged, and __str__ methods"""
+
+        user = User(4815162342)
+        self.assertEquals(user.isLogged(), True)
+        user.name = "Joe"
+        user.url = "http://example.org/";
+        user.outfit = "naked"
+        user.privilege = User.ADMIN
+        self.assertEquals(user.isLogged(), True)
+
+        # Test __str__
+        self.assertEquals("%s" % user, 'serial = 4815162342, name = Joe, url = http://example.org/, outfit = naked, privilege = %d' % User.ADMIN)
+
+        user.logout()
+        self.assertEquals(user.isLogged(), False)
+        self.assertEquals(user.serial, 0)
+        self.assertEquals(user.name, 'anonymous')
+        self.assertEquals(user.url, 'random')
+        self.assertEquals(user.outfit, 'random')
+        self.assertEquals(user.privilege, None)
+    # -----------------------------------------------------------------------------------------------------    
+    def test03_hasPrivilege(self):
+        """test03_hasPrivilege
+        test hasPrivilege method"""
+        user = User(4815162342)
+        self.assertEquals(user.hasPrivilege(None), True)
+        self.assertEquals(user.hasPrivilege(User.ADMIN), False)
+        self.assertEquals(user.hasPrivilege(User.REGULAR), False)
+        user.privilege = User.REGULAR
+        self.assertEquals(user.hasPrivilege(None), True)
+        self.assertEquals(user.hasPrivilege(User.ADMIN), False)
+        self.assertEquals(user.hasPrivilege(User.REGULAR), True)
+        user.privilege = User.ADMIN
+        self.assertEquals(user.hasPrivilege(None), True)
+        self.assertEquals(user.hasPrivilege(User.ADMIN), True)
+        self.assertEquals(user.hasPrivilege(User.REGULAR), True)
+        user.logout()
+        self.assertEquals(user.hasPrivilege(None), True)
+        self.assertEquals(user.hasPrivilege(User.ADMIN), False)
+        self.assertEquals(user.hasPrivilege(User.REGULAR), False)
+    # -----------------------------------------------------------------------------------------------------    
+    def test04_checkName(self):
+        """test04_checkName
+        test checkName static function"""
+
+        # Empty string.
+        self.assertEquals(userClass.checkName(""),
+                          (False, mylimits.NAME_TOO_SHORT, 'login name must be at least 5 characters long'))
+
+
+        # First, loops to test length only.  All generated strings should be valid
+
+        #                                 [A-Z]          [a-z]     
+        atoZ = [ chr(xx) for xx in range(65, 91) + range(97,123) ]
+        underbar =  [ '_' ]
+        #                             [0-9]
+        nums = [ chr(xx) for xx in range(48, 58) ]
+        weirdChars =  [ chr(xx) for xx in range(33, 48) + range(91, 94) ]
+
+        # SPEED NOTE: replaced atoZ with [ 'a', 'z', 'h', 'H', 'A', 'Z' ] for speed
+        for first in [ 'a', 'z', 'h', 'H', 'A', 'Z' ]:
+            for cc in  [ 'a', 'z', 'A', 'Z' ] + nums + underbar:
+                name = first
+                while len(name) < userClass.NAME_LENGTH_MIN:
+                    self.assertEquals(userClass.checkName(name),
+                                      (False, mylimits.NAME_TOO_SHORT, 'login name must be at least 5 characters long'))
+                    name += cc
+                while len(name) <= userClass.NAME_LENGTH_MAX:
+                    self.assertEquals(userClass.checkName(name), (True, None, None))
+                    if len(name) < userClass.NAME_LENGTH_MAX:
+                        for dd in underbar + nums:
+                            self.assertEquals(userClass.checkName(dd + name),
+                                              (False, mylimits.NAME_MUST_START_WITH_LETTER,
+                                               'login name must start with a letter'))
+                            self.assertEquals(userClass.checkName(name + dd), (True, None, None))
+                        for dd in weirdChars:
+                            self.assertEquals(userClass.checkName(dd + name),
+                                              (False, mylimits.NAME_MUST_START_WITH_LETTER,
+                                               'login name must start with a letter'))
+                            self.assertEquals(userClass.checkName(name + dd),
+                                              (False, mylimits.NAME_NOT_ALNUM,
+                                               'login name must be all letters, digits or underscore '))
+                    name += cc
+                for kk in range(20):
+                    self.assertEquals(userClass.checkName(name), 
+                                      (False, mylimits.NAME_TOO_LONG, 'login name must be at most 50 characters long'))
+    # -----------------------------------------------------------------------------------------------------    
+    def test05_checkPassword(self):
+        """test05_checkPassword
+        test checkPassword static function"""
+
+        # Empty string.
+        self.assertEquals(userClass.checkPassword(""),
+                          (False, mylimits.PASSWORD_TOO_SHORT, 'password must be at least %d characters long' % userClass.PASSWORD_LENGTH_MIN))
+
+
+        # First, loops to test length only.  All generated strings should be valid
+
+        #                                 [A-Z]          [a-z]     
+        atoZ = [ chr(xx) for xx in range(65, 91) + range(97,123) ]
+        underbar =  [ '_' ]
+        #                             [0-9]
+        nums = [ chr(xx) for xx in range(48, 58) ]
+        weirdChars =  [ chr(xx) for xx in range(33, 48) + range(91, 94) ]
+
+        # SPEED NOTE: replaced atoZ with [ 'a', 'z', 'h', 'H', 'A', 'Z' ] for speed
+        for cc in  [ 'a', 'z', 'H', 'h' 'A', 'Z' ] + nums:
+            pw = cc
+            while len(pw) < userClass.PASSWORD_LENGTH_MIN:
+                self.assertEquals(userClass.checkPassword(pw),
+                                  (False, mylimits.PASSWORD_TOO_SHORT, 'password must be at least %d characters long' % userClass.PASSWORD_LENGTH_MIN))
+                pw += cc
+            while len(pw) <= userClass.PASSWORD_LENGTH_MAX:
+                self.assertEquals(userClass.checkPassword(pw), (True, None, None))
+                if len(pw) < userClass.PASSWORD_LENGTH_MAX:
+                    for dd in weirdChars:
+                        self.assertEquals(userClass.checkPassword(pw + dd),
+                                          (False, mylimits.PASSWORD_NOT_ALNUM,
+                                           'password must be all letters and digits'))
+                pw += cc
+            for kk in range(20):
+                self.assertEquals(userClass.checkPassword(pw), 
+                                  (False, mylimits.PASSWORD_TOO_LONG, 'password must be at most %d characters long' % userClass.PASSWORD_LENGTH_MAX))
+    # -----------------------------------------------------------------------------------------------------    
+    def test06_checkNameAndPassword(self):
+        """test06_checkNameAndPassword
+        make sure check and password name"""
+        global thisCount
+        thisCount = 0
+        def firstOneNone(name):
+            return (None, "one", "one")
+        def firstOneFalse(name):
+            return (False, "two", "two")
+        def firstOneTrue(name):
+            return (True, "three", "three")
+        def countCall(password):
+            global thisCount
+            thisCount += 1
+            return (True, "FOUND", "FOUND")
+
+        saveCheckName = userClass.checkName
+        saveCheckPassword = userClass.checkPassword
+
+        userClass.checkPassword = countCall
+
+        userClass.checkName = firstOneNone
+        self.assertEquals(userClass.checkNameAndPassword("dummy", "dummy"), (None, "one", "one"))
+        self.assertEquals(thisCount, 0)
+
+        userClass.checkName = firstOneFalse
+        self.assertEquals(userClass.checkNameAndPassword("dummy", "dummy"), (False, "two", "two"))
+        self.assertEquals(thisCount, 0)
+
+        userClass.checkName = firstOneTrue
+        self.assertEquals(userClass.checkNameAndPassword("dummy", "dummy"), (True, "FOUND", "FOUND"))
+        self.assertEquals(thisCount, 1)
+
+        userClass.checkName = saveCheckName 
+        userClass.checkPassword = saveCheckPassword 
+# -----------------------------------------------------------------------------------------------------
+def GetTestSuite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(PokerUserTestCase))
+    # Comment out above and use line below this when you wish to run just
+    # one test by itself (changing prefix as needed).
+#    suite.addTest(unittest.makeSuite(PokerUserTestCase, prefix = "test05"))
+    return suite
+# -----------------------------------------------------------------------------------------------------
+def Run(verbose):
+    suite = GetTestSuite()
+    verbosity = int(os.environ.get('VERBOSE_T', 2))
+    return unittest.TextTestRunner(verbosity=verbose).run(suite)
+    
+# -----------------------------------------------------------------------------------------------------
+if __name__ == '__main__':
+    if Run(int(os.environ.get('VERBOSE_T', 2))).wasSuccessful():
+        sys.exit(0)
+    else:
+        sys.exit(1)
+
+# Interpreted by emacs
+# Local Variables:
+# compile-command: "( cd .. ; ./config.status tests/test-user.py ) ; ( cd ../tests ; make COVERAGE_FILES='../pokernetwork/user.py' TESTS='coverage-reset test-user.py coverage-report' check )"
+# End:
-- 

   -- bkuhn
_______________________________________________
Pokersource-users mailing list
[email protected]
https://mail.gna.org/listinfo/pokersource-users

Reply via email to