Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_authentication.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_authentication.py	(revision 5760)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_authentication.py	(revision 5760)
@@ -0,0 +1,347 @@
+##
+## test_authentication.py
+## Login : <uli@pu.smp.net>
+## Started on  Fri Aug 20 08:18:58 2010 Uli Fouquet
+## $Id$
+## 
+## Copyright (C) 2010 Uli Fouquet
+## 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
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+## 
+## 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 General Public License for more details.
+## 
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+import grok
+import unittest
+from zope.component import provideAdapter
+from zope.component.hooks import setSite
+from zope.interface import verify
+from zope.pluggableauth.interfaces import  IAuthenticatedPrincipalFactory
+from zope.publisher.browser import TestRequest
+from zope.publisher.interfaces import IRequest
+from zope.session.session import RAMSessionDataContainer
+from zope.session.interfaces import ISession
+from zope.site import LocalSiteManager
+from zope.site.folder import Folder
+from zope.site.testing import siteSetUp, siteTearDown
+from zope.testing import cleanup
+from waeup.sirp.applicants.jambtables.authentication import (
+    ApplicantsAuthenticatorPlugin, WAeUPApplicantCredentialsPlugin,
+    ApplicantCredentials, AuthenticatedApplicantPrincipalFactory,
+    ApplicantPrincipalInfo, ApplicantPrincipal)
+from waeup.sirp.applicants.jambtables.interfaces import(
+    IJAMBApplicantSessionCredentials,)
+
+class FakeBatch(dict):
+    def getAccessCode(self, id):
+        return self.get(id)
+
+class FakeAccessCode(object):
+    def __init__(self, repr, inv_date=None):
+        self.invalidation_date = inv_date
+        self.representation = repr
+
+class FakeInvAccessCode(object):
+    invalidation_date = True
+
+class FakeApplication(object):
+    def __init__(self, ac=None):
+        self.access_code = ac
+
+class FakeSite(grok.Application, grok.Container):
+    def __init__(self):
+        super(FakeSite, self).__init__()
+        self['applications'] = {
+            'APP-12345': FakeApplication('APP-12345'),
+            'APP-54321': FakeApplication('APP-54321'),
+            'APP-22222': FakeApplication('APP-OTHER'),
+            'APP-44444': FakeApplication(),
+            'APP-55555': FakeApplication('APP-OTHER'),
+            'JAMB1': FakeApplication(),
+            'JAMB2': FakeApplication('APP-12345'),
+            'JAMB3': FakeApplication('APP-54321'),
+            'JAMB4': FakeApplication('APP-44444'),
+            }
+        self['accesscodes'] = {
+            'APP': FakeBatch({
+                    'APP-12345': FakeAccessCode('APP-12345'),
+                    'APP-54321': FakeAccessCode('APP-54321', True),
+                    'APP-11111': FakeAccessCode('APP-11111'),
+                    'APP-22222': FakeAccessCode('APP-22222'),
+                    'APP-33333': FakeAccessCode('APP-33333', True),
+                    'APP-44444': FakeAccessCode('APP-44444', True),
+                    'APP-55555': FakeAccessCode('APP-55555', True),
+                    })
+            }
+
+class AuthenticatorPluginTest(unittest.TestCase):
+
+    def setUp(self):
+        self.root = Folder()
+        siteSetUp(self.root)
+        self.app = FakeSite() #grok.Application()
+        self.root['app'] = self.app
+        self.app.setSiteManager(LocalSiteManager(self.app))
+        self.plugin = ApplicantsAuthenticatorPlugin()
+        setSite(self.app)
+        return
+
+    def tearDown(self):
+        siteTearDown()
+        return
+
+    def test_invalid_credentials(self):
+        result = self.plugin.authenticateCredentials('not-a-dict')
+        assert result is None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode=None, foo='blah'))
+        assert result is None
+
+        result = self.plugin.authenticateCredentials(
+            dict(jambregno=None, foo='blah'))
+        assert result is None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode=None, jambregno=None))
+        assert result is None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='Nonsense', jambregno='Nonsense'))
+        assert result is None
+
+        # The nine possible cases, where formal correct authentication
+        # data is not valid:
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-22222'))
+        assert result is None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-33333'))
+        assert result is None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-44444'))
+        assert result is None
+        
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-55555'))
+        assert result is None
+        
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-12345', jambregno='JAMB-NOT-EXISTENT'))
+        assert result is None
+        
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-12345', jambregno='JAMB3'))
+        assert result is None
+        
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-54321', jambregno='JAMB-NOT-EXISTENT'))
+        assert result is None
+        
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-54321', jambregno='JAMB1'))
+        assert result is None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-54321', jambregno='JAMB2'))
+        assert result is None
+        
+        return
+
+    def test_valid_credentials(self):
+        """The six different cases where we allow login.
+
+        All other combinations should be forbidden.
+        """
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-11111'))
+        assert result is not None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-12345'))
+        assert result is not None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-54321'))
+        assert result is not None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-12345', jambregno='JAMB1'))
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-12345', jambregno='JAMB2'))
+        assert result is not None
+
+        result = self.plugin.authenticateCredentials(
+            dict(accesscode='APP-54321', jambregno='JAMB3'))
+        assert result is not None
+
+        # check the `principalInfo` method of authenticator
+        # plugin. This is only here to satisfy the coverage report.
+        assert self.plugin.principalInfo('not-an-id') is None
+        return
+
+session_data = {
+    'zope.pluggableauth.browserplugins': {}
+    }
+
+class FakeSession(dict):
+    def __init__(self, request):
+        pass
+
+    def get(self, key, default=None):
+        return self.__getitem__(key, default)
+    
+    def __getitem__(self, key, default=None):
+        return session_data.get(key, default)
+
+    def __setitem__(self, key, value):
+        session_data[key] = value
+        return
+
+class CredentialsPluginTest(unittest.TestCase):
+
+    def setUp(self):
+        self.request = TestRequest()
+        provideAdapter(FakeSession, (IRequest,), ISession)
+        self.plugin = WAeUPApplicantCredentialsPlugin()
+        self.full_request = TestRequest()
+        session_data['zope.pluggableauth.browserplugins'] = {}
+        return
+
+    def tearDown(self):
+        cleanup.tearDown()
+        return
+
+    def filled_request(self, form_dict):
+        request = TestRequest()
+        for key, value in form_dict.items():
+            request.form[key] = value
+        return request
+
+    def test_extractCredentials_invalid(self):
+        result = self.plugin.extractCredentials('not-a-request')
+        assert result is None
+        return
+
+    def test_extractCredentials_empty(self):
+        result = self.plugin.extractCredentials(self.request)
+        assert result is None
+        return
+
+    def test_extractCredentials_full_set(self):
+        request = self.filled_request({
+                'form.prefix': 'APP',
+                'form.ac_series': '1',
+                'form.ac_number': '1234567890',
+                'form.jamb_reg_no': 'JAMB_NUMBER',
+                })
+        result = self.plugin.extractCredentials(request)
+        self.assertEqual(result, {'jambregno': 'JAMB_NUMBER',
+                                  'accesscode': 'APP-1-1234567890'})
+        return
+
+    def test_extractCredentials_accesscode_only(self):
+        request = self.filled_request({
+                'form.prefix': 'APP',
+                'form.ac_series': '1',
+                'form.ac_number': '1234567890',
+                })
+        result = self.plugin.extractCredentials(request)
+        self.assertEqual(result, {'accesscode': 'APP-1-1234567890'})
+        return
+
+    def test_extractCredentials_from_empty_session(self):
+        session_data['zope.pluggableauth.browserplugins']['credentials'] = None
+        result = self.plugin.extractCredentials(self.request)
+        assert result is None
+        return
+
+    def test_extractCredentials_from_nonempty_session(self):
+        credentials = ApplicantCredentials('APP-1-12345')
+        session_data['zope.pluggableauth.browserplugins'][
+            'credentials'] = credentials
+        result = self.plugin.extractCredentials(self.request)
+        self.assertEqual(result, {'accesscode': 'APP-1-12345'})
+        return
+
+
+class ApplicantCredentialsTest(unittest.TestCase):
+
+    def setUp(self):
+        self.credentials = ApplicantCredentials('SOME_ACCESSCODE')
+        return
+
+    def tearDown(self):
+        return
+
+    def test_methods(self):
+        self.assertEqual(self.credentials.getAccessCode(), 'SOME_ACCESSCODE')
+        assert self.credentials.getLogin() is None
+        assert self.credentials.getPassword() is None
+        return
+
+class FakePluggableAuth(object):
+    prefix = 'foo'
+
+class PrincipalFactoryTest(unittest.TestCase):
+
+    def setUp(self):
+        self.info = ApplicantPrincipalInfo('APP-1-1234567890')
+        return
+
+    def tearDown(self):
+        pass
+
+    def test_principalFactory_interface(self):
+        verify.verifyClass(IAuthenticatedPrincipalFactory,
+                           AuthenticatedApplicantPrincipalFactory
+                           )
+        return
+
+    def test_principalFactory_create(self):
+        factory = AuthenticatedApplicantPrincipalFactory(self.info, None)
+
+        assert factory.info is self.info
+        assert factory.request is None
+        return
+
+    def test_principalFactory_call_w_prefix(self):
+        factory = AuthenticatedApplicantPrincipalFactory(self.info, None)
+        principal = factory(FakePluggableAuth())
+
+        assert isinstance(principal, ApplicantPrincipal)
+        self.assertEqual(principal.__repr__(),
+                         "ApplicantPrincipal('foo.APP-1-1234567890')")
+        self.assertEqual(principal.id, 'foo.APP-1-1234567890')
+        return
+
+    def test_principalFactory_call_wo_prefix(self):
+        factory = AuthenticatedApplicantPrincipalFactory(self.info, None)
+        fake_auth = FakePluggableAuth()
+        fake_auth.prefix = None
+        principal = factory(fake_auth)
+        self.assertEqual(principal.id, 'APP-1-1234567890')
+        return
+        
+def test_suite():
+    suite = unittest.TestSuite()
+    for testcase in [
+        AuthenticatorPluginTest, CredentialsPluginTest,
+        ApplicantCredentialsTest, PrincipalFactoryTest,
+        ]:
+        suite.addTest(unittest.TestLoader().loadTestsFromTestCase(
+                testcase
+                )
+        )
+    return suite
