trafficserver-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From shinr...@apache.org
Subject [trafficserver] branch master updated: Traffic-replay updated
Date Fri, 12 Jan 2018 22:07:23 GMT
This is an automated email from the ASF dual-hosted git repository.

shinrich pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 97f67ef  Traffic-replay updated
97f67ef is described below

commit 97f67ef39ea10a9ac29ff62a541d1a120293ff87
Author: Jesse Zhang <macisasandwich@gmail.com>
AuthorDate: Fri Jan 12 15:24:00 2018 -0600

    Traffic-replay updated
    
    Format change for SSL and nonSSL URL paths
    
    Ignoring connection header since ATS modifies it
    
    allows custom PULL http method
    
    Cleaned up traffic-replay verification logic
    
    Added in content-length vs actual body length verification
    
    Integrate SSLReplay to use the same logic as NonSSLReplay
    Removed unnecessary functions
    Updated h2replay
---
 tests/gold_tests/autest-site/microserver.test.ext  | 48 ++++++++++----------
 tests/tools/lib/result.py                          | 37 +++++++++++----
 tests/tools/microServer/uWServer.py                | 39 ++++++++--------
 tests/tools/sessionvalidation/sessionvalidation.py | 11 +++--
 tests/tools/traffic-replay/NonSSL.py               | 53 ++++++++++++++--------
 tests/tools/traffic-replay/SSLReplay.py            | 50 +++++++++++---------
 tests/tools/traffic-replay/Scheduler.py            | 45 ++++++++++++++----
 tests/tools/traffic-replay/__main__.py             |  3 +-
 tests/tools/traffic-replay/extractHeader.py        |  6 ++-
 tests/tools/traffic-replay/h2Replay.py             | 26 ++++-------
 10 files changed, 194 insertions(+), 124 deletions(-)

diff --git a/tests/gold_tests/autest-site/microserver.test.ext b/tests/gold_tests/autest-site/microserver.test.ext
index 4ab6783..f4a2685 100644
--- a/tests/gold_tests/autest-site/microserver.test.ext
+++ b/tests/gold_tests/autest-site/microserver.test.ext
@@ -49,54 +49,57 @@ def addResponse(self, filename, testName, request_header, response_header):
     self.Setup.CopyAs(absFilepath, self.Variables.DataDir)
     return
 
+
 def getHeaderFieldVal(request_header, field):
     requestline = request_header["headers"].split("\r\n")[0]
     requestline = requestline.split(" ")[1]
-    field = field+':'
-    valField = request_header["headers"].split(field,1);
-    val=""
-    if len(valField)>1:
-            field_v = valField[1].split("\r\n",1)
-            if len(field_v)>0:
-                val = field_v[0].strip()
+    field = field + ':'
+    valField = request_header["headers"].split(field, 1)
+    val = ""
+    if len(valField) > 1:
+        field_v = valField[1].split("\r\n", 1)
+        if len(field_v) > 0:
+            val = field_v[0].strip()
     return val
 
 # addResponse adds customized response with respect to request_header. request_header and
response_header are both dictionaries
+
+
 def addResponse(self, filename, request_header, response_header):
     requestline = request_header["headers"].split("\r\n")[0]
     host_ = ""
     path_ = ""
     if requestline:
         url_part = requestline.split(" ")
-        if len(url_part)>1:
+        if len(url_part) > 1:
             if url_part[1].startswith("http"):
-                path_ = url_part[1].split("/",2)[2]
-                host_,path_ = path_.split("/",1)
+                path_ = url_part[1].split("/", 2)[2]
+                host_, path_ = path_.split("/", 1)
             else:
-                path_ = url_part[1].split("/",1)[1]
+                path_ = url_part[1].split("/", 1)[1]
 
     kpath = ""
     #print("Format of lookup key",self.Variables.lookup_key)
-    
+
     argsList = []
     keyslist = self.Variables.lookup_key.split("}")
     for keystr in keyslist:
         if keystr == '{PATH':
