123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- #!/usr/bin/python
- '''
- WebSocket server-side load test program. Sends and receives traffic
- that has a random payload (length and content) that is checksummed and
- given a sequence number. Any errors are reported and counted.
- '''
- import sys, os, socket, ssl, time, traceback
- import random, time
- from base64 import b64encode, b64decode
- from select import select
- sys.path.insert(0,os.path.dirname(__file__) + "/../utils/")
- from websocket import *
- buffer_size = 65536
- max_packet_size = 10000
- recv_cnt = send_cnt = 0
- def check(buf):
- global recv_cnt
- try:
- data_list = decode(buf)
- except:
- print "\n<BOF>" + repr(buf) + "<EOF>"
- return "Failed to decode"
- err = ""
- for data in data_list:
- if data.count('$') > 1:
- raise Exception("Multiple parts within single packet")
- if len(data) == 0:
- traffic("_")
- continue
- if data[0] != "^":
- err += "buf did not start with '^'\n"
- continue
- try:
- cnt, length, chksum, nums = data[1:-1].split(':')
- cnt = int(cnt)
- length = int(length)
- chksum = int(chksum)
- except:
- print "\n<BOF>" + repr(data) + "<EOF>"
- err += "Invalid data format\n"
- continue
- if recv_cnt != cnt:
- err += "Expected count %d but got %d\n" % (recv_cnt, cnt)
- recv_cnt = cnt + 1
- continue
- recv_cnt += 1
- if len(nums) != length:
- err += "Expected length %d but got %d\n" % (length, len(nums))
- continue
- inv = nums.translate(None, "0123456789")
- if inv:
- err += "Invalid characters found: %s\n" % inv
- continue
- real_chksum = 0
- for num in nums:
- real_chksum += int(num)
- if real_chksum != chksum:
- err += "Expected checksum %d but real chksum is %d\n" % (chksum, real_chksum)
- return err
- def generate():
- global send_cnt, rand_array
- length = random.randint(10, max_packet_size)
- numlist = rand_array[max_packet_size-length:]
- # Error in length
- #numlist.append(5)
- chksum = sum(numlist)
- # Error in checksum
- #numlist[0] = 5
- nums = "".join( [str(n) for n in numlist] )
- data = "^%d:%d:%d:%s$" % (send_cnt, length, chksum, nums)
- send_cnt += 1
- return encode(data)
- def responder(client, delay=10):
- global errors
- cqueue = []
- cpartial = ""
- socks = [client]
- last_send = time.time() * 1000
- while True:
- ins, outs, excepts = select(socks, socks, socks, 1)
- if excepts: raise Exception("Socket exception")
- if client in ins:
- buf = client.recv(buffer_size)
- if len(buf) == 0: raise Exception("Client closed")
- #print "Client recv: %s (%d)" % (repr(buf[1:-1]), len(buf))
- if buf[-1] == '\xff':
- if cpartial:
- err = check(cpartial + buf)
- cpartial = ""
- else:
- err = check(buf)
- if err:
- traffic("}")
- errors = errors + 1
- print err
- else:
- traffic(">")
- else:
- traffic(".>")
- cpartial = cpartial + buf
- now = time.time() * 1000
- if client in outs and now > (last_send + delay):
- last_send = now
- #print "Client send: %s" % repr(cqueue[0])
- client.send(generate())
- traffic("<")
- def test_handler(client):
- global errors, delay, send_cnt, recv_cnt
- send_cnt = 0
- recv_cnt = 0
- try:
- responder(client, delay)
- except:
- print "accumulated errors:", errors
- errors = 0
- raise
- if __name__ == '__main__':
- errors = 0
- try:
- if len(sys.argv) < 2: raise
- listen_port = int(sys.argv[1])
- if len(sys.argv) == 3:
- delay = int(sys.argv[2])
- else:
- delay = 10
- except:
- print "Usage: <listen_port> [delay_ms]"
- sys.exit(1)
- print "Prepopulating random array"
- rand_array = []
- for i in range(0, max_packet_size):
- rand_array.append(random.randint(0, 9))
- settings['listen_port'] = listen_port
- settings['daemon'] = False
- settings['handler'] = test_handler
- start_server()
|