Stress Test
You can use this python utility to test the DUAP platform performance - authentication capacity.
Make sure the following things ready.
- DUAP server installed on Windows 2003 server,
- Modify TypeSense similarity in Home - System Settings - Authenticator - Typesense - Info,
- Install Python 2.5 (or later) on the machine (XP SP3) where you are going to run the utility,
- Regsiter the com dll das.dll on the same machine.
Then run the following command in Windows Prompt.
stresstest.py -s 192.168.222.11 -p 8080 -d -t -c 5 -r 2
You can adjust the parameters, please run "stresstest.py -h" to see what they mean.
The result sample
Server URL: http://192.168.222.11:8080/das/xmlrpc Initializing Tests Creating application... OK Creating account... OK Creating TypeSense token... OK Creating DevicePass token... OK Training TypeSense token (77004276)... . . . . . . . . . Status: ACTIVE, Training: 9, Progress: 9 Start 2 tests with 5 threads per test Number of requests per thread: 2 Thread Result Serial Type --------------------------------------------------- 228 E-CREDENTIAL-INCORRECT 77004277 DevicePass 1968 TRUE 77004276 TypeSense 5156 E-CREDENTIAL-INCORRECT 77004277 DevicePass 5288 TRUE 77004276 TypeSense 5996 E-CREDENTIAL-INCORRECT 77004277 DevicePass 4416 TRUE 77004276 TypeSense 4828 TRUE 77004276 TypeSense 4732 E-CREDENTIAL-INCORRECT 77004277 DevicePass 228 TRUE 77004277 DevicePass 1968 TRUE 77004276 TypeSense 5288 TRUE 77004276 TypeSense 5156 E-CREDENTIAL-INCORRECT 77004277 DevicePass 4504 TRUE 77004276 TypeSense 5996 E-CREDENTIAL-INCORRECT 77004277 DevicePass 4828 TRUE 77004276 TypeSense 5096 E-CREDENTIAL-INCORRECT 77004277 DevicePass 4416 TRUE 77004276 TypeSense 4732 E-CREDENTIAL-INCORRECT 77004277 DevicePass 4504 TRUE 77004276 TypeSense 5096 E-CREDENTIAL-INCORRECT 77004277 DevicePass --------------------------------------------- Time: 0.636563267456 seconds Requests: 20 Requests/Time: 31.418715189
The Source Code
import sys import win32com.client import datetime import random import time import threading import thread from optparse import OptionParser creds = [ '90-1-0#90-2-121#69-1-228#69-2-322#78-1-343#78-2-421#71-1-445#71-2-525#89-1-580#89-2-671#73-1-769#73-2-858#9-1-959#9-2-858#80-1-1068#80-2-1151#65-1-1282#65-2-1368#83-1-1466#83-2-1541#83-1-1633#83-2-1711#80-1-1801#79-1-1944#80-2-1959#82-1-2078#79-2-2086#82-2-2163#84-1-2248#84-2-2350', '90-1-0#90-2-110#69-1-217#69-2-322#78-1-338#78-2-427#71-1-459#71-2-564#89-1-586#89-2-672#73-1-767#73-2-861#9-1-932#9-2-861#80-1-1025#80-2-1116#65-1-1198#65-2-1284#83-1-1396#83-2-1476#83-1-1558#83-2-1663#80-1-1728#80-2-1822#79-1-1882#79-2-1988#82-1-2042#82-2-2119#84-1-2207#84-2-2304', '90-1-0#90-2-111#69-1-228#69-2-339#78-1-361#78-2-476#71-1-512#71-2-606#89-1-647#89-2-733#73-1-839#73-2-928#9-1-1012#9-2-928#80-1-1163#80-2-1248#65-1-1325#65-2-1396#83-1-1508#83-2-1586#83-1-1687#83-2-1770#80-1-1851#80-2-1948#79-1-2008#79-2-2113#82-1-2141#82-2-2226#84-1-2311#84-2-2396', '90-1-0#90-2-105#69-1-225#69-2-316#78-1-343#78-2-448#71-1-525#89-1-627#71-2-649#89-2-707#73-1-806#73-2-897#9-1-973#9-2-897#80-1-1115#80-2-1184#65-1-1307#65-2-1356#83-1-1477#83-2-1543#83-1-1641#83-2-1721#80-1-1836#80-2-1905#79-1-1962#79-2-2081#82-1-2111#82-2-2191#84-1-2267#84-2-2370', '90-1-0#90-2-85#69-1-222#69-2-299#78-1-365#78-2-448#71-1-480#71-2-566#89-1-637#89-2-731#73-1-829#73-2-912#9-1-975#9-2-912#80-1-1119#80-2-1214#65-1-1295#65-2-1373#83-1-1474#83-2-1551#83-1-1644#83-2-1729#80-1-1798#80-2-1883#79-1-1943#79-2-2054#82-1-2098#82-2-2178#84-1-2284#84-2-2361', '90-1-0#90-2-119#69-1-234#69-2-314#78-1-330#78-2-413#71-1-441#71-2-537#89-1-586#89-2-669#73-1-770#73-2-848#9-1-902#9-2-848#80-1-1028#80-2-1108#65-1-1198#65-2-1281#83-1-1377#83-2-1446#83-1-1536#83-2-1616#80-1-1698#80-2-1781#79-1-1857#79-2-1970#82-1-2019#82-2-2102#84-1-2181#84-2-2298', '90-1-0#90-2-91#69-1-222#69-2-311#78-1-324#78-2-410#71-1-456#71-2-553#89-1-578#89-2-672#73-1-770#73-2-853#9-1-913#80-1-853#80-2-936#65-1-1007#65-2-1076#83-1-1180#83-2-1257#83-1-1358#83-2-1424#80-1-1484#80-2-1570#79-1-1619#79-2-1749#82-1-1776#82-2-1867#84-1-1946#84-2-2049', '90-1-0#90-2-75#69-1-217#78-1-316#69-2-330#78-2-416#71-1-438#71-2-554#89-1-576#89-2-653#73-1-749#73-2-840#9-1-911#9-2-840#80-1-1029#80-2-1114#65-1-1188#65-2-1271#83-1-1374#83-2-1441#83-1-1547#83-2-1602#80-1-1698#80-2-1795#79-1-1863#79-2-1965#82-1-2003#82-2-2094#84-1-2187#84-2-2278', '90-1-0#90-2-86#69-1-280#69-2-374#78-1-393#78-2-481#71-1-497#71-2-583#89-1-657#89-2-729#73-1-816#73-2-896#9-1-989#9-2-896#80-1-1125#80-2-1218#65-1-1273#65-2-1362#83-1-1457#83-2-1518#83-1-1614#83-2-1699#80-1-1748#80-2-1837#79-1-1894#79-2-2005#82-1-2029#82-2-2118#84-1-2199#84-2-2296', '90-1-0#90-2-107#69-1-186#69-2-272#78-1-291#78-2-376#71-1-406#71-2-503#89-1-525#89-2-604#73-1-692#73-2-783#9-1-876#9-2-783#80-1-991#80-2-1074#65-1-1139#65-2-1217#83-1-1320#83-2-1384#83-1-1471#83-2-1537#80-1-1663#80-2-1746#79-1-1789#79-2-1889#82-1-1976#82-2-2056#84-1-2201#84-2-2298' ] oManager = win32com.client.Dispatch("DAS.Manager") oAuth = win32com.client.Dispatch("DAS.Authenticator") uid='testaccount-001' loginName='testaccount' appid='STEST' tdid='8438C8D3-CF01-45c8-BAA8-1A9E7CE36344' ip='127.0.0.1' serial='' formats = "%10d %10s %10s %15s" deviceCredential='''<credential><method>DevicePass</method><credentialData><devicePrint>y02FyQz/HwxDC8R9mOXTAn52TlNECTyFue6JrHDAAZ8qtszQE6yw8XWNxI/d2l/qrMt9zrJ6 ngbYJfgMLevuhMI3TvWZHT8FydSEZHO5CcqDmSUEnNwNYAtFj4stTp6OEdrQ1Y5IXl0/Sp/0 Z+mY8pwY9l9HvFp2Elm6+P2UGGYJzVsS5LQ5eZ/f+oJiUggYfZjyU4BGD7AHmNHVI26RMkdd d0dlj93ZnDMfQyVsuUvnnWCmQvuCfIG77mECxlXvt7ZfM4njvVebrnHm8gwCxx6bXR9uRGuJ thU96sfLnC+qWyzeDTved4xLQU95pnoMbGjonPah4519CWqquXfsHslY6zGa7KU7AqLpqO/K IrzgCvHGl/j0dv6Es1/q6Pj1VCrsd8QDXH8cLfRnru/2jdTOqGC38L7YsW5BnwEW52Hlyy9K nZSP</devicePrint></credentialData></credential>''' devicePrint = '''<credential><method>DevicePass</method><token><deviceID>%s</deviceID><class>%s</class></token><credentialData> <devicePrint>y02FyQz/HwxDC8Rlz+rsK3xFTAJmHx6o2fi9l0zYD5oYk8KPKYKw8XWNxI/d2l/qrMt9zrJ6njOnA5ZNZo6gxsUkCYyeXlBe+K+AZ2ijNee3vyUEnNwNYD46qeVsBfvAU93DkvdPHTJke+TwZPKCzrEs0F9HvFp2EmzF3pPVUwNHj1wBo80+OvCEy/lmURMCQbXGdYBGD7AHmOSqBQDQeSITNUB2yKTe31xEcl5oulD9oU2SZPuCfIG77lR94Duu/NMRcY7w+i6c7R69w3cGxAWBYTJaYmuJthU96vK0ukHrEEmQTzzNMPVMAiAilwEIb3PyoNuVxZ19CWqquUKTOKcZoFTUrqIoRdvu64CRE8fkCercq9XAUP6Es1/q6M2KckStPKFNHngPao1g7YCtvK/Kq3utzJPsl25BnwEW52Hlyy9KnZSP</devicePrint></credentialData></credential>''' % (tdid, ip) counter_lock = thread.allocate_lock() g_reqs = 0 def increaseCounter(): try: # Entering critical section. counter_lock.acquire() global g_reqs g_reqs += 1 finally: counter_lock.release() def generateTypeprint(index): typeprint = creds[index] credential ='<?xml version="1.0"?>' credential += '<credential>' credential += '<method>Typesense</method>' credential += '<credentialData>' credential += '<typetext></typetext>' credential += '<typeprint>'+typeprint+'</typeprint>' credential += '</credentialData>' credential += '</credential>' return credential def testTypeSense(reqs): n = len(creds) for i in xrange(reqs): cred = generateTypeprint(i%n) result = oAuth.verifyCredential(appid, uid, cred) if options.verbose: print formats % (thread.get_ident(), oAuth.LastError, result.Serial, 'TypeSense ')#, result.Score increaseCounter() def trainToken(): n = len(creds) print 'Training TypeSense token (%s)...' % serial, for i in range(1,n): cred = generateTypeprint(i) result = oManager.trainToken(serial, cred) print '.', print result = oManager.checkToken(serial) if oManager.LastError!='OK': print oManager.LastError return False print 'Status: %s, Training: %d, Progress: %d' % (result.Status, result.Training, result.Progress) return True def testDevicePass(reqs): for i in xrange(reqs): result = oAuth.verifyCredential2('1234567890',appid,uid,devicePrint) if options.verbose: print formats % (thread.get_ident(), oAuth.LastError, result.Serial, 'DevicePass') increaseCounter() class TypeSenseTestThread(threading.Thread): def __init__(self, r): threading.Thread.__init__(self) self.reqs = r def run(self): testTypeSense(self.reqs) class DevicePassTestThread(threading.Thread): def __init__(self, r): threading.Thread.__init__(self) self.reqs = r def run(self): testDevicePass(self.reqs) def createEnv(): oApplication = win32com.client.Dispatch("DAS.Application") oApplication.Name = "Stress Test" oApplication.AppID = appid #oApplication.AppKey = "12345678" print print 'Initializing Tests' print print '\tCreating application...', result = oManager.createApp(oApplication) print oManager.LastError if not result: return False oAccount = win32com.client.Dispatch("DAS.Account") oAccount.AppID = appid oAccount.UserID =uid oAccount.UserName = "Test User" oAccount.LoginName = loginName print '\tCreating account...', result = oManager.createAccount(oAccount) print oManager.LastError if not result: return False if options.typesense: print '\tCreating TypeSense token...', oToken = win32com.client.Dispatch("DAS.Token") oToken.AppID = appid oToken.UserID = uid oToken.Method = 'TypeSense' oToken.Name = 'TestTypeSenseToken' oToken.Description = 'Typesense Token created by stress test' result = oManager.createToken(oToken, True) print oManager.LastError if result is None: return False global serial serial = result if options.devicepass: print '\tCreating DevicePass token...', oToken = win32com.client.Dispatch("DAS.Token") oToken.AppID = appid oToken.UserID = uid oToken.Method = 'DevicePass' oToken.Name = 'TestDevicePassToken' oToken.Description = 'DevicePass Token created by stress test' oToken.Credential = deviceCredential oToken.Class = ip oToken.DeviceID = tdid result = oManager.createToken(oToken, True) print oManager.LastError if result is None: return False print def clearupEnv(): oManager.deleteAccount(appid,uid) oManager.deleteApp(appid) def main(): parser = OptionParser() parser.add_option("-s", "--server", dest="serverIP", default="127.0.0.1", help="IP address of Deepnet Authentication Server", metavar="IP") parser.add_option("-p", "--port", dest="serverPort",default=8080,type='int', help="Port number of Deepnet Authentication Server", metavar="PORT") parser.add_option("-t", "--typesense", dest="typesense",default=False, action='store_true', help="Do TypeSense tests") parser.add_option("-d", "--devicepass", dest="devicepass",default=False, action='store_true', help="Do DevicePass tests") parser.add_option("-c", dest="threads",default=10, type='int', metavar="THREADS", help="Number of concurrent threads for each tests") parser.add_option("-r", dest="requests",default=10, type='int', metavar="REQUESTS", help="Number of requests per thread") parser.add_option("-q", "--quiet", action="store_false", dest="verbose", default=True, help="don't print verify credential details to stdout") global options (options, args) = parser.parse_args() tests = 0 if options.typesense: tests=tests+1 if options.devicepass: tests=tests+1 if tests==0: parser.print_help() sys.exit(2) global oManager, oAuth url = 'http://%s:%d/das/xmlrpc' % (options.serverIP, options.serverPort) print 'Server URL:', url oManager.ServerURI = url oAuth.ServerURI = url try: result = oManager.hello() if oManager.LastError !='OK': print 'Connect to server failed:',oManager.LastError sys.exit(1) except Exception, err: sys.stderr.write('ERROR: %s\n' % str(err)) sys.exit(1) try: createEnv() if options.typesense: trainToken() time.clock() thrdgrp=list() print if tests>1: print 'Start %d tests with %d threads per test' % (tests,options.threads) else: print 'Start %d test with %d threads per test' % (tests,options.threads) print 'Number of requests per thread: %d' % options.requests print if options.verbose and tests!=0: print "%10s %10s %10s %10s" % ('Thread', 'Result', 'Serial', 'Type') print '---------------------------------------------------' if options.typesense: for i in range(options.threads): m=TypeSenseTestThread(options.requests) m.start() thrdgrp.append(m) if options.devicepass: for i in range(options.threads): m=DevicePassTestThread(options.requests) m.start() thrdgrp.append(m) for t in thrdgrp: t.join() T = time.clock() if options.verbose and tests!=0: print '---------------------------------------------' print "Time:", T, "seconds\tRequests:", g_reqs, "\tRequests/Time:", g_reqs/T finally: clearupEnv() main()