# Tests for webservices import xmlrpclib import os from cStringIO import StringIO from zope.app.testing.xmlrpc import ServerProxy from zope.component import getUtility from waeup.kofa.interfaces import IExtFileStore, IFileStoreNameChooser from waeup.kofa.testing import FunctionalLayer from waeup.kofa.students.payments import StudentOnlinePayment from waeup.kofa.students.tests.test_browser import StudentsFullSetup from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket class XMLRPCTests(StudentsFullSetup): # check XMLRPC services for university portal layer = FunctionalLayer def setup_student(self, student): study_level = StudentStudyLevel() study_level.level_session = 2012 study_level.level_verdict = "A" study_level.level = 100 study_level.validated_by = u"my adviser" student['studycourse'].addStudentStudyLevel( self.certificate, study_level) ticket = CourseTicket() ticket.automatic = True ticket.carry_over = True ticket.code = u'CRS1' ticket.title = u'Course 1' ticket.fcode = u'FAC1' ticket.dcode = u'DEP1' ticket.credits = 100 ticket.passmark = 100 ticket.semester = 2 study_level[ticket.code] = ticket def create_passport_img(self, student): # create some passport file for `student` storage = getUtility(IExtFileStore) image_path = os.path.join(os.path.dirname(__file__), 'test_image.jpg') self.image_contents = open(image_path, 'rb').read() file_id = IFileStoreNameChooser(student).chooseName( attr='passport.jpg') storage.createFile(file_id, StringIO(self.image_contents)) def create_fpm_file(self, student, finger_num): # create some .fpm file for `student` finger `finger_num` storage = getUtility(IExtFileStore) file_id = IFileStoreNameChooser(student).chooseName( attr='%s.fpm' % finger_num) storage.createFile(file_id, StringIO('FP1FakedMintiaeFile1')) def XMLRPC_post(self, body): self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') self.browser.addHeader('Content-Length', len(body)) self.browser.post('http://localhost/app', body, 'text/xml; charset=utf-8') return self.browser.contents def test_get_student_id_no_match(self): # w/o any students we get none server = ServerProxy('http://mgr:mgrpw@localhost/app') result = server.get_student_id('Nonsense') self.assertTrue(result is None) return def test_get_student_id_regno_exists(self): # we can get the id of an existing student with matching reg_no server = ServerProxy('http://mgr:mgrpw@localhost/app') result = server.get_student_id('123') self.assertEqual(result, 'K1000000') self.assertEqual(self.student_id, result) REQUEST_XML = """\ get_student_id 123 """ RESPONSE_XML = """\ K1000000 """ xmlout = self.XMLRPC_post(REQUEST_XML) self.assertEqual(xmlout, RESPONSE_XML) return def test_get_student_id_block_unauthorized(self): # requests from unauthorized users are blocked # no username nor password server = ServerProxy('http://localhost/app') self.assertRaises( xmlrpclib.ProtocolError, server.get_student_id, '123') # wrong password server = ServerProxy('http://mgr:WRONGPW@localhost/app') self.assertRaises( xmlrpclib.ProtocolError, server.get_student_id, '123') # wrong username server = ServerProxy('http://WRONGUSER:mgrpw@localhost/app') self.assertRaises( xmlrpclib.ProtocolError, server.get_student_id, '123') return def test_get_courses_by_session(self): server = ServerProxy('http://mgr:mgrpw@localhost/app') result = server.get_courses_by_session('K1000000') self.assertEqual(result, None) self.setup_student(self.student) result = server.get_courses_by_session('K1000000', '2010') self.assertEqual(result, None) result = server.get_courses_by_session('K1000000', '2012') self.assertEqual(result, {'100|CRS1': 'Course 1', '100|COURSE1': 'Unnamed Course'}) result = server.get_courses_by_session('K1000000') self.assertEqual(result, {'100|CRS1': 'Course 1', '100|COURSE1': 'Unnamed Course'}) # Also matric_number ... result = server.get_courses_by_session('234') self.assertEqual(result, {'100|CRS1': 'Course 1', '100|COURSE1': 'Unnamed Course'}) # ... or reg_number can be used. result = server.get_courses_by_session('123') self.assertEqual(result, {'100|CRS1': 'Course 1', '100|COURSE1': 'Unnamed Course'}) result = server.get_courses_by_session('Nonsense') self.assertEqual(result, None) REQUEST_XML = """\ get_courses_by_session K1000000 """ RESPONSE_XML = """\ 100|CRS1 Course 1 100|COURSE1 Unnamed Course """ xmlout = self.XMLRPC_post(REQUEST_XML) self.assertEqual(xmlout, RESPONSE_XML) return def test_get_students_by_course(self): self.setup_student(self.student) server = ServerProxy('http://mgr:mgrpw@localhost/app') result = server.get_students_by_course('CRS1', '2010') self.assertEqual(result, None) result = server.get_students_by_course('CRS1', '2012') self.assertEqual(result, [['K1000000', '234', 'my adviser', 0], ]) result = server.get_students_by_course('CRS1') self.assertEqual(result, [['K1000000', '234', 'my adviser', 0], ]) payment = StudentOnlinePayment() payment.p_id = 'my-id' payment.p_session = 2012 payment.amount_auth = 12.12 payment.p_state = u'paid' payment.p_category = u'schoolfee' self.student['payments']['my-payment'] = payment result = server.get_students_by_course('CRS1') self.assertEqual(result, [['K1000000', '234', 'my adviser', 12.12], ]) REQUEST_XML = """\ get_students_by_course CRS1 2012 """ RESPONSE_XML = """\ K1000000 234 my adviser 12.12 """ xmlout = self.XMLRPC_post(REQUEST_XML) self.assertEqual(xmlout, RESPONSE_XML) return def test_get_student_info(self): server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) result = server.get_student_info('123') self.assertEqual(result, ['Anna Tester', 'CERT1', '1234', 'aa@aa.ng']) REQUEST_XML = """\ get_student_info K1000000 """ RESPONSE_XML = """\ Anna Tester CERT1 1234 aa@aa.ng """ xmlout = self.XMLRPC_post(REQUEST_XML) self.assertEqual(xmlout, RESPONSE_XML) return def test_get_student_passport(self): server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) self.create_passport_img(self.student) result = server.get_student_passport('123') img = getUtility(IExtFileStore).getFileByContext( self.student, attr='passport.jpg') binary = img.read() self.assertEqual(binary, result) REQUEST_XML = """\ get_student_passport K1000000 """ RESPONSE_XML = """\ /9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+4ADkFkb2JlAGTAAAAAAf/b """ xmlout = self.XMLRPC_post(REQUEST_XML) self.assertTrue(xmlout.startswith(RESPONSE_XML)) def test_get_paid_sessions(self): server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) payment = StudentOnlinePayment() payment.p_id = 'my-id' payment.p_session = 2009 payment.amount_auth = 12.12 payment.p_state = u'paid' payment.p_category = u'schoolfee' self.student['payments']['my-payment'] = payment result = server.get_paid_sessions('123') self.assertEqual(result, {'2009': 12.12}) REQUEST_XML = """\ get_paid_sessions K1000000 """ RESPONSE_XML = """\ 2009 12.12 """ xmlout = self.XMLRPC_post(REQUEST_XML) self.assertEqual(xmlout, RESPONSE_XML) return def test_check_student_credentials(self): # make sure we can get student infos providing valid creds server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) stud_id = self.student.student_id result = server.check_student_credentials(stud_id, 'spwd') self.assertEqual( result, { 'description': 'Anna Tester', 'email': 'aa@aa.ng', 'id': 'K1000000', 'type': 'student'} ) return def test_get_student_moodle_data(self): server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) result = server.get_student_moodle_data(self.student.student_id) self.assertEqual(result, {'lastname': 'Tester', 'email': 'aa@aa.ng', 'firstname': 'Anna'}) REQUEST_XML = """\ get_student_moodle_data K1000000 """ RESPONSE_XML = """\ lastname Tester email aa@aa.ng firstname Anna """ xmlout = self.XMLRPC_post(REQUEST_XML) self.assertEqual(xmlout, RESPONSE_XML) return def test_put_student_fingerprints_no_stud(self): # invalid student ids will result in `False` server = ServerProxy('http://mgr:mgrpw@localhost/app') self.assertRaises( xmlrpclib.Fault, server.put_student_fingerprints, 'invalid id', {}) def test_put_student_fingerprints_non_dict(self): # fingerprints must be passed in in a dict server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) self.assertRaises( xmlrpclib.Fault, server.put_student_fingerprints, self.student.student_id, 'not-a-dict') def test_put_student_fingerprints_non_num_keys_ignored(self): # non-numeric keys in fingerprint dict are ignored server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) result = server.put_student_fingerprints( self.student.student_id, {'not-a-num': 'foo', '12.2': 'bar', '123': 'baz'}) self.assertEqual(result, False) def test_put_student_fingerprints_non_fpm_data(self): # we cannot pass non-.fpm files as values server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) self.assertRaises( xmlrpclib.Fault, server.put_student_fingerprints, self.student.student_id, {'1': 'not-a-fingerprint'}) def test_put_student_fingerprints_invalid_file_format(self): # invalid files will result in `False` server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) invalid_fpm = xmlrpclib.Binary('invalid file') self.assertRaises( xmlrpclib.Fault, server.put_student_fingerprints, self.student.student_id, {'1': invalid_fpm}) def test_put_student_fingerprints(self): # we can store fingerprints server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) fpm = xmlrpclib.Binary('FP1faked_fpm') result = server.put_student_fingerprints( self.student.student_id, {'1': fpm}) self.assertEqual(result, True) stored_file = getUtility(IExtFileStore).getFileByContext( self.student, attr="finger1.fpm") self.assertEqual(stored_file.read(), 'FP1faked_fpm') # storing is logged logfile = os.path.join( self.app['datacenter'].storage, 'logs', 'students.log') logcontent = open(logfile).read() self.assertTrue( 'zope.mgr - grok.meta.StudentsXMLRPC ' '- K1000000 - fingerprint stored' in logcontent) def test_put_student_fingerprints_existing(self): # existing fingerprints are overwritten server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) self.create_fpm_file(self.student, '1') fpm1 = xmlrpclib.Binary('FP1faked_fpm1') fpm2 = xmlrpclib.Binary('FP1faked_fpm2') result = server.put_student_fingerprints( self.student.student_id, {'1': fpm1, '3': fpm2}) self.assertEqual(result, True) stored_file1 = getUtility(IExtFileStore).getFileByContext( self.student, attr="finger1.fpm") stored_file2 = getUtility(IExtFileStore).getFileByContext( self.student, attr="finger3.fpm") self.assertEqual(stored_file1.read(), 'FP1faked_fpm1') self.assertEqual(stored_file2.read(), 'FP1faked_fpm2') def test_get_student_fingerprints_no_stud(self): # invalid student ids result in empty dict server = ServerProxy('http://mgr:mgrpw@localhost/app') result = server.get_student_fingerprints('invalid id') self.assertEqual(result, {}) def test_get_student_fingerprints_no_files(self): # we get student data, but no fingerprints if not stored before server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) result = server.get_student_fingerprints(self.student.student_id) self.assertEqual( result, {'lastname': 'Tester', 'email': 'aa@aa.ng', 'firstname': 'Anna', 'fingerprints': {}, 'img': None, 'img_name': None, }) def test_get_student_fingerprints_passport(self): # we get a photograph of the student if avail. server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) self.create_passport_img(self.student) result = server.get_student_fingerprints(self.student.student_id) self.assertTrue( isinstance(result['img'], xmlrpclib.Binary)) self.assertEqual(result['img_name'], 'passport_K1000000.jpg') def test_get_student_fingerprints_fpm(self): # we get minutiae files if any are avail. server = ServerProxy('http://mgr:mgrpw@localhost/app') self.setup_student(self.student) self.create_fpm_file(self.student, 'finger1') result = server.get_student_fingerprints(self.student.student_id) self.assertTrue('1' in result['fingerprints'].keys()) self.assertTrue( isinstance(result['fingerprints']['1'], xmlrpclib.Binary)) def test_get_student_fingerprints_block_unauthorized(self): # requests from unauthorized users are blocked # no username nor password server = ServerProxy('http://localhost/app') self.setup_student(self.student) stud_id = self.student.student_id self.assertRaises( xmlrpclib.ProtocolError, server.get_student_id, stud_id) # wrong password server = ServerProxy('http://mgr:WRONGPW@localhost/app') self.assertRaises( xmlrpclib.ProtocolError, server.get_student_id, stud_id) # wrong username server = ServerProxy('http://WRONGUSER:mgrpw@localhost/app') self.assertRaises( xmlrpclib.ProtocolError, server.get_student_id, stud_id) return