"""
This module tests UserManagers in different permutations.
UserManagers can save their data to files, or to a MiddleKit database.
For MiddleKit, the database can be MySQL, PostgreSQL and MSSQL.
To run these tests:
cd Webware
python AllTests.py UserKit.Tests.UserManagerTest.makeTestSuite
"""
import os, sys
import logging
import unittest
import shutil
import UserKit
import AllTests
_log = logging.getLogger(__name__)
TEST_CODE_DIR = os.path.dirname(__file__) # e.g. ".../Webware/UserKit/Tests"
class UserManagerTest(unittest.TestCase):
def setUp(self):
from UserKit.UserManager import UserManager
self._mgr = UserManager()
def checkSettings(self):
mgr = self._mgr
value = 5.1
mgr.setModifiedUserTimeout(value)
assert mgr.modifiedUserTimeout() == value
mgr.setCachedUserTimeout(value)
assert mgr.cachedUserTimeout() == value
mgr.setActiveUserTimeout(value)
assert mgr.activeUserTimeout() == value
def checkUserClass(self):
mgr = self._mgr
from UserKit.User import User
class SubUser(User): pass
mgr.setUserClass(SubUser)
assert mgr.userClass() == SubUser, \
"We should be able to set a custom user class."
class Poser: pass
self.assertRaises(Exception, mgr.setUserClass, Poser), \
"Setting a customer user class that doesn't extend UserKit.User should fail."
def tearDown(self):
self._mgr.shutDown()
self._mgr = None
class _UserManagerToSomewhereTest(UserManagerTest):
"""
This abstract class provides some tests that all user managers should pass.
Subclasses are responsible for overriding setUp() and tearDown() for which
they should invoke super.
"""
def setUp(self):
pass # nothing for no
def tearDown(self):
self._mgr = None
def testBasics(self):
mgr = self._mgr
user = self._user = mgr.createUser('foo', 'bar')
assert user.manager() == mgr
assert user.name() == 'foo'
assert user.password() == 'bar'
assert not user.isActive()
assert mgr.userForSerialNum(user.serialNum()) == user
assert mgr.userForExternalId(user.externalId()) == user
assert mgr.userForName(user.name()) == user
externalId = user.externalId() # for use later in testing
users = mgr.users()
assert len(users) == 1
assert users[0] == user, 'users[0]=%r, user=%r' % (users[0], user)
assert len(mgr.activeUsers()) == 0
assert len(mgr.inactiveUsers()) == 1
# login
user2 = mgr.login(user, 'bar')
assert user == user2
assert user.isActive()
assert len(mgr.activeUsers()) == 1
assert len(mgr.inactiveUsers()) == 0
# logout
user.logout()
assert not user.isActive()
assert mgr.numActiveUsers() == 0
# login via user
result = user.login('bar')
assert result == user
assert user.isActive()
assert mgr.numActiveUsers() == 1
# logout via user
user.logout()
assert not user.isActive()
assert mgr.numActiveUsers() == 0
# login a 2nd time, but with bad password
user.login('bar')
user.login('rab')
assert not user.isActive()
assert mgr.numActiveUsers() == 0
# Check that we can access the user when he is not cached
mgr.clearCache()
user = mgr.userForSerialNum(1)
assert user
assert user.password() == 'bar'
if 0: # @@ 2001-04-15 ce: doesn't work yet
mgr.clearCache()
user = self._mgr.userForExternalId(externalId)
assert user
assert user.password() == 'bar'
mgr.clearCache()
user = self._mgr.userForName('foo')
assert user
assert user.password() == 'bar'
def testUserAccess(self):
mgr = self._mgr
user = mgr.createUser('foo', 'bar')
assert mgr.userForSerialNum(user.serialNum()) == user
assert mgr.userForExternalId(user.externalId()) == user
assert mgr.userForName(user.name()) == user
self.assertRaises(KeyError, mgr.userForSerialNum, 1000)
self.assertRaises(KeyError, mgr.userForExternalId, 'asdf')
self.assertRaises(KeyError, mgr.userForName, 'asdf')
assert mgr.userForSerialNum(1000, 1) == 1
assert mgr.userForExternalId('asdf', 1) == 1
assert mgr.userForName('asdf', 1) == 1
def testDuplicateUser(self):
mgr = self._mgr
user = self._user = mgr.createUser('foo', 'bar')
self.assertRaises(AssertionError, mgr.createUser, 'foo', 'bar')
userClass = mgr.userClass()
self.assertRaises(AssertionError, userClass, mgr, 'foo', 'bar')
class UserManagerToFileTest(_UserManagerToSomewhereTest):
def setUp(self):
_UserManagerToSomewhereTest.setUp(self)
from UserKit.UserManagerToFile import UserManagerToFile
self._mgr = UserManagerToFile()
self.setUpUserDir(self._mgr)
def setUpUserDir(self, mgr):
path = 'Users'
if os.path.exists(path):
shutil.rmtree(path, ignore_errors=1)
os.mkdir(path)
mgr.setUserDir(path)
def tearDown(self):
path = 'Users'
if os.path.exists(path):
shutil.rmtree(path, ignore_errors=1)
_UserManagerToSomewhereTest.tearDown(self)
class UserManagerToMiddleKitTest(_UserManagerToSomewhereTest):
def write(self, text):
self._output.append(text)
def setUp(self):
_UserManagerToSomewhereTest.setUp(self)
self._output = []
self._stdout, self._stderr = sys.stdout, sys.stderr
sys.stdout = sys.stderr = self
try:
# Generate Python and SQL from our test MiddleKit Model
from MiddleKit.Design.Generate import Generate
generator = Generate()
modelFileName = os.path.join(TEST_CODE_DIR, 'UserManagerTest.mkmodel')
generationDir = os.path.join(TEST_CODE_DIR, 'mk_MySQL')
# _log.debug('model: %s',modelFileName)
# @@ 2001-02-18 ce: woops: hard coding MySQL
args = 'Generate.py --db MySQL --model %s --outdir %s' % (
modelFileName, generationDir)
Generate().main(args.split())
create_sql = os.path.join(generationDir, 'GeneratedSQL', 'Create.sql')
assert os.path.exists(create_sql), \
'The generation process should create some SQL files.'
assert os.path.exists(os.path.join(generationDir, 'UserForMKTest.py')), \
'The generation process should create some Python files.'
self._mysqlTestInfo = AllTests.config().setting('mysqlTestInfo')
# _log.info('mysqlTestInfo=%s', self._mysqlTestInfo)
# Create our test database using info from AllTests.config
self._mysqlClient = self._mysqlTestInfo['mysqlClient']
mysqlClientName = os.path.basename(self._mysqlClient)
assert mysqlClientName == 'mysql' or mysqlClientName == 'mysql.exe'
self._mysqlClient = ' '.join([self._mysqlClient] + ['--%s="%s"'
% (p.replace('passwd', 'password'), v) for (p ,v)
in self._mysqlTestInfo['DatabaseArgs'].items() if v])
executeSqlCmd = '%s < %s' % (self._mysqlClient, create_sql)
# _log.debug('running: %s', executeSqlCmd)
f = os.popen(executeSqlCmd)
self._output.append(f.read())
if f.close():
raise OSError, 'Error running: %s' % executeSqlCmd
# Create store, and connect to database
from MiddleKit.Run.MySQLObjectStore import MySQLObjectStore
store = MySQLObjectStore(**self._mysqlTestInfo['DatabaseArgs'])
store.readModelFileNamed(modelFileName)
from MiddleKit.Run.MiddleObject import MiddleObject
from UserKit.UserManagerToMiddleKit import UserManagerToMiddleKit
from UserKit.Tests.mk_MySQL.UserForMKTest import UserForMKTest
assert issubclass(UserForMKTest, MiddleObject)
from UserKit.User import User
if User not in UserForMKTest.__bases__:
UserForMKTest.__bases__ += (User,)
assert issubclass(UserForMKTest, MiddleObject)
def __init__(self, manager, name, password):
base1 = self.__class__.__bases__[0]
base2 = self.__class__.__bases__[1]
base1.__init__(self)
base2.__init__(self, manager=manager, name=name, password=password)
UserForMKTest.__init__ = __init__
self._mgr = self.userManagerClass()(userClass=UserForMKTest, store=store)
except Exception:
sys.stdout, sys.stderr = self._stdout, self._stderr
print "Error in %s.SetUp." % self.__class__.__name__
print ''.join(self._output)
raise
else:
sys.stdout, sys.stderr = self._stdout, self._stderr
def testUserClass(self):
pass
def userManagerClass(self):
from UserKit.UserManagerToMiddleKit import UserManagerToMiddleKit
return UserManagerToMiddleKit
def tearDown(self):
self._output = []
self._stdout, self._stderr = sys.stdout, sys.stderr
sys.stdout = sys.stderr = self
try:
# clean out generated files
path = os.path.join(TEST_CODE_DIR, 'mk_MySQL')
if os.path.exists(path):
shutil.rmtree(path, ignore_errors=1)
# Drop tables from database
sqlDropTables = "drop table UserForMKTest, _MKClassIds"
db = self._mysqlTestInfo['database']
executeSqlCmd = '%s %s -e "%s"' % (self._mysqlClient, db, sqlDropTables)
# _log.debug('running: %s', executeSqlCmd)
f = os.popen(executeSqlCmd)
self._output.append(f.read())
if f.close():
raise OSError, 'Error running: %s' % executeSqlCmd
except Exception:
sys.stdout, sys.stderr = self._stdout, self._stderr
print "Error in %s.SetUp." % self.__class__.__name__
print ''.join(self._output)
raise
else:
sys.stdout, sys.stderr = self._stdout, self._stderr
_UserManagerToSomewhereTest.tearDown(self)
class RoleUserManagerToFileTest(UserManagerToFileTest):
def setUp(self):
UserManagerToFileTest.setUp(self)
from UserKit.RoleUserManagerToFile import RoleUserManagerToFile
self._mgr = umClass()
self.setUpUserDir(self._mgr)
class RoleUserManagerToMiddleKitTest(UserManagerToMiddleKitTest):
def userManagerClass(self):
from UserKit.RoleUserManagerToMiddleKit import RoleUserManagerToMiddleKit
return RoleUserManagerToMiddleKit
def makeTestSuite():
testClasses = [
UserManagerTest, UserManagerToFileTest, RoleUserManagerToFileTest]
# See if AllTests.conf has been configured for MySQL
if AllTests.config().setting('hasMysql'):
mysqlTestInfo = AllTests.config().setting('mysqlTestInfo')
_log.info('Adding MySQL tests for UserKit.')
# Add paths for MySQL-python driver
numBadPaths = AllTests.checkAndAddPaths(mysqlTestInfo['extraSysPath'])
# Add the tests that require MySQL
testClasses.extend([UserManagerToMiddleKitTest, RoleUserManagerToMiddleKitTest])
else:
_log.info('Skipping MySQL tests. MySQL is not configured in AllTests.config.')
make = unittest.makeSuite
tests = [unittest.makeSuite(klass) for klass in testClasses]
return unittest.TestSuite(tests)
|