-            kpath = kpath+path_
+            kpath = kpath + path_
             continue
         if keystr == '{HOST':
             kpath = kpath + host_
             continue
-        if keystr == '': #empty
+        if keystr == '':  # empty
             continue
-        stringk = keystr.replace("{%","")
+        stringk = keystr.replace("{%", "")
         argsList.append(stringk)
     KeyList = []
     for argsL in argsList:
-        field_val = getHeaderFieldVal(request_header,argsL)
-        if field_val!=None:
+        field_val = getHeaderFieldVal(request_header, argsL)
+        if field_val != None:
             KeyList.append(field_val)
-    rl = "".join(KeyList)+kpath
+    rl = "".join(KeyList) + kpath
     txn = dict()
     txn["timestamp"] = ""
     txn["uuid"] = rl
@@ -141,7 +144,7 @@ def makeHeader(self, requestString, **kwargs):
     return headerStr
 
 
-def MakeOriginServer(obj, name, port=False, ip=False, delay=False, ssl=False, lookup_key='{PATH}',
options={}):
+def MakeOriginServer(obj, name, port=False, ip=False, delay=False, ssl=False, lookup_key='{PATH}',
mode='test', options={}):
     server_path = os.path.join(obj.Variables.AtsTestToolsDir, 'microServer/uWServer.py')
     data_dir = os.path.join(obj.RunDirectory, name)
     # create Process
@@ -152,8 +155,8 @@ def MakeOriginServer(obj, name, port=False, ip=False, delay=False, ssl=False,
lo
         ip = '127.0.0.1'
     if (delay == False):
         delay = 0
-    command = "python3 {0} --data-dir {1} --port {2} --ip_address {3} --delay {4} -m test
--ssl {5} --lookupkey '{6}'".format(
-        server_path, data_dir, port, ip, delay, ssl,lookup_key)
+    command = "python3 {0} --data-dir {1} --port {2} --ip_address {3} --delay {4} -m test
--ssl {5} --lookupkey '{6}' -m {7}".format(
+        server_path, data_dir, port, ip, delay, ssl, lookup_key, mode)
     for flag, value in options.items():
         command += " {} {}".format(flag, value)
 
