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()


