From 54177d374e83640284ff25b34097a1ab28b8ef88 Mon Sep 17 00:00:00 2001 From: danielatdattrixdotcom Date: Fri, 18 Mar 2016 22:24:25 -0700 Subject: [PATCH 1/3] Add a "cookiejar" option to config. Takes a string to create cookiejar file in CWD which it will remove when complete. Added condition for GET requests as well. --- pyresttest/resttest.py | 15 +++++++++++---- pyresttest/tests.py | 28 +++++++++++++++++----------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/pyresttest/resttest.py b/pyresttest/resttest.py index 7bfb33c1..16f05878 100644 --- a/pyresttest/resttest.py +++ b/pyresttest/resttest.py @@ -108,6 +108,7 @@ class TestConfig: verbose = False ssl_insecure = False skip_term_colors = False # Turn off output term colors + cookiejar = None # Binding and creation of generators variable_binds = None @@ -278,6 +279,8 @@ def parse_configuration(node, base_config=None): test_config.timeout = int(value) elif key == u'print_bodies': test_config.print_bodies = safe_to_bool(value) + elif key == u'cookiejar': + test_config.cookiejar = os.path.basename(str(value)) elif key == u'retries': test_config.retries = int(value) elif key == u'variable_binds': @@ -314,7 +317,7 @@ def run_test(mytest, test_config=TestConfig(), context=None, curl_handle=None, * mytest.update_context_before(my_context) templated_test = mytest.realize(my_context) curl = templated_test.configure_curl( - timeout=test_config.timeout, context=my_context, curl_handle=curl_handle) + timeout=test_config.timeout, cookiejar=test_config.cookiejar, context=my_context, curl_handle=curl_handle) result = TestResponse() result.test = templated_test @@ -708,6 +711,10 @@ def run_testsets(testsets): benchmark, test_config=myconfig) my_file.close() + if myconfig.cookiejar: + curl_handle.close() + os.remove('/'.join([os.getcwd(), myconfig.cookiejar])) + if myinteractive: # a break for when interactive bits are complete, before summary data print("===================================") @@ -719,10 +726,10 @@ def run_testsets(testsets): total_failures = total_failures + failures passfail = {True: u'SUCCEEDED: ', False: u'FAILED: '} - output_string = "Test Group {0} {1}: {2}/{3} Tests Passed!".format(group, passfail[failures == 0], str(test_count - failures), str(test_count)) - + output_string = "Test Group {0} {1}: {2}/{3} Tests Passed!".format(group, passfail[failures == 0], str(test_count - failures), str(test_count)) + if myconfig.skip_term_colors: - print(output_string) + print(output_string) else: if failures > 0: print('\033[91m' + output_string + '\033[0m') diff --git a/pyresttest/tests.py b/pyresttest/tests.py index 56365fce..03ea5689 100644 --- a/pyresttest/tests.py +++ b/pyresttest/tests.py @@ -286,24 +286,28 @@ def __init__(self): def __str__(self): return json.dumps(self, default=safe_to_json) - def configure_curl(self, timeout=DEFAULT_TIMEOUT, context=None, curl_handle=None): + def configure_curl(self, timeout=DEFAULT_TIMEOUT, cookiejar=None, context=None, curl_handle=None): """ Create and mostly configure a curl object for test, reusing existing if possible """ if curl_handle: curl = curl_handle - try: # Check the curl handle isn't closed, and reuse it if possible - curl.getinfo(curl.HTTP_CODE) - # Below clears the cookies & curl options for clean run - # But retains the DNS cache and connection pool - curl.reset() - curl.setopt(curl.COOKIELIST, "ALL") + curl.getinfo(curl.HTTP_CODE) + if not cookiejar: + # Below clears the cookies & curl options for clean run + # But retains the DNS cache and connection pool + curl.reset() + curl.setopt(curl.COOKIELIST, "ALL") except pycurl.error: curl = pycurl.Curl() - + else: curl = pycurl.Curl() + if cookiejar: + curl.setopt(curl.COOKIEJAR, cookiejar) + curl.setopt(curl.COOKIEFILE, cookiejar) + # curl.setopt(pycurl.VERBOSE, 1) # Debugging convenience curl.setopt(curl.URL, str(self.url)) curl.setopt(curl.TIMEOUT, timeout) @@ -319,12 +323,14 @@ def configure_curl(self, timeout=DEFAULT_TIMEOUT, context=None, curl_handle=None curl.setopt(curl.READFUNCTION, MyIO(bod).read) if self.auth_username and self.auth_password: - curl.setopt(pycurl.USERPWD, - parsing.encode_unicode_bytes(self.auth_username) + b':' + + curl.setopt(pycurl.USERPWD, + parsing.encode_unicode_bytes(self.auth_username) + b':' + parsing.encode_unicode_bytes(self.auth_password)) if self.auth_type: curl.setopt(pycurl.HTTPAUTH, self.auth_type) - + if self.method == u'GET': + curl.setopt(HTTP_METHODS[u'GET'], 1) + curl.unsetopt(curl.CUSTOMREQUEST) if self.method == u'POST': curl.setopt(HTTP_METHODS[u'POST'], 1) # Required for some servers From 567f442937b4184f685e0df77745c0fec70ee8e8 Mon Sep 17 00:00:00 2001 From: danielatdattrixdotcom Date: Wed, 23 Mar 2016 19:26:36 -0700 Subject: [PATCH 2/3] Revise cookiejar implmentation and fix bug. --- pyresttest/resttest.py | 5 ++++- pyresttest/tests.py | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pyresttest/resttest.py b/pyresttest/resttest.py index 16f05878..a56c7671 100644 --- a/pyresttest/resttest.py +++ b/pyresttest/resttest.py @@ -713,7 +713,10 @@ def run_testsets(testsets): if myconfig.cookiejar: curl_handle.close() - os.remove('/'.join([os.getcwd(), myconfig.cookiejar])) + try: + os.remove('/'.join([os.getcwd(), myconfig.cookiejar])) + except OSError: + pass if myinteractive: # a break for when interactive bits are complete, before summary data diff --git a/pyresttest/tests.py b/pyresttest/tests.py index 03ea5689..28ee3a33 100644 --- a/pyresttest/tests.py +++ b/pyresttest/tests.py @@ -291,12 +291,12 @@ def configure_curl(self, timeout=DEFAULT_TIMEOUT, cookiejar=None, context=None, if curl_handle: curl = curl_handle + curl.reset() try: # Check the curl handle isn't closed, and reuse it if possible curl.getinfo(curl.HTTP_CODE) if not cookiejar: # Below clears the cookies & curl options for clean run # But retains the DNS cache and connection pool - curl.reset() curl.setopt(curl.COOKIELIST, "ALL") except pycurl.error: curl = pycurl.Curl() @@ -307,6 +307,7 @@ def configure_curl(self, timeout=DEFAULT_TIMEOUT, cookiejar=None, context=None, if cookiejar: curl.setopt(curl.COOKIEJAR, cookiejar) curl.setopt(curl.COOKIEFILE, cookiejar) + curl.setopt(curl.COOKIELIST, "RELOAD") # curl.setopt(pycurl.VERBOSE, 1) # Debugging convenience curl.setopt(curl.URL, str(self.url)) @@ -330,8 +331,7 @@ def configure_curl(self, timeout=DEFAULT_TIMEOUT, cookiejar=None, context=None, curl.setopt(pycurl.HTTPAUTH, self.auth_type) if self.method == u'GET': curl.setopt(HTTP_METHODS[u'GET'], 1) - curl.unsetopt(curl.CUSTOMREQUEST) - if self.method == u'POST': + elif self.method == u'POST': curl.setopt(HTTP_METHODS[u'POST'], 1) # Required for some servers if bod is not None: From 196c3b848a87da5cd05560ddf213f9c24019a22f Mon Sep 17 00:00:00 2001 From: danielatdattrixdotcom Date: Thu, 24 Mar 2016 00:58:22 -0700 Subject: [PATCH 3/3] Move Curl.reset() back to directly after the Curl.getinfo() call to prevent a segfault. --- pyresttest/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyresttest/tests.py b/pyresttest/tests.py index 28ee3a33..03aded24 100644 --- a/pyresttest/tests.py +++ b/pyresttest/tests.py @@ -291,9 +291,9 @@ def configure_curl(self, timeout=DEFAULT_TIMEOUT, cookiejar=None, context=None, if curl_handle: curl = curl_handle - curl.reset() try: # Check the curl handle isn't closed, and reuse it if possible curl.getinfo(curl.HTTP_CODE) + curl.reset() if not cookiejar: # Below clears the cookies & curl options for clean run # But retains the DNS cache and connection pool