# Tests for webservices
import xmlrpclib
import os
from time import time
from cStringIO import StringIO
from zope.app.testing.xmlrpc import ServerProxy
from zope.component import getUtility, createObject
from waeup.kofa.interfaces import (
IExtFileStore, IFileStoreNameChooser, IKofaUtils)
from waeup.kofa.testing import FunctionalLayer
from waeup.kofa.utils.helpers import to_timezone
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):
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_students_by_department(self):
self.course2 = createObject('waeup.Course')
self.course2.code = 'COURSE2'
self.app['faculties']['fac1']['dep1'].courses.addCourse(
self.course2)
self.setup_student(self.student)
ticket = CourseTicket()
ticket.code = u'COURSE2'
ticket.title = u'Course 2'
ticket.fcode = u'fac1'
ticket.dcode = u'fac1'
self.student['studycourse']['100'][ticket.code] = ticket
server = ServerProxy('http://mgr:mgrpw@localhost/app')
result = server.get_students_by_department('fac1','dep1', '2011')
self.assertEqual(result, {})
result = server.get_students_by_department('fac1','dep1', '2012', '200')
self.assertEqual(result, {})
result = server.get_students_by_department('fac1','dep1', '2012', '100')
self.assertEqual(
result, {'K1000000': [
'234', 'Anna Tester', 2004, 100, ['COURSE1', 'COURSE2']]})
result = server.get_students_by_department('fac1','dep1', '0', '100')
self.assertEqual(
result, {'K1000000': [
'234', 'Anna Tester', 2004, 100, ['COURSE1', 'COURSE2']]})
result = server.get_students_by_department('fac1','dep1')
self.assertEqual(
result, {'K1000000': [
'234', 'Anna Tester', 2004, 100, ['COURSE1', 'COURSE2']]})
result = server.get_students_by_department('fac1','dep2')
self.assertEqual(result, None)
REQUEST_XML = """\
get_students_by_department
fac1
dep1
0
100
"""
RESPONSE_XML = """\
K1000000
234
Anna Tester
2004
100
COURSE1
COURSE2
"""
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_grad_student(self):
server = ServerProxy('http://localhost/app')
self.setup_student(self.student)
result = server.get_grad_student('123', 'aa@aa.ng')
self.assertEqual(result,
[True, False, False])
REQUEST_XML = """\
get_grad_student
K1000000
aa@aa.ng
"""
RESPONSE_XML = """\
1
0
0
"""
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
def test_get_bursary_data(self):
tz = getUtility(IKofaUtils).tzinfo
payment1 = StudentOnlinePayment()
payment1.p_id = 'my-id1'
payment1.p_session = 2012
payment1.amount_auth = 12.12
payment1.p_state = u'paid'
payment1.p_category = u'schoolfee'
self.student['payments']['my-payment1'] = payment1
payment2 = StudentOnlinePayment()
payment2.p_id = 'my-id2'
payment2.p_session = 2012
payment2.amount_auth = 12.12
payment2.p_state = u'paid'
payment2.p_category = u'clearance'
self.student['payments']['my-payment2'] = payment2
server = ServerProxy('http://mgr:mgrpw@localhost/app', allow_none=True)
result = server.get_bursary_data(None,None,None,None,'dep1',2012)
self.assertEqual(
result,[
{'entry_mode': None, 'reg_number': '123', 'display_item': None,
'firstname': 'Anna', 'payment_date': 'None#',
'middlename': None, 'student_id': 'K1000000', 'p_id':
'my-id1', 'certcode': 'CERT1', 'entry_session': 2004,
'creation_date': str('%s#' % to_timezone(payment1.creation_date, tz)),
'state': 'created', 'current_session': 2004,
'faccode': 'fac1', 'lastname': 'Tester',
'p_category': 'schoolfee', 'amount_auth': 12.12,
'p_state': 'paid', 'p_session': 2012, 'matric_number': '234',
'depcode': 'dep1'},
{'entry_mode': None, 'reg_number': '123', 'display_item': None,
'firstname': 'Anna', 'payment_date': 'None#',
'middlename': None, 'student_id': 'K1000000',
'p_id': 'my-id2', 'certcode': 'CERT1', 'entry_session': 2004,
'creation_date': str('%s#' % to_timezone(payment2.creation_date, tz)),
'state': 'created', 'current_session': 2004, 'faccode': 'fac1',
'lastname': 'Tester', 'p_category': 'clearance',
'amount_auth': 12.12, 'p_state': 'paid', 'p_session': 2012,
'matric_number': '234', 'depcode': 'dep1'}
]
)
REQUEST_XML = """\
get_bursary_data
dep1
"""
RESPONSE_XML = """\
entry_mode
reg_number
123
display_item
firstname
Anna
payment_date
None#
middlename
student_id
K1000000
p_id
my-id1
certcode
CERT1
creation_date
%s
matric_number
234
state
created
lastname
Tester
current_session
2004
faccode
fac1
entry_session
2004
p_category
schoolfee
amount_auth
12.12
p_session
2012
p_state
paid
depcode
dep1
entry_mode
reg_number
123
display_item
firstname
Anna
payment_date
None#
middlename
student_id
K1000000
p_id
my-id2
certcode
CERT1
creation_date
%s
matric_number
234
state
created
lastname
Tester
current_session
2004
faccode
fac1
entry_session
2004
p_category
clearance
amount_auth
12.12
p_session
2012
p_state
paid
depcode
dep1
"""
xmlout = self.XMLRPC_post(REQUEST_XML)
response = RESPONSE_XML % (str('%s#' % to_timezone(payment1.creation_date, tz)),
str('%s#' % to_timezone(payment2.creation_date, tz))
)
self.assertEqual(xmlout, response)
return
def test_get_payment(self):
payment1 = StudentOnlinePayment()
payment1.p_id = 'my-id1'
payment1.p_session = 2012
payment1.amount_auth = 12.12
payment1.p_state = u'failed'
payment1.p_category = u'schoolfee'
payment1.r_company = u'xyz'
self.student['payments']['my-payment1'] = payment1
server = ServerProxy('http://mgr:mgrpw@localhost/app', allow_none=True)
results = server.get_payment()
self.assertEqual(results, None)
results = server.get_payment('nonsense')
self.assertEqual(results, None)
results = server.get_payment('my-id1')
self.assertEqual(
results,
{'display_item': None,
'p_id': 'my-id1',
'p_category': 'schoolfee',
'amount_auth': 12.12, 'p_session': 2012,
'p_state': 'failed',
'r_company': 'xyz',
'fullname': 'Anna Tester',
'id': 'K1000000',
'matric_number': '234'}
)
REQUEST_XML = """\
get_payment
my-id1
"""
RESPONSE_XML = """\
display_item
amount_auth
12.12
p_id
my-id1
r_company
xyz
matric_number
234
p_category
schoolfee
fullname
Anna Tester
p_state
failed
p_session
2012
id
K1000000
"""
xmlout = self.XMLRPC_post(REQUEST_XML)
self.assertEqual(xmlout, RESPONSE_XML)
return
def test_get_unpaid_payments(self):
timestamp1 = ("%d" % int((time()-10)*10000))[1:]
timestamp2 = ("%d" % int((time()-5)*10000))[1:]
timestamp3 = ("%d" % int((time()-(3*86400))*10000))[1:]
p_id_1 = ("p%s" % timestamp1)
p_id_2 = ("p%s" % timestamp2)
p_id_3 = ("p%s" % timestamp3)
payment1 = StudentOnlinePayment()
payment1.p_id = p_id_1
payment1.p_session = 2012
payment1.amount_auth = 12.12
payment1.p_state = u'failed'
payment1.p_category = u'schoolfee'
payment1.r_company = u'xyz'
self.student['payments']['my-payment1'] = payment1
payment2 = StudentOnlinePayment()
payment2.p_id = p_id_2
payment2.p_session = 2012
payment2.amount_auth = 12.12
payment2.p_state = u'paid'
payment2.p_category = u'clearance'
self.student['payments']['my-payment2'] = payment2
payment3 = StudentOnlinePayment()
payment3.p_id = p_id_3
payment3.p_session = 2012
payment3.amount_auth = 12.12
payment3.p_state = u'unpaid'
payment3.p_category = u'schoolfee'
self.student['payments']['my-payment3'] = payment3
server = ServerProxy('http://mgr:mgrpw@localhost/app', allow_none=True)
results = server.get_unpaid_payments(1)
self.assertEqual(
results,[
{'display_item': None,
'p_id': '%s' % p_id_1,
'p_category': 'schoolfee',
'amount_auth': 12.12, 'p_session': 2012,
'p_state': 'failed',
'r_company': 'xyz',
'fullname': 'Anna Tester',
'id': 'K1000000',
'matric_number': '234'}
])
results = server.get_unpaid_payments(4)
self.assertEqual(
results,[
{'display_item': None,
'p_id': '%s' % p_id_3,
'p_category': 'schoolfee',
'amount_auth': 12.12,
'p_session': 2012,
'p_state': 'unpaid',
'r_company': None,
'fullname': 'Anna Tester',
'id': 'K1000000',
'matric_number': '234'},
{'display_item': None,
'p_id': '%s' % p_id_1,
'p_category': 'schoolfee',
'amount_auth': 12.12,
'p_session': 2012,
'p_state': 'failed',
'r_company': 'xyz',
'fullname': 'Anna Tester',
'id': 'K1000000',
'matric_number': '234'},
])
results = server.get_unpaid_payments(4,'xyz')
self.assertEqual(
results,[
{'display_item': None,
'p_id': '%s' % p_id_1,
'p_category': 'schoolfee',
'amount_auth': 12.12,
'p_session': 2012,
'p_state': 'failed',
'r_company': 'xyz',
'fullname': 'Anna Tester',
'id': 'K1000000',
'matric_number': '234'},
])
REQUEST_XML = """\
get_unpaid_payments
1
"""
RESPONSE_XML = """\
display_item
amount_auth
12.12
p_id
%s
r_company
xyz
matric_number
234
p_category
schoolfee
fullname
Anna Tester
p_state
failed
p_session
2012
id
K1000000
""" % p_id_1
xmlout = self.XMLRPC_post(REQUEST_XML)
self.assertEqual(xmlout, RESPONSE_XML)
return