Using nGrinder to perform load test for socket.io app Python version - songeunwoo/ngrinder GitHub Wiki
In previous guide, we used a java library to provide the synchronized java client for socket.io app. In this guide, we will use python to archieve this goal. The advantages to use python to implement the synchronized client for socket.io is, we can customize the event and communication easily in python just in nGrinder script editor. Not need to modify in java and export as a jar or class and upload into nGrinder. So, at first, we need to add a script in the lib directory named “BlockingSocketIO.py”. It can be imported in test script to use from the lib directory. The script will be as below:
# -*- coding:utf-8 -*-
from io.socket import IOCallback
from java.util.concurrent.locks import ReentrantLock
from io.socket import SocketIO
class BlockingSocketIO(IOCallback):
respMsg = "";
def __init__(self, url, logger):
logger.info("init with url: %s" % url)
self.transportLock = ReentrantLock()
self.responseCondition = self.transportLock.newCondition()
self.socketIO = SocketIO(url, self)
self.logger = logger;
def sendAndRcv(self, message):
try:
self.transportLock.lock()
self.socketIO.send(message)
self.respMsg = ""
self.responseCondition.await()
return self.respMsg
except Exception, err:
self.logger.error(err.message)
finally:
self.transportLock.unlock()
return self.respMsg;
def emitAndRcv(self, event, message):
try:
self.transportLock.lock();
self.socketIO.emit(event, message)
self.respMsg = ""
self.responseCondition.await()
return self.respMsg
except Exception, err:
self.logger.error(err.message)
finally:
self.transportLock.unlock()
return self.respMsg;
def onConnect(self):
self.logger.info("connected")
def onDisconnect(self):
self.logger.info("disconnect")
def onMessage(self, data, acknowledge):
self.logger.info("message")
setResponse(data)
def on(self, event, acknowledge, args):
self.logger.info("Server triggered event: %s" % event)
for x in args:
self.logger.info("args: %s" % x)
respStr = ",".join(x.toString() for x in args)
self.setResponse(respStr)
def onError(self, exception):
self.logger.error("error:%s" % exception.getMessage())
def setResponse(self, data):
self.logger.info("Server said: %s" % data)
try:
self.transportLock.lock()
self.respMsg = data
self.responseCondition.signal()
finally:
self.transportLock.unlock()
In this script, we implemented the java interface “IOCallback”. It is similiar with the java version of “BlockingSocketIO.java” of last guide. And the test script is almostsame as that in java version, just be careful to import the BlockingSocketIO from the py module, but not the java lib.
from net.grinder.script.Grinder import grinder
from net.grinder.script import Test
from org.json import JSONObject
import BlockingSocketIO
test1 = Test(1, "Test1")
class TestRunner:
def testSocketIO(self):
json = JSONObject()
user = "Thread-%s" % grinder.threadNumber
json.putOpt("user", user)
msg = "test message<%s>." % user
json.putOpt("message", msg)
grinder.logger.info("msg:" + json.toString())
respMsg = self.socketIO.emitAndRcv("user message", json)
return respMsg
def __init__(self):
grinder.statistics.delayReports=True
#init socket io, BlockingSocketIO.BlockingSocketIO() means from the module call that function to create a socketIO object.
self.socketIO = BlockingSocketIO.BlockingSocketIO("http://127.0.0.1:3000", grinder.logger)
#send socket.io server to init user
json = JSONObject()
user = "Thread-%s" % grinder.threadNumber
json.putOpt("username", user)
self.socketIO.emitAndRcv("user", json)
# test method
def __call__(self):
resp = self.testSocketIO()
if "test message" in resp :
grinder.statistics.forLastTest.success = 1
else :
grinder.statistics.forLastTest.success = 0
test1.record(TestRunner.testSocketIO)