mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-08 12:10:59 +00:00
http_server : Fix and enable example tests
This introduces the following changes in the example test scripts : * Dependency on python requests library removed in favor of httplib * Bug fixed in the logic responsible for receiving and processing http chunked responses * Default timeouts increased Note : Due to connectivity issues (between runner host and DUT) in the runner environment, some of the advanced_tests are being ignored. These tests are intended for verifying the expected limits of the http_server capabilities, and implement sending and receiving of large HTTP packets and malformed requests, running multiple parallel sessions, etc. It is advised that all these tests be run locally, when making changes or adding new features to this component.
This commit is contained in:
@@ -130,11 +130,11 @@
|
||||
|
||||
|
||||
import threading
|
||||
from multiprocessing import Process, Queue
|
||||
import socket
|
||||
import time
|
||||
import argparse
|
||||
import requests
|
||||
import signal
|
||||
import httplib
|
||||
import sys
|
||||
import string
|
||||
import random
|
||||
@@ -144,8 +144,24 @@ _verbose_ = False
|
||||
class Session:
|
||||
def __init__(self, addr, port):
|
||||
self.client = socket.create_connection((addr, int(port)))
|
||||
self.client.settimeout(30)
|
||||
self.client.settimeout(15)
|
||||
self.target = addr
|
||||
self.status = 0
|
||||
self.encoding = ''
|
||||
self.content_type = ''
|
||||
self.content_len = 0
|
||||
|
||||
def send_err_check(self, request, data=None):
|
||||
rval = True
|
||||
try:
|
||||
self.client.sendall(request);
|
||||
if data:
|
||||
self.client.sendall(data)
|
||||
except socket.error as err:
|
||||
self.client.close()
|
||||
print "Socket Error in send :", err
|
||||
rval = False
|
||||
return rval
|
||||
|
||||
def send_get(self, path, headers=None):
|
||||
request = "GET " + path + " HTTP/1.1\r\nHost: " + self.target
|
||||
@@ -153,7 +169,7 @@ class Session:
|
||||
for field, value in headers.iteritems():
|
||||
request += "\r\n"+field+": "+value
|
||||
request += "\r\n\r\n"
|
||||
self.client.send(request);
|
||||
return self.send_err_check(request)
|
||||
|
||||
def send_put(self, path, data, headers=None):
|
||||
request = "PUT " + path + " HTTP/1.1\r\nHost: " + self.target
|
||||
@@ -161,8 +177,7 @@ class Session:
|
||||
for field, value in headers.iteritems():
|
||||
request += "\r\n"+field+": "+value
|
||||
request += "\r\nContent-Length: " + str(len(data)) +"\r\n\r\n"
|
||||
self.client.send(request)
|
||||
self.client.send(data)
|
||||
return self.send_err_check(request, data)
|
||||
|
||||
def send_post(self, path, data, headers=None):
|
||||
request = "POST " + path + " HTTP/1.1\r\nHost: " + self.target
|
||||
@@ -170,82 +185,95 @@ class Session:
|
||||
for field, value in headers.iteritems():
|
||||
request += "\r\n"+field+": "+value
|
||||
request += "\r\nContent-Length: " + str(len(data)) +"\r\n\r\n"
|
||||
self.client.send(request)
|
||||
self.client.send(data)
|
||||
return self.send_err_check(request, data)
|
||||
|
||||
def read_resp_hdrs(self):
|
||||
state = 'nothing'
|
||||
resp_read = ''
|
||||
while True:
|
||||
char = self.client.recv(1)
|
||||
if char == '\r' and state == 'nothing':
|
||||
state = 'first_cr'
|
||||
elif char == '\n' and state == 'first_cr':
|
||||
state = 'first_lf'
|
||||
elif char == '\r' and state == 'first_lf':
|
||||
state = 'second_cr'
|
||||
elif char == '\n' and state == 'second_cr':
|
||||
state = 'second_lf'
|
||||
else:
|
||||
state = 'nothing'
|
||||
resp_read += char
|
||||
if state == 'second_lf':
|
||||
break;
|
||||
# Handle first line
|
||||
line_hdrs = resp_read.splitlines()
|
||||
line_comp = line_hdrs[0].split()
|
||||
self.status = line_comp[1]
|
||||
del line_hdrs[0]
|
||||
self.encoding = ''
|
||||
self.content_type = ''
|
||||
headers = dict()
|
||||
# Process other headers
|
||||
for h in range(len(line_hdrs)):
|
||||
line_comp = line_hdrs[h].split(':')
|
||||
if line_comp[0] == 'Content-Length':
|
||||
self.content_len = int(line_comp[1])
|
||||
if line_comp[0] == 'Content-Type':
|
||||
self.content_type = line_comp[1].lstrip()
|
||||
if line_comp[0] == 'Transfer-Encoding':
|
||||
self.encoding = line_comp[1].lstrip()
|
||||
if len(line_comp) == 2:
|
||||
headers[line_comp[0]] = line_comp[1].lstrip()
|
||||
return headers
|
||||
try:
|
||||
state = 'nothing'
|
||||
resp_read = ''
|
||||
while True:
|
||||
char = self.client.recv(1)
|
||||
if char == '\r' and state == 'nothing':
|
||||
state = 'first_cr'
|
||||
elif char == '\n' and state == 'first_cr':
|
||||
state = 'first_lf'
|
||||
elif char == '\r' and state == 'first_lf':
|
||||
state = 'second_cr'
|
||||
elif char == '\n' and state == 'second_cr':
|
||||
state = 'second_lf'
|
||||
else:
|
||||
state = 'nothing'
|
||||
resp_read += char
|
||||
if state == 'second_lf':
|
||||
break
|
||||
# Handle first line
|
||||
line_hdrs = resp_read.splitlines()
|
||||
line_comp = line_hdrs[0].split()
|
||||
self.status = line_comp[1]
|
||||
del line_hdrs[0]
|
||||
self.encoding = ''
|
||||
self.content_type = ''
|
||||
headers = dict()
|
||||
# Process other headers
|
||||
for h in range(len(line_hdrs)):
|
||||
line_comp = line_hdrs[h].split(':')
|
||||
if line_comp[0] == 'Content-Length':
|
||||
self.content_len = int(line_comp[1])
|
||||
if line_comp[0] == 'Content-Type':
|
||||
self.content_type = line_comp[1].lstrip()
|
||||
if line_comp[0] == 'Transfer-Encoding':
|
||||
self.encoding = line_comp[1].lstrip()
|
||||
if len(line_comp) == 2:
|
||||
headers[line_comp[0]] = line_comp[1].lstrip()
|
||||
return headers
|
||||
except socket.error as err:
|
||||
self.client.close()
|
||||
print "Socket Error in recv :", err
|
||||
return None
|
||||
|
||||
def read_resp_data(self):
|
||||
read_data = ''
|
||||
if self.encoding != 'chunked':
|
||||
while len(read_data) != self.content_len:
|
||||
read_data += self.client.recv(self.content_len)
|
||||
self.content_len = 0
|
||||
else:
|
||||
chunk_data_buf = ''
|
||||
while (True):
|
||||
# Read one character into temp buffer
|
||||
read_ch = self.client.recv(1)
|
||||
# Check CRLF
|
||||
if (read_ch == '\r'):
|
||||
try:
|
||||
read_data = ''
|
||||
if self.encoding != 'chunked':
|
||||
while len(read_data) != self.content_len:
|
||||
read_data += self.client.recv(self.content_len)
|
||||
else:
|
||||
chunk_data_buf = ''
|
||||
while (True):
|
||||
# Read one character into temp buffer
|
||||
read_ch = self.client.recv(1)
|
||||
if (read_ch == '\n'):
|
||||
# If CRLF decode length of chunk
|
||||
chunk_len = int(chunk_data_buf, 16)
|
||||
# Keep adding to contents
|
||||
self.content_len += chunk_len
|
||||
read_data += self.client.recv(chunk_len)
|
||||
chunk_data_buf = ''
|
||||
# Fetch remaining CRLF
|
||||
if self.client.recv(2) != "\r\n":
|
||||
# Error in packet
|
||||
return None
|
||||
if not chunk_len:
|
||||
# If last chunk
|
||||
break
|
||||
continue
|
||||
chunk_data_buf += '\r'
|
||||
# If not CRLF continue appending
|
||||
# character to chunked data buffer
|
||||
chunk_data_buf += read_ch
|
||||
return read_data
|
||||
# Check CRLF
|
||||
if (read_ch == '\r'):
|
||||
read_ch = self.client.recv(1)
|
||||
if (read_ch == '\n'):
|
||||
# If CRLF decode length of chunk
|
||||
chunk_len = int(chunk_data_buf, 16)
|
||||
# Keep adding to contents
|
||||
self.content_len += chunk_len
|
||||
rem_len = chunk_len
|
||||
while (rem_len):
|
||||
new_data = self.client.recv(rem_len)
|
||||
read_data += new_data
|
||||
rem_len -= len(new_data)
|
||||
chunk_data_buf = ''
|
||||
# Fetch remaining CRLF
|
||||
if self.client.recv(2) != "\r\n":
|
||||
# Error in packet
|
||||
print "Error in chunked data"
|
||||
return None
|
||||
if not chunk_len:
|
||||
# If last chunk
|
||||
break
|
||||
continue
|
||||
chunk_data_buf += '\r'
|
||||
# If not CRLF continue appending
|
||||
# character to chunked data buffer
|
||||
chunk_data_buf += read_ch
|
||||
return read_data
|
||||
except socket.error as err:
|
||||
self.client.close()
|
||||
print "Socket Error in recv :", err
|
||||
return None
|
||||
|
||||
def close(self):
|
||||
self.client.close()
|
||||
@@ -259,11 +287,12 @@ def test_val(text, expected, received):
|
||||
return False
|
||||
return True
|
||||
|
||||
class myThread (threading.Thread):
|
||||
class adder_thread (threading.Thread):
|
||||
def __init__(self, id, dut, port):
|
||||
threading.Thread.__init__(self)
|
||||
self.id = id
|
||||
self.dut = dut
|
||||
self.depth = 3
|
||||
self.session = Session(dut, port)
|
||||
|
||||
def run(self):
|
||||
@@ -272,24 +301,21 @@ class myThread (threading.Thread):
|
||||
# Pipeline 3 requests
|
||||
if (_verbose_):
|
||||
print " Thread: Using adder start " + str(self.id)
|
||||
self.session.send_post('/adder', str(self.id));
|
||||
time.sleep(1)
|
||||
self.session.send_post('/adder', str(self.id));
|
||||
time.sleep(1)
|
||||
self.session.send_post('/adder', str(self.id));
|
||||
time.sleep(1)
|
||||
|
||||
self.session.read_resp_hdrs()
|
||||
self.response.append(self.session.read_resp_data())
|
||||
self.session.read_resp_hdrs()
|
||||
self.response.append(self.session.read_resp_data())
|
||||
self.session.read_resp_hdrs()
|
||||
self.response.append(self.session.read_resp_data())
|
||||
for _ in range(self.depth):
|
||||
self.session.send_post('/adder', str(self.id))
|
||||
time.sleep(2)
|
||||
|
||||
for _ in range(self.depth):
|
||||
self.session.read_resp_hdrs()
|
||||
self.response.append(self.session.read_resp_data())
|
||||
|
||||
def adder_result(self):
|
||||
if len(self.response) != self.depth:
|
||||
print "Error : missing response packets"
|
||||
return False
|
||||
for i in range(len(self.response)):
|
||||
# print self.response[i]
|
||||
if not test_val("thread" + str(self.id) + ": response[" + str(i) + "]",
|
||||
if not test_val("Thread" + str(self.id) + " response[" + str(i) + "]",
|
||||
str(self.id * (i + 1)), str(self.response[i])):
|
||||
return False
|
||||
return True
|
||||
@@ -300,103 +326,145 @@ class myThread (threading.Thread):
|
||||
def get_hello(dut, port):
|
||||
# GET /hello should return 'Hello World!'
|
||||
print "[test] GET /hello returns 'Hello World!' =>",
|
||||
r = requests.get("http://" + dut + ":" + port + "/hello")
|
||||
if not test_val("status_code", 200, r.status_code):
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("GET", "/hello")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 200, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
if not test_val("data", "Hello World!", r.text):
|
||||
if not test_val("data", "Hello World!", resp.read()):
|
||||
conn.close()
|
||||
return False
|
||||
if not test_val("data", "application/json", r.headers['Content-Type']):
|
||||
return False
|
||||
print "Success"
|
||||
return True
|
||||
|
||||
def post_hello(dut, port):
|
||||
# PUT /hello returns 405'
|
||||
print "[test] PUT /hello returns 405' =>",
|
||||
r = requests.put("http://" + dut + ":" + port + "/hello", data="Hello")
|
||||
if not test_val("status_code", 405, r.status_code):
|
||||
if not test_val("data", "application/json", resp.getheader('Content-Type')):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def put_hello(dut, port):
|
||||
# POST /hello returns 405'
|
||||
print "[test] POST /hello returns 404' =>",
|
||||
r = requests.post("http://" + dut + ":" + port + "/hello", data="Hello")
|
||||
if not test_val("status_code", 405, r.status_code):
|
||||
# PUT /hello returns 405'
|
||||
print "[test] PUT /hello returns 405' =>",
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("PUT", "/hello", "Hello")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 405, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def post_hello(dut, port):
|
||||
# POST /hello returns 405'
|
||||
print "[test] POST /hello returns 404' =>",
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("POST", "/hello", "Hello")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 405, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def post_echo(dut, port):
|
||||
# POST /echo echoes data'
|
||||
print "[test] POST /echo echoes data' =>",
|
||||
r = requests.post("http://" + dut + ":" + port + "/echo", data="Hello")
|
||||
if not test_val("status_code", 200, r.status_code):
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("POST", "/echo", "Hello")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 200, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
if not test_val("data", "Hello", r.text):
|
||||
if not test_val("data", "Hello", resp.read()):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def put_echo(dut, port):
|
||||
# POST /echo echoes data'
|
||||
# PUT /echo echoes data'
|
||||
print "[test] PUT /echo echoes data' =>",
|
||||
r = requests.put("http://" + dut + ":" + port + "/echo", data="Hello")
|
||||
if not test_val("status_code", 200, r.status_code):
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("PUT", "/echo", "Hello")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 200, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
if not test_val("data", "Hello", r.text):
|
||||
if not test_val("data", "Hello", resp.read()):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def get_echo(dut, port):
|
||||
# GET /echo returns 404'
|
||||
print "[test] GET /echo returns 405' =>",
|
||||
r = requests.get("http://" + dut + ":" + port + "/echo")
|
||||
if not test_val("status_code", 405, r.status_code):
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("GET", "/echo")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 405, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def get_hello_type(dut, port):
|
||||
# GET /hello/type_html returns text/html as Content-Type'
|
||||
print "[test] GET /hello/type_html has Content-Type of text/html =>",
|
||||
r = requests.get("http://" + dut + ":" + port + "/hello/type_html")
|
||||
if not test_val("status_code", 200, r.status_code):
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("GET", "/hello/type_html")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 200, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
if not test_val("data", "Hello World!", r.text):
|
||||
if not test_val("data", "Hello World!", resp.read()):
|
||||
conn.close()
|
||||
return False
|
||||
if not test_val("data", "text/html", r.headers['Content-Type']):
|
||||
if not test_val("data", "text/html", resp.getheader('Content-Type')):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def get_hello_status(dut, port):
|
||||
# GET /hello/status_500 returns status 500'
|
||||
print "[test] GET /hello/status_500 returns status 500 =>",
|
||||
r = requests.get("http://" + dut + ":" + port + "/hello/status_500")
|
||||
if not test_val("status_code", 500, r.status_code):
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("GET", "/hello/status_500")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 500, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def get_false_uri(dut, port):
|
||||
# GET /false_uri returns status 404'
|
||||
print "[test] GET /false_uri returns status 404 =>",
|
||||
r = requests.get("http://" + dut + ":" + port + "/false_uri")
|
||||
if not test_val("status_code", 404, r.status_code):
|
||||
conn = httplib.HTTPConnection(dut, int(port))
|
||||
conn.request("GET", "/false_uri")
|
||||
resp = conn.getresponse()
|
||||
if not test_val("status_code", 404, resp.status):
|
||||
conn.close()
|
||||
return False
|
||||
print "Success"
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
def parallel_sessions_adder(dut, port, max_sessions):
|
||||
# POSTs on /adder in parallel sessions
|
||||
print "[test] POST {pipelined} on /adder in " + str(max_sessions) + " sessions =>",
|
||||
t = []
|
||||
# Create all sessions
|
||||
# Create all sessions
|
||||
for i in xrange(max_sessions):
|
||||
t.append(myThread(i * 2, dut, port))
|
||||
t.append(adder_thread(i, dut, port))
|
||||
|
||||
for i in xrange(len(t)):
|
||||
t[i].start()
|
||||
@@ -406,9 +474,8 @@ def parallel_sessions_adder(dut, port, max_sessions):
|
||||
|
||||
res = True
|
||||
for i in xrange(len(t)):
|
||||
if not t[i].adder_result():
|
||||
if not test_val("Thread" + str(i) + "Failed", "True", "False"):
|
||||
res = False
|
||||
if not test_val("Thread" + str(i) + " Failed", t[i].adder_result(), True):
|
||||
res = False
|
||||
t[i].close()
|
||||
if (res):
|
||||
print "Success"
|
||||
@@ -436,32 +503,30 @@ def async_response_test(dut, port):
|
||||
def leftover_data_test(dut, port):
|
||||
# Leftover data in POST is purged (valid and invalid URIs)
|
||||
print "[test] Leftover data in POST is purged (valid and invalid URIs) =>",
|
||||
s = Session(dut, port)
|
||||
s = httplib.HTTPConnection(dut + ":" + port)
|
||||
|
||||
s.send_post('/leftover_data',
|
||||
"abcdefghijklmnopqrstuvwxyz\r\nabcdefghijklmnopqrstuvwxyz")
|
||||
s.read_resp_hdrs()
|
||||
if not test_val("Partial data", "abcdefghij", s.read_resp_data()):
|
||||
s.request("POST", url='/leftover_data', body="abcdefghijklmnopqrstuvwxyz\r\nabcdefghijklmnopqrstuvwxyz")
|
||||
resp = s.getresponse()
|
||||
if not test_val("Partial data", "abcdefghij", resp.read()):
|
||||
s.close()
|
||||
return False
|
||||
|
||||
s.send_get('/hello')
|
||||
s.read_resp_hdrs()
|
||||
if not test_val("Hello World Data", "Hello World!", s.read_resp_data()):
|
||||
s.request("GET", url='/hello')
|
||||
resp = s.getresponse()
|
||||
if not test_val("Hello World Data", "Hello World!", resp.read()):
|
||||
s.close()
|
||||
return False
|
||||
|
||||
s.send_post('/false_uri',
|
||||
"abcdefghijklmnopqrstuvwxyz\r\nabcdefghijklmnopqrstuvwxyz")
|
||||
s.read_resp_hdrs()
|
||||
if not test_val("False URI Status", str(404), str(s.status)):
|
||||
s.request("POST", url='/false_uri', body="abcdefghijklmnopqrstuvwxyz\r\nabcdefghijklmnopqrstuvwxyz")
|
||||
resp = s.getresponse()
|
||||
if not test_val("False URI Status", str(404), str(resp.status)):
|
||||
s.close()
|
||||
return False
|
||||
s.read_resp_data()
|
||||
resp.read()
|
||||
|
||||
s.send_get('/hello')
|
||||
s.read_resp_hdrs()
|
||||
if not test_val("Hello World Data", "Hello World!", s.read_resp_data()):
|
||||
s.request("GET", url='/hello')
|
||||
resp = s.getresponse()
|
||||
if not test_val("Hello World Data", "Hello World!", resp.read()):
|
||||
s.close()
|
||||
return False
|
||||
|
||||
@@ -469,122 +534,86 @@ def leftover_data_test(dut, port):
|
||||
print "Success"
|
||||
return True
|
||||
|
||||
def timeout_handler(signum, frame):
|
||||
raise Exception("Timeout")
|
||||
|
||||
def spillover_session(dut, port, max):
|
||||
# Session max_sessions + 1 is rejected
|
||||
print "[test] Session max_sessions (" + str(max) + ") + 1 is rejected =>",
|
||||
def spillover_session(dut, port, max_sess):
|
||||
# Session max_sess_sessions + 1 is rejected
|
||||
print "[test] Session max_sess_sessions (" + str(max_sess) + ") + 1 is rejected =>",
|
||||
s = []
|
||||
# Register a timeout callback
|
||||
signal.signal(signal.SIGALRM, timeout_handler)
|
||||
for i in xrange(max + 1):
|
||||
_verbose_ = True
|
||||
for i in xrange(max_sess + 1):
|
||||
if (_verbose_):
|
||||
print "Executing " + str(i)
|
||||
a = Session(dut, port)
|
||||
a.send_get('/hello')
|
||||
|
||||
try:
|
||||
# Check for response timeout
|
||||
signal.alarm(5)
|
||||
a.read_resp_hdrs()
|
||||
a.read_resp_data()
|
||||
signal.alarm(0)
|
||||
|
||||
# Control reaches here only if connection was established
|
||||
a = httplib.HTTPConnection(dut + ":" + port)
|
||||
a.request("GET", url='/hello')
|
||||
resp = a.getresponse()
|
||||
if not test_val("Connection " + str(i), "Hello World!", resp.read()):
|
||||
a.close()
|
||||
break
|
||||
s.append(a)
|
||||
except Exception, msg:
|
||||
except:
|
||||
if (_verbose_):
|
||||
print str(msg) + ": Connection " + str(i) + " rejected"
|
||||
print "Connection " + str(i) + " rejected"
|
||||
a.close()
|
||||
break
|
||||
|
||||
# Close open connections
|
||||
for a in s:
|
||||
a.close()
|
||||
|
||||
# Check if number of connections is equal to max
|
||||
print ["Fail","Success"][len(s) == max]
|
||||
return (len(s) == max)
|
||||
# Check if number of connections is equal to max_sess
|
||||
print ["Fail","Success"][len(s) == max_sess]
|
||||
return (len(s) == max_sess)
|
||||
|
||||
def recv_timeout_test(dut, port):
|
||||
print "[test] Timeout occurs if partial packet sent =>",
|
||||
signal.signal(signal.SIGALRM, timeout_handler)
|
||||
s = Session(dut, port)
|
||||
s.client.send("GE")
|
||||
try:
|
||||
signal.alarm(15)
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
signal.alarm(0)
|
||||
if not test_val("Request Timeout", "Server closed this connection", resp):
|
||||
s.close()
|
||||
return False
|
||||
except:
|
||||
s.close()
|
||||
return False
|
||||
s.close()
|
||||
print "Success"
|
||||
return True
|
||||
|
||||
def pipeline_test(dut, port, max_sess):
|
||||
print "[test] Pipelining test =>",
|
||||
s = [Session(dut, port) for _ in range(max_sess)]
|
||||
path = "/echo"
|
||||
pipeline_depth = 10
|
||||
header = "POST " + path + " HTTP/1.1\r\nHost: " + dut + "\r\nContent-Length: "
|
||||
s[0].client.send(header)
|
||||
for i in range(1, max_sess):
|
||||
for j in range(pipeline_depth):
|
||||
data = str(i) + ":" + str(j)
|
||||
request = header + str(len(data)) + "\r\n\r\n" + data
|
||||
s[i].client.send(request)
|
||||
|
||||
s[0].client.send(str(len("0:0")) + "\r\n\r\n" + "0:0")
|
||||
for j in range(1, pipeline_depth):
|
||||
data = "0:" + str(j)
|
||||
request = header + str(len(data)) + "\r\n\r\n" + data
|
||||
s[0].client.send(request)
|
||||
|
||||
res = True
|
||||
for i in range(max_sess):
|
||||
#time.sleep(1)
|
||||
for j in range(pipeline_depth):
|
||||
s[i].read_resp_hdrs()
|
||||
echo_data = s[i].read_resp_data()
|
||||
if (_verbose_):
|
||||
print "[" + str(i) + "][" + str(j) + "] = " + echo_data
|
||||
if not test_val("Echo Data", str(i) + ":" + str(j), echo_data):
|
||||
res = False
|
||||
s[i].close()
|
||||
|
||||
#for i in range(max_sess):
|
||||
#s[i].close()
|
||||
|
||||
if (res):
|
||||
print "Success"
|
||||
return res
|
||||
|
||||
def packet_size_limit_test(dut, port, test_size):
|
||||
print "[test] LWIP send size limit test =>",
|
||||
s = Session(dut, port)
|
||||
random_data = ''.join(string.printable[random.randint(0,len(string.printable))-1] for _ in range(test_size))
|
||||
path = "/echo"
|
||||
s.send_post(path, random_data)
|
||||
s.client.sendall("GE")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
result = (resp == random_data)
|
||||
if not result:
|
||||
test_val("Data size", str(len(random_data)), str(len(resp)))
|
||||
if not test_val("Request Timeout", "Server closed this connection", resp):
|
||||
s.close()
|
||||
return False
|
||||
print "Success"
|
||||
s.close()
|
||||
print "Success"
|
||||
return True
|
||||
|
||||
def packet_size_limit_test(dut, port, test_size):
|
||||
print "[test] send size limit test =>",
|
||||
retry = 5
|
||||
while (retry):
|
||||
retry -= 1
|
||||
print "data size = ", test_size
|
||||
s = httplib.HTTPConnection(dut + ":" + port)
|
||||
random_data = ''.join(string.printable[random.randint(0,len(string.printable))-1] for _ in range(test_size))
|
||||
path = "/echo"
|
||||
s.request("POST", url=path, body=random_data)
|
||||
resp = s.getresponse()
|
||||
if not test_val("Error", "200", str(resp.status)):
|
||||
if test_val("Error", "408", str(resp.status)):
|
||||
print "Data too large to be allocated"
|
||||
test_size = test_size/10
|
||||
else:
|
||||
print "Unexpected error"
|
||||
s.close()
|
||||
print "Retry..."
|
||||
continue
|
||||
resp = resp.read()
|
||||
result = (resp == random_data)
|
||||
if not result:
|
||||
test_val("Data size", str(len(random_data)), str(len(resp)))
|
||||
s.close()
|
||||
print "Retry..."
|
||||
continue
|
||||
s.close()
|
||||
print "Success"
|
||||
return True
|
||||
print "Failed"
|
||||
return False
|
||||
|
||||
def code_500_server_error_test(dut, port):
|
||||
print "[test] 500 Server Error test =>",
|
||||
s = Session(dut, port)
|
||||
s.client.send("abcdefgh\0")
|
||||
s.client.sendall("abcdefgh\0")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
# Presently server sends back 400 Bad Request
|
||||
@@ -602,7 +631,7 @@ def code_501_method_not_impl(dut, port):
|
||||
print "[test] 501 Method Not Implemented =>",
|
||||
s = Session(dut, port)
|
||||
path = "/hello"
|
||||
s.client.send("ABC " + path + " HTTP/1.1\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.client.sendall("ABC " + path + " HTTP/1.1\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
# Presently server sends back 400 Bad Request
|
||||
@@ -620,7 +649,7 @@ def code_505_version_not_supported(dut, port):
|
||||
print "[test] 505 Version Not Supported =>",
|
||||
s = Session(dut, port)
|
||||
path = "/hello"
|
||||
s.client.send("GET " + path + " HTTP/2.0\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.client.sendall("GET " + path + " HTTP/2.0\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
if not test_val("Server Error", "505", s.status):
|
||||
@@ -634,7 +663,7 @@ def code_400_bad_request(dut, port):
|
||||
print "[test] 400 Bad Request =>",
|
||||
s = Session(dut, port)
|
||||
path = "/hello"
|
||||
s.client.send("XYZ " + path + " HTTP/1.1\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.client.sendall("XYZ " + path + " HTTP/1.1\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
if not test_val("Client Error", "400", s.status):
|
||||
@@ -648,7 +677,7 @@ def code_404_not_found(dut, port):
|
||||
print "[test] 404 Not Found =>",
|
||||
s = Session(dut, port)
|
||||
path = "/dummy"
|
||||
s.client.send("GET " + path + " HTTP/1.1\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.client.sendall("GET " + path + " HTTP/1.1\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
if not test_val("Client Error", "404", s.status):
|
||||
@@ -662,7 +691,7 @@ def code_405_method_not_allowed(dut, port):
|
||||
print "[test] 405 Method Not Allowed =>",
|
||||
s = Session(dut, port)
|
||||
path = "/hello"
|
||||
s.client.send("POST " + path + " HTTP/1.1\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.client.sendall("POST " + path + " HTTP/1.1\r\nHost: " + dut + "\r\n\r\n")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
if not test_val("Client Error", "405", s.status):
|
||||
@@ -674,18 +703,11 @@ def code_405_method_not_allowed(dut, port):
|
||||
|
||||
def code_408_req_timeout(dut, port):
|
||||
print "[test] 408 Request Timeout =>",
|
||||
signal.signal(signal.SIGALRM, timeout_handler)
|
||||
s = Session(dut, port)
|
||||
s.client.send("POST /echo HTTP/1.1\r\nHost: " + dut + "\r\nContent-Length: 10\r\n\r\nABCD")
|
||||
try:
|
||||
signal.alarm(15)
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
signal.alarm(0)
|
||||
if not test_val("Client Error", "408", s.status):
|
||||
s.close()
|
||||
return False
|
||||
except:
|
||||
s.client.sendall("POST /echo HTTP/1.1\r\nHost: " + dut + "\r\nContent-Length: 10\r\n\r\nABCD")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
if not test_val("Client Error", "408", s.status):
|
||||
s.close()
|
||||
return False
|
||||
s.close()
|
||||
@@ -696,7 +718,7 @@ def code_411_length_required(dut, port):
|
||||
print "[test] 411 Length Required =>",
|
||||
s = Session(dut, port)
|
||||
path = "/echo"
|
||||
s.client.send("POST " + path + " HTTP/1.1\r\nHost: " + dut + "\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n\r\n")
|
||||
s.client.sendall("POST " + path + " HTTP/1.1\r\nHost: " + dut + "\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n\r\n")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
# Presently server sends back 400 Bad Request
|
||||
@@ -715,11 +737,11 @@ def send_getx_uri_len(dut, port, length):
|
||||
method = "GET "
|
||||
version = " HTTP/1.1\r\n"
|
||||
path = "/"+"x"*(length - len(method) - len(version) - len("/"))
|
||||
s.client.send(method)
|
||||
s.client.sendall(method)
|
||||
time.sleep(1)
|
||||
s.client.send(path)
|
||||
s.client.sendall(path)
|
||||
time.sleep(1)
|
||||
s.client.send(version + "Host: " + dut + "\r\n\r\n")
|
||||
s.client.sendall(version + "Host: " + dut + "\r\n\r\n")
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
s.close()
|
||||
@@ -743,9 +765,9 @@ def send_postx_hdr_len(dut, port, length):
|
||||
custom_hdr_field = "\r\nCustom: "
|
||||
custom_hdr_val = "x"*(length - len(host) - len(custom_hdr_field) - len("\r\n\r\n") + len("0"))
|
||||
request = "POST " + path + " HTTP/1.1\r\n" + host + custom_hdr_field + custom_hdr_val + "\r\n\r\n"
|
||||
s.client.send(request[:length/2])
|
||||
s.client.sendall(request[:length/2])
|
||||
time.sleep(1)
|
||||
s.client.send(request[length/2:])
|
||||
s.client.sendall(request[length/2:])
|
||||
hdr = s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
s.close()
|
||||
@@ -768,7 +790,7 @@ def test_upgrade_not_supported(dut, port):
|
||||
print "[test] Upgrade Not Supported =>",
|
||||
s = Session(dut, port)
|
||||
path = "/hello"
|
||||
s.client.send("OPTIONS * HTTP/1.1\r\nHost:" + dut + "\r\nUpgrade: TLS/1.0\r\nConnection: Upgrade\r\n\r\n");
|
||||
s.client.sendall("OPTIONS * HTTP/1.1\r\nHost:" + dut + "\r\nUpgrade: TLS/1.0\r\nConnection: Upgrade\r\n\r\n");
|
||||
s.read_resp_hdrs()
|
||||
resp = s.read_resp_data()
|
||||
if not test_val("Client Error", "200", s.status):
|
||||
@@ -831,10 +853,6 @@ if __name__ == '__main__':
|
||||
async_response_test(dut, port)
|
||||
spillover_session(dut, port, max_sessions)
|
||||
recv_timeout_test(dut, port)
|
||||
|
||||
# May timeout in case requests are sent slower than responses are read.
|
||||
# Instead use httperf stress test
|
||||
pipeline_test(dut, port, max_sessions)
|
||||
packet_size_limit_test(dut, port, 50*1024)
|
||||
get_hello(dut, port)
|
||||
|
||||
|
Reference in New Issue
Block a user