@@ -163,7 +166,7 @@ def MakeOriginServer(obj, name, port=False, ip=False, delay=False, ssl=False,
lo
     p.Variables.DataDir = data_dir
     p.Variables.lookup_key = lookup_key
     p.Ready = When.PortOpen(port, ip)
-    p.ReturnCode = Any(None,0)
+    p.ReturnCode = Any(None, 0)
     AddMethodToInstance(p, addResponse)
     AddMethodToInstance(p, addTransactionToSession)
 
@@ -172,4 +175,3 @@ def MakeOriginServer(obj, name, port=False, ip=False, delay=False, ssl=False,
lo
 
 ExtendTest(MakeOriginServer, name="MakeOriginServer")
 ExtendTest(MakeOriginServer, name="MakeOrigin")
-
diff --git a/tests/tools/lib/result.py b/tests/tools/lib/result.py
index 664250d..7322e65 100644
--- a/tests/tools/lib/result.py
+++ b/tests/tools/lib/result.py
@@ -32,7 +32,8 @@ class TermColors:
     ENDC = '\033[0m'
 
 
-ignoredFields = {'age', 'set-cookie', 'server', 'date', 'last-modified', 'via', 'expires',
'cahe-control'}  # all lower case
+ignoredFields = {'age', 'set-cookie', 'server', 'date', 'last-modified',
+                 'via', 'expires', 'cache-control', 'vary', 'connection'}  # all lower case
 
 
 class Result(object):
@@ -57,27 +58,44 @@ class Result(object):
         else:
             return ""
 
-    def Compare(self, received_dict, expected_dict):
+    def Compare(self, received_dict, expected_dict, src=None):
         global ignoredFields
+        # print("RECEIVED")
+        # print(received_dict)
+        # print("RECIEVED CACHE CONTROL")
+        # print(received_dict['Cache-Control'.lower()])
+        # print("EXPECTED")
+        # print(expected_dict)
         try:
             for key in received_dict:
                 # print(key)
                 if key.lower() in expected_dict and key.lower() not in ignoredFields:
-                    #print("{0} ==? {1}".format(expected_dict[key.lower()],received_dict[key]))
-                    if received_dict[key] != expected_dict[key.lower()]:
+                    # print("{0} ==? {1}".format(expected_dict[key.lower()],received_dict[key]))
+                    if received_dict[key.lower()] != expected_dict[key.lower()]:
                         print("{0}Difference in the field \"{1}\": \n received:\n{2}\n expected:\n{3}{4}".format(
                             TermColors.FAIL, key, received_dict[key], expected_dict[key],
TermColors.ENDC))
                         return False
+                    if key.lower() == 'content-length' and self._received_response_body:
+                        if int(received_dict[key.lower()]) != len(self._received_response_body):
+                            print("{0}Difference in received content length and actual body
length \ncontent-length: {1} \nbody: {2}\nbody length: {3}{4}".format(
+                                TermColors.FAIL, received_dict[key.lower()], self._received_response_body,
len(
+                                    self._received_response_body, TermColors.ENDC)
+                            ))
+                            return False
 
         except:
             e = sys.exc_info()
-            print("Error in comparing key ", e, key, expected_dict[key.lower()], received_dict[key])
+            if src:
+                print("In {0}: ".format(src), end='')
+            print("Error in comparing key ", e, key, "expected", expected_dict[key.lower()],
"received", received_dict[key])
+            return False
         return True
 
-    def getResultString(self, received_dict, expected_dict, colorize=False):
+    def getResult(self, received_dict, expected_dict, colorize=False):
         global ignoredFields
+        retval = False
         ''' Return a nicely formatted result string with color if requested '''
-        if self.getResultBool() and self.Compare(received_dict, expected_dict):
+        if self.getResultBool() and self.Compare(received_dict, expected_dict, self._test_name):
             if colorize:
                 outstr = "{0}PASS{1}".format(
                     TermColors.OKGREEN, TermColors.ENDC)
@@ -85,6 +103,8 @@ class Result(object):
             else:
                 outstr = "PASS"
 
+            retval = True
+
         else:
             if colorize:
                 outstr = "{0}FAIL{1}: expected {2}, received {3}, session file: {4}".format(
@@ -93,6 +113,5 @@ class Result(object):
             else:
                 outstr = "FAIL: expected {0}, received {1}".format(
                     self._expected_response, self._received_response)
-                sys.exit(0)
 
-        return outstr
+        return (retval, outstr)
diff --git a/tests/tools/microServer/uWServer.py b/tests/tools/microServer/uWServer.py
index b646608..cceb226 100644
--- a/tests/tools/microServer/uWServer.py
+++ b/tests/tools/microServer/uWServer.py
@@ -52,7 +52,7 @@ import sessionvalidation.sessionvalidation as sv
 
 
 SERVER_PORT = 5005  # default port
-SERVER_DELAY = 0 # default delay
+SERVER_DELAY = 0  # default delay
 HTTP_VERSION = 'HTTP/1.1'
 G_replay_dict = {}
 
@@ -171,40 +171,39 @@ class MyHandler(BaseHTTPRequestHandler):
 
     def getLookupKey(self, requestline):
         global lookup_key_
-        kpath= ""
+        kpath = ""
         path = ""
         url_part = requestline.split(" ")
         if url_part:
             if url_part[1].startswith("http"):
-                path = url_part[1].split("/",2)[2]
-                host_, path = path.split("/",1)
+                path = url_part[1].split("/", 2)[2]
+                host_, path = path.split("/", 1)
             else:
-                path = url_part[1].split("/",1)[1]
+                path = url_part[1].split("/", 1)[1]
         argsList = []
         keyslist = lookup_key_.split("}")
-        for keystr in keyslist:            
+        for keystr in keyslist:
             if keystr == '{PATH':
-                kpath = kpath+path
-                continue # do not include path in the list of header fields
+                kpath = kpath + path
+                continue  # do not include path in the list of header fields
             if keystr == '{HOST':
-                kpath = kpath+host_
+                kpath = kpath + host_
                 continue
-            stringk = keystr.replace("{%","")
+            stringk = keystr.replace("{%", "")
             argsList.append(stringk)
         KeyList = []
         for argsL in argsList:
-            print("args",argsL,len(argsL))
-            if len(argsL)>0:
+            print("args", argsL, len(argsL))
+            if len(argsL) > 0:
                 val = self.headers.get(argsL)
                 if val:
-                    field_val,__ = cgi.parse_header(val)
+                    field_val, __ = cgi.parse_header(val)
                 else:
-                    field_val=None
-                if field_val!=None:
+                    field_val = None
+                if field_val != None:
                     KeyList.append(field_val)
-        key = "".join(KeyList)+kpath
-        print("lookup key",key, len(key))
-
+        key = "".join(KeyList) + kpath
+        print("lookup key", key, len(key))
 
         return key
 
@@ -447,7 +446,7 @@ class MyHandler(BaseHTTPRequestHandler):
                     header_parts = header.split(':', 1)
                     header_field = str(header_parts[0].strip())
                     header_field_val = str(header_parts[1].strip())
-                    #print("{0} === >{1}".format(header_field, header_field_val))
+                    # print("{0} === >{1}".format(header_field, header_field_val))
                     self.send_header(header_field, header_field_val)
                 # End for
                 if test_mode_enabled:
@@ -712,7 +711,7 @@ def main():
         else:
             server = ThreadingServer((options.ip_address, options.port), MyHandler, options)
         server.timeout = 5
-        print("started server")
+        print("started server on port {0}".format(options.port))
         server_thread = threading.Thread(target=server.serve_forever())
         server_thread.daemon = True
         server_thread.start()
diff --git a/tests/tools/sessionvalidation/sessionvalidation.py b/tests/tools/sessionvalidation/sessionvalidation.py
index e8ddc21..101e27b 100644
--- a/tests/tools/sessionvalidation/sessionvalidation.py
+++ b/tests/tools/sessionvalidation/sessionvalidation.py
@@ -24,6 +24,7 @@ import sessionvalidation.request as request
 import sessionvalidation.response as response
 
 valid_HTTP_request_methods = ['GET', 'POST', 'HEAD']
+G_CUSTOM_METHODS = False
 G_VERBOSE_LOG = True
 
 
@@ -155,6 +156,7 @@ class SessionValidator(object):
         retval = True
 
         #valid_HTTP_request_methods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'OPTIONS',
'CONNECT', 'PATCH']
+        custom_HTTP_request_methods = ['PULL']  # transaction monitor plugin for ATS may
have custom methods
         # we can later uncomment the previous line to support more HTTP methods
         valid_HTTP_versions = ['HTTP/1.0', 'HTTP/1.1', 'HTTP/2.0']
 
@@ -170,8 +172,9 @@ class SessionValidator(object):
                 _verbose_print("invalid transaction request timestamp")
                 retval = False
             elif txn_req.getHeaders().split()[0] not in valid_HTTP_request_methods:
-                _verbose_print("invalid HTTP method for transaction {0}".format(txn_req.getHeaders().split()[0]))
-                retval = False
+                if G_CUSTOM_METHODS and txn_req.getHeaders().split()[0] not in custom_HTTP_request_methods:
+                    _verbose_print("invalid HTTP method for transaction {0}".format(txn_req.getHeaders().split()[0]))
+                    retval = False
             elif not txn_req.getHeaders().endswith("\r\n\r\n"):
                 _verbose_print("transaction request headers didn't end with \\r\\n\\r\\n")
                 retval = False
@@ -250,8 +253,10 @@ class SessionValidator(object):
         ''' Returns an iterator of bad session filenames (iterator of strings) '''
         return iter(self._bad_sessions)
 
-    def __init__(self, json_log_dir):
+    def __init__(self, json_log_dir, allow_custom=False):
         global valid_HTTP_request_methods
+        global G_CUSTOM_METHODS
+        G_CUSTOM_METHODS = allow_custom
         self._json_log_dir = json_log_dir
         self._bad_sessions = list()   # list of filenames
         self._sessions = list()       # list of _good_ session objects
diff --git a/tests/tools/traffic-replay/NonSSL.py b/tests/tools/traffic-replay/NonSSL.py
index c7986ca..9685bf2 100644
--- a/tests/tools/traffic-replay/NonSSL.py
+++ b/tests/tools/traffic-replay/NonSSL.py
@@ -93,35 +93,48 @@ def txn_replay(session_filename, txn, proxy, result_queue, request_session):
             body = createDummyBodywithLength(nBytes)
         #print("request session is",id(request_session))
         if method == 'GET':
-            response = request_session.get('http://' + extractHeader.extract_host(txn_req_headers)
+ extractHeader.extract_GET_path(txn_req_headers),
-                                           headers=txn_req_headers_dict, stream=False, allow_redirects=False,
data=body)
-            if 'Content-Length' in response.headers:
-                content = response.raw
-                #print("len: {0} received {1}".format(response.headers['Content-Length'],content))
+            r1 = request_session.request('GET', extractHeader.extract_GET_path(
+                txn_req_headers), headers=txn_req_headers_dict, data=body)
+            responseHeaders = r1.headers
+            responseContent = r1.content  # byte array
+
+            #print("len: {0} received {1}".format(responseHeaders['Content-Length'], responseContent))
 
         elif method == 'POST':
-            response = request_session.post('http://' + extractHeader.extract_host(txn_req_headers)
+ extractHeader.extract_GET_path(txn_req_headers),
-                                            headers=txn_req_headers_dict, stream=False, data=body,
allow_redirects=False)
-
-            if 'Content-Length' in response.headers:
-                content = response.raw
-                # print("reading==========>>>>>>>>>>>>>.")
-                # print(content.data)
-                #print("len: {0} received {1}".format(response.headers['Content-Length'],content))
+            r1 = request_session.request('POST', extractHeader.extract_GET_path(
+                txn_req_headers), headers=txn_req_headers_dict, data=body)
+            responseHeaders = r1.headers
+            responseContent = r1.content
+
+            #print("len: {0} received {1}".format(responseHeaders['Content-Length'], responseContent))
         elif method == 'HEAD':
-            response = request_session.head('http://' + extractHeader.extract_host(txn_req_headers)
+ extractHeader.extract_GET_path(txn_req_headers),
-                                            headers=txn_req_headers_dict, stream=False)
+            r1 = request_session.request('HEAD', extractHeader.extract_GET_path(
+                txn_req_headers), headers=txn_req_headers_dict, data=body)
+            responseHeaders = r1.headers
+            responseContent = r1.content
 
-            #gzip_file = gzip.GzipFile(fileobj=content)
+            #gzip_file = gzip.GzipFile(fileobj=responseContent)
             #shutil.copyfileobj(gzip_file, f)
+
         expected = extractHeader.responseHeader_to_dict(resp.getHeaders())
+        # print("------------EXPECTED-----------")
         # print(expected)
+        # print("------------RESP--------------")
+        # print(responseHeaders)
+        # print()
+
         if mainProcess.verbose:
             expected_output_split = resp.getHeaders().split('\r\n')[0].split(' ', 2)
             expected_output = (int(expected_output_split[1]), str(expected_output_split[2]))
-            r = result.Result(session_filename, expected_output[0], response.status_code)
-            print(r.getResultString(response.headers, expected, colorize=True))
-            r.Compare(response.headers, expected)
+            r = result.Result(session_filename, expected_output[0], r1.status_code, responseContent)
+            b_res, res = r.getResult(responseHeaders, expected, colorize=True)
+            print(res)
+
+            if not b_res:
+                print("Received response")
+                print(responseHeaders)
+                print("Expected response")
+                print(expected)
         # result_queue.put(r)
     except UnicodeEncodeError as e:
         # these unicode errors are due to the interaction between Requests and our wiretrace
data.
@@ -132,7 +145,7 @@ def txn_replay(session_filename, txn, proxy, result_queue, request_session):
         print("ContentDecodingError", e)
     except:
         e = sys.exc_info()
-        print("ERROR in requests: ", e, response, session_filename)
+        print("ERROR in NonSSLReplay: ", e, response, session_filename)
 
 
 def session_replay(input, proxy, result_queue):
diff --git a/tests/tools/traffic-replay/SSLReplay.py b/tests/tools/traffic-replay/SSLReplay.py
index 88c8d26..cc0d94e 100644
--- a/tests/tools/traffic-replay/SSLReplay.py
+++ b/tests/tools/traffic-replay/SSLReplay.py
@@ -126,35 +126,41 @@ def txn_replay(session_filename, txn, proxy, result_queue, request_session):
             body = createDummyBodywithLength(nBytes)
         #print("request session is",id(request_session))
         if method == 'GET':
-            request_session.request('GET', 'https://' + extractHeader.extract_host(txn_req_headers)
+ extractHeader.extract_GET_path(txn_req_headers),
-                                    headers=txn_req_headers_dict, body=body)
-            r1 = request_session.getresponse()
-            responseHeaders = r1.getheaders()
-            responseContent = r1.read()
+            r1 = request_session.request('GET', extractHeader.extract_GET_path(
+                txn_req_headers), headers=txn_req_headers_dict, data=body)
+            responseHeaders = r1.headers
+            responseContent = r1.content  # byte array
 
         elif method == 'POST':
-            request_session.request('POST', 'https://' + extractHeader.extract_host(txn_req_headers)
+ extractHeader.extract_GET_path(txn_req_headers),
-                                    headers=txn_req_headers_dict, body=body)
-            r1 = request_session.getresponse()
-            responseHeaders = r1.getheaders()
-            responseContent = r1.read()
+            r1 = request_session.request('POST', extractHeader.extract_GET_path(
+                txn_req_headers), headers=txn_req_headers_dict, data=body)
+            responseHeaders = r1.headers
+            responseContent = r1.content
 
         elif method == 'HEAD':
-            request_session.request('HEAD', 'https://' + extractHeader.extract_host(txn_req_headers)
+ extractHeader.extract_GET_path(txn_req_headers),
-                                    headers=txn_req_headers_dict, body=body)
-            r1 = request_session.getresponse()
-            responseHeaders = r1.getheaders()
-            responseContent = r1.read()
-        for key, value in responseHeaders:
-            responseDict[key.lower()] = value
+            r1 = request_session.request('HEAD', extractHeader.extract_GET_path(
+                txn_req_headers), headers=txn_req_headers_dict, data=body)
+            responseHeaders = r1.headers
+            responseContent = r1.content
+
         expected = extractHeader.responseHeader_to_dict(resp.getHeaders())
-        # print(responseDict)
+        # print("------------EXPECTED-----------")
+        # print(expected)
+        # print("------------RESP--------------")
+        # print(responseHeaders)
+        # print()
         if mainProcess.verbose:
             expected_output_split = resp.getHeaders().split('\r\n')[0].split(' ', 2)
             expected_output = (int(expected_output_split[1]), str(expected_output_split[2]))
-            r = result.Result(session_filename, expected_output[0], r1.status)
-            print(r.getResultString(responseDict, expected, colorize=True))
-            r.Compare(responseDict, expected)
+            r = result.Result(session_filename, expected_output[0], r1.status_code, responseContent)
+            b_res, res = r.getResult(responseHeaders, expected, colorize=True)
+            print(res)
+
+            if not res:
+                print("Received response")
+                print(responseHeaders)
+                print("Expected response")
+                print(expected)
         # result_queue.put(r)
     except UnicodeEncodeError as e:
         # these unicode errors are due to the interaction between Requests and our wiretrace
data.
@@ -165,7 +171,7 @@ def txn_replay(session_filename, txn, proxy, result_queue, request_session):
         print("ContentDecodingError", e)
     except:
         e = sys.exc_info()
-        print("ERROR in requests: ", e, response, session_filename)
+        print("ERROR in SSLReplay: ", e, response, session_filename)
 
 
 def client_replay(input, proxy, result_queue, nThread):
diff --git a/tests/tools/traffic-replay/Scheduler.py b/tests/tools/traffic-replay/Scheduler.py
index f34ebfd..a1a4353 100644
--- a/tests/tools/traffic-replay/Scheduler.py
+++ b/tests/tools/traffic-replay/Scheduler.py
@@ -28,7 +28,7 @@ import time
 
 def LaunchWorkers(path, nProcess, proxy, replay_type, nThread):
     ms1 = time.time()
-    s = sv.SessionValidator(path)
+    s = sv.SessionValidator(path, allow_custom=True)
     sessions = s.getSessionList()
     sessions.sort(key=lambda session: session._timestamp)
     Processes = []
@@ -40,17 +40,44 @@ def LaunchWorkers(path, nProcess, proxy, replay_type, nThread):
     OutputQ = Queue()
     #======================================== Pre-load queues
     for session in sessions:
-        # if nProcess == 1:
-        #    QList[0].put(session)
-        # else:
-        QList[random.randint(0, nProcess - 1)].put(session)
-        # if QList[0].qsize() > 10 :
-        #    break
+        if replay_type == 'mixed':
+            if nProcess < 2:
+                raise ValueError("For mixed replay type, there should be at least 2 processes.")
+            # odd Qs for SSL sessions, even Qs for nonSSL sessions
+            num = random.randint(0, nProcess - 1)
+
+            # get the first transaction in each session, which is indictive if session is
over SSL or not
+            if "https" in session.returnFirstTransaction().getRequest().getHeaders():
+                # spin until we get an odd number
+                while num & 1 == 0:
+                    num = random.randint(0, nProcess - 1)
+            else:
+                # nonSSL sessions get put here into even Qs
+                while num & 1 == 1:
+                    num = random.randint(0, nProcess - 1)
+
+            QList[num].put(session)
+        else:
+            # if nProcess == 1:
+            #    QList[0].put(session)
+            # else:
+            QList[random.randint(0, nProcess - 1)].put(session)
+            # if QList[0].qsize() > 10 :
+            #    break
     #=============================================== Launch Processes
+    # for i in range(nProcess):
+    #     QList[i].put('STOP')
     for i in range(nProcess):
         QList[i].put('STOP')
-    for i in range(nProcess):
-        p = Process(target=WorkerTask.worker, args=[QList[i], OutputQ, proxy, replay_type,
nThread])
+
+        if replay_type == 'mixed':
+            if i & 1:  # odd/SSL
+                p = Process(target=WorkerTask.worker, args=[QList[i], OutputQ, proxy, 'ssl',
nThread])
+            else:  # even/nonSSL
+                p = Process(target=WorkerTask.worker, args=[QList[i], OutputQ, proxy, 'nossl',
nThread])
+        else:
+            p = Process(target=WorkerTask.worker, args=[QList[i], OutputQ, proxy, replay_type,
nThread])
+
         p.daemon = False
         Processes.append(p)
         p.start()
diff --git a/tests/tools/traffic-replay/__main__.py b/tests/tools/traffic-replay/__main__.py
index 0f6074a..4b64e51 100644
--- a/tests/tools/traffic-replay/__main__.py
+++ b/tests/tools/traffic-replay/__main__.py
@@ -25,7 +25,8 @@ import Config
 if __name__ == '__main__':
 
     parser = argparse.ArgumentParser()
-    parser.add_argument("-type", action='store', dest='replay_type', help="Replay type: ssl/random/h2/nossl")
+    parser.add_argument("-type", action='store', dest='replay_type',
+                        help="Replay type: ssl/random/h2/nossl/mixed (at least 2 processes
needed for mixed)")
     parser.add_argument("-log_dir", type=str, help="directory of JSON replay files")
     parser.add_argument("-v", dest="verbose", help="verify response status code", action="store_true")
     parser.add_argument("-host", help="proxy/host to send the requests to", default=Config.proxy_host)
diff --git a/tests/tools/traffic-replay/extractHeader.py b/tests/tools/traffic-replay/extractHeader.py
index 69fed04..c8f7961 100644
--- a/tests/tools/traffic-replay/extractHeader.py
+++ b/tests/tools/traffic-replay/extractHeader.py
@@ -42,7 +42,11 @@ def responseHeader_to_dict(header):
     headers = {}
     for line in header:
         split_here = line.find(":")
-        headers[line[:split_here].lower()] = line[(split_here + 1):].strip()
+        # append multiple headers into a single string
+        if line[:split_here].lower() in headers:
+            headers[line[:split_here].lower()] += ", {0}".format(line[(split_here + 1):].strip())
+        else:
+            headers[line[:split_here].lower()] = line[(split_here + 1):].strip()
 
     return headers
 
diff --git a/tests/tools/traffic-replay/h2Replay.py b/tests/tools/traffic-replay/h2Replay.py
index f656a3e..ff990c2 100644
--- a/tests/tools/traffic-replay/h2Replay.py
+++ b/tests/tools/traffic-replay/h2Replay.py
@@ -230,7 +230,7 @@ def txn_replay(session_filename, txn, proxy, result_queue, h2conn, request_IDs):
         if method == 'GET':
             responseID = h2conn.request('GET', url=extractHeader.extract_GET_path(
                 txn_req_headers), headers=txn_req_headers_dict, body=mbody)
-            #print("get response", responseID)
+            # print("get response", responseID)
             return responseID
             # request_IDs.append(responseID)
             #response = h2conn.get_response(id)
@@ -250,18 +250,6 @@ def txn_replay(session_filename, txn, proxy, result_queue, h2conn, request_IDs):
             print("get response", responseID)
             return responseID
 
-        # print(response.headers)
-        #print("logged respose")
-        expected = extractHeader.responseHeader_to_dict(resp.getHeaders())
-        # print(expected)
-        if mainProcess.verbose:
-            expected_output_split = resp.getHeaders().split('\r\n')[0].split(' ', 2)
-            expected_output = (int(expected_output_split[1]), str(expected_output_split[2]))
-            r = result.Result(session_filename, expected_output[0], response.status_code)
-            print(r.getResultString(response.headers, expected, colorize=True))
-
-        # return responseID
-
     except UnicodeEncodeError as e:
         # these unicode errors are due to the interaction between Requests and our wiretrace
data.
         # TODO fix
@@ -315,10 +303,16 @@ def session_replay(input, proxy, result_queue):
 
                         expected_output_split = expectedH.getHeaders().split('\r\n')[0].split('
', 2)
                         expected_output = (int(expected_output_split[1]), str(expected_output_split[2]))
-                        r = result.Result("", expected_output[0], response.status)
+                        r = result.Result("", expected_output[0], response.status, response.read())
                         expected_Dict = extractHeader.responseHeader_to_dict(expectedH.getHeaders())
-                        print(r.getResultString(response_dict, expected_Dict, colorize=Config.colorize))
-                        # r.Compare(response_dict,expected_Dict)
+                        b_res, res = r.getResult(response_dict, expected_Dict, colorize=Config.colorize)
+                        print(res)
+
+                        if not b_res:
+                            print("Received response")
+                            print(response_dict)
+                            print("Expected response")
+                            print(expected_Dict)
 
         bSTOP = True
         #print("Queue is empty")

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <commits@trafficserver.apache.org>'].

Mime
View raw message