You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by so...@apache.org on 2016/05/20 16:49:35 UTC

[trafficserver] 03/15: TS-4388: Add an API test for TSHttpTxnParentProxySet.

This is an automated email from the ASF dual-hosted git repository.

sorber pushed a commit to branch 6.2.x
in repository https://git-dual.apache.org/repos/asf/trafficserver.git

commit 071853a28c5186e915ae28bce9e41ab440cbe749
Author: James Peach <jp...@apache.org>
AuthorDate: Wed Apr 27 12:19:57 2016 -0700

    TS-4388: Add an API test for TSHttpTxnParentProxySet.
    
    Add an API test for TSHttpTxnParentProxySet. This test sends a
    request to the API test synserver, and expects a response. The quirk
    is that it can't get the right response unless TSHttpTxnParentProxySet()
    is called to parent proxy to the syn server.
    
    This test currently crashes, so it is only enabled at REGRESSION_TEST_FATAL
    (level 4).
    
    This closes #605.
    
    TSHttpTxnParentProxySet should take const arguments.
    
    (cherry picked from commit 600f4bc4d0754f7e028836f597a4a34f180be0c4)
    (cherry picked from commit 4c05b1cba0332347affa4596364d8e153bef32b7)
---
 .../api/functions/TSHttpTxnParentProxySet.en.rst   |   2 +-
 proxy/InkAPI.cc                                    |   4 +-
 proxy/InkAPITest.cc                                | 135 ++++++++++++++++++++-
 proxy/InkAPITestTool.cc                            |  40 ++++--
 proxy/api/ts/ts.h                                  |   4 +-
 5 files changed, 172 insertions(+), 13 deletions(-)

diff --git a/doc/developer-guide/api/functions/TSHttpTxnParentProxySet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnParentProxySet.en.rst
index daae59a..8da767d 100644
--- a/doc/developer-guide/api/functions/TSHttpTxnParentProxySet.en.rst
+++ b/doc/developer-guide/api/functions/TSHttpTxnParentProxySet.en.rst
@@ -28,7 +28,7 @@ Synopsis
 
 `#include <ts/ts.h>`
 
-.. function:: void TSHttpTxnParentProxySet(TSHttpTxn txnp, char * hostname, int port)
+.. function:: void TSHttpTxnParentProxySet(TSHttpTxn txnp, const char * hostname, int port)
 
 Description
 ===========
diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
index f4ec204..5ec1466 100644
--- a/proxy/InkAPI.cc
+++ b/proxy/InkAPI.cc
@@ -5557,7 +5557,7 @@ TSHttpTxnServerRequestBodySet(TSHttpTxn txnp, char *buf, int64_t buflength)
 }
 
 TSReturnCode
-TSHttpTxnParentProxyGet(TSHttpTxn txnp, char **hostname, int *port)
+TSHttpTxnParentProxyGet(TSHttpTxn txnp, const char **hostname, int *port)
 {
   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
 
@@ -5570,7 +5570,7 @@ TSHttpTxnParentProxyGet(TSHttpTxn txnp, char **hostname, int *port)
 }
 
 void
-TSHttpTxnParentProxySet(TSHttpTxn txnp, char *hostname, int port)
+TSHttpTxnParentProxySet(TSHttpTxn txnp, const char *hostname, int port)
 {
   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
   sdk_assert(sdk_sanity_check_null_ptr((void *)hostname) == TS_SUCCESS);
diff --git a/proxy/InkAPITest.cc b/proxy/InkAPITest.cc
index 17d0140..d7d64dd 100644
--- a/proxy/InkAPITest.cc
+++ b/proxy/InkAPITest.cc
@@ -5668,7 +5668,7 @@ checkHttpTxnParentProxy(ContData *data, TSHttpTxn txnp)
 {
   const char *hostname = "txnpp.example.com";
   int port = 10180;
-  char *hostnameget = NULL;
+  const char *hostnameget = NULL;
   int portget = 0;
 
   TSHttpTxnParentProxySet(txnp, (char *)hostname, port);
@@ -5858,6 +5858,139 @@ EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpSsn)(RegressionTest *test, int /* atype AT
   return;
 }
 
+struct ParentTest {
+  RegressionTest *regtest;
+  int *pstatus;
+  SocketServer *os;
+  ClientTxn *browser;
+
+  RecBool parent_proxy_routing_enable;
+  unsigned int magic;
+};
+
+static int
+parent_proxy_handler(TSCont contp, TSEvent event, void *edata)
+{
+  ParentTest *ptest = (ParentTest *)TSContDataGet(contp);
+  TSHttpTxn txnp = (TSHttpTxn)edata;
+
+  switch (event) {
+  case TS_EVENT_HTTP_READ_REQUEST_HDR:
+    rprintf(ptest->regtest, "setting synserver parent proxy to %s:%d\n", "127.0.0.1", SYNSERVER_LISTEN_PORT);
+
+    // Since we chose a request format with a hostname of trafficserver.apache.org, it won't get
+    // sent to the synserver unless we set a parent proxy.
+    TSHttpTxnParentProxySet(txnp, "127.0.0.1", SYNSERVER_LISTEN_PORT);
+
+    TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp);
+    TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, contp);
+
+    TSSkipRemappingSet(txnp, 1);
+    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+    break;
+
+  case TS_EVENT_HTTP_SEND_RESPONSE_HDR: {
+    int expected = get_request_id(txnp);
+    int received = get_response_id(txnp);
+
+    if (expected != received) {
+      *(ptest->pstatus) = REGRESSION_TEST_FAILED;
+      SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", "TestCase", TC_FAIL, "Expected response ID %d, received %d", expected,
+                 received);
+    } else {
+      *(ptest->pstatus) = REGRESSION_TEST_PASSED;
+      SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", "TestCase", TC_PASS, "Received expected response ID %d", expected);
+    }
+    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+    break;
+  }
+
+  case TS_EVENT_TIMEOUT:
+    if (*(ptest->pstatus) == REGRESSION_TEST_INPROGRESS) {
+      // If we are still in progress, reschedule.
+      rprintf(ptest->regtest, "waiting for response\n");
+      TSContSchedule(contp, 100, TS_THREAD_POOL_DEFAULT);
+    } else {
+      // Otherwise the test completed so clean up.
+      RecSetRecordInt("proxy.config.http.parent_proxy_routing_enable", ptest->parent_proxy_routing_enable, REC_SOURCE_EXPLICIT);
+
+      ptest->magic = MAGIC_DEAD;
+      synclient_txn_delete(ptest->browser);
+      synserver_delete(ptest->os);
+      TSfree(ptest);
+      TSContDataSet(contp, NULL);
+    }
+    break;
+
+  case TS_EVENT_HTTP_TXN_CLOSE:
+    // We expected to pass or fail reading the response header. At this point we must have failed.
+    if (*(ptest->pstatus) == REGRESSION_TEST_INPROGRESS) {
+      *(ptest->pstatus) = REGRESSION_TEST_FAILED;
+      SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", "TestCase", TC_FAIL, "Failed on txn close");
+    }
+    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+    break;
+
+  default:
+    *(ptest->pstatus) = REGRESSION_TEST_FAILED;
+    SDK_RPRINT(ptest->regtest, "TSHttpTxnParentProxySet", "TestCase", TC_FAIL, "Unexpected event %d", event);
+    break;
+  }
+
+  return 0;
+}
+
+EXCLUSIVE_REGRESSION_TEST(SDK_API_HttpParentProxySet)(RegressionTest *test, int level, int *pstatus)
+{
+  // Don't enable this test by default until it passes.
+  if (level < REGRESSION_TEST_FATAL) {
+    *pstatus = REGRESSION_TEST_NOT_RUN;
+    return;
+  }
+
+  *pstatus = REGRESSION_TEST_INPROGRESS;
+
+  TSCont cont = TSContCreate(parent_proxy_handler, TSMutexCreate());
+  if (cont == NULL) {
+    SDK_RPRINT(test, "TSHttpTxnParentProxySet", "TestCase", TC_FAIL, "Unable to create continuation");
+    *pstatus = REGRESSION_TEST_FAILED;
+    return;
+  }
+
+  ParentTest *ptest = (ParentTest *)TSmalloc(sizeof(SocketTest));
+  ink_zero(*ptest);
+
+  ptest->regtest = test;
+  ptest->pstatus = pstatus;
+  ptest->magic = MAGIC_ALIVE;
+  TSContDataSet(cont, ptest);
+
+  /* If parent proxy routing is not enabled, enable it for the life of the test. */
+  RecGetRecordBool("proxy.config.http.parent_proxy_routing_enable", &ptest->parent_proxy_routing_enable);
+  if (!ptest->parent_proxy_routing_enable) {
+    rprintf(test, "enabling proxy.config.http.parent_proxy_routing_enable");
+    RecSetRecordInt("proxy.config.http.parent_proxy_routing_enable", 1, REC_SOURCE_EXPLICIT);
+  }
+
+  RecSetRecordInt("proxy.config.http.parent_proxy_routing_enable", 1, REC_SOURCE_EXPLICIT);
+  /* Hook read request headers, since that is the earliest reasonable place to set the parent proxy. */
+  TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, cont);
+
+  /* Create a new synthetic server */
+  ptest->os = synserver_create(SYNSERVER_LISTEN_PORT);
+  synserver_start(ptest->os);
+
+  /* Create a client transaction */
+  ptest->browser = synclient_txn_create();
+
+  // HTTP_REQUEST_FORMAT10 is a hostname, so we will need to set the parent to the synserver to get a response.
+  char *request = generate_request(10);
+  synclient_txn_send_request(ptest->browser, request);
+  TSfree(request);
+
+  TSContSchedule(cont, 25, TS_THREAD_POOL_DEFAULT);
+}
+
 /////////////////////////////////////////////////////
 //       SDK_API_TSHttpTxnCache
 //
diff --git a/proxy/InkAPITestTool.cc b/proxy/InkAPITestTool.cc
index fa6d542..eb399fd 100644
--- a/proxy/InkAPITestTool.cc
+++ b/proxy/InkAPITestTool.cc
@@ -404,6 +404,21 @@ generate_response(const char *request)
   return response;
 }
 
+static int
+get_request_id_value(const char *name, TSMBuffer buf, TSMLoc hdr)
+{
+  int id = -1;
+  TSMLoc field;
+
+  field = TSMimeHdrFieldFind(buf, hdr, name, -1);
+  if (field != TS_NULL_MLOC) {
+    id = TSMimeHdrFieldValueIntGet(buf, hdr, field, 0);
+  }
+
+  TSHandleMLocRelease(buf, hdr, field);
+  return id;
+}
+
 // This routine can be called by tests, from the READ_REQUEST_HDR_HOOK
 // to figure out the id of a test message
 // Returns id/-1 in case of error
@@ -411,22 +426,33 @@ static int
 get_request_id(TSHttpTxn txnp)
 {
   TSMBuffer bufp;
-  TSMLoc hdr_loc, id_loc;
+  TSMLoc hdr_loc;
   int id = -1;
 
   if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
     return -1;
   }
 
-  id_loc = TSMimeHdrFieldFind(bufp, hdr_loc, X_REQUEST_ID, -1);
-  if (id_loc == TS_NULL_MLOC) {
-    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+  id = get_request_id_value(X_REQUEST_ID, bufp, hdr_loc);
+  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
+  return id;
+}
+
+// This routine can be called by tests, from the READ_RESPONSE_HDR_HOOK
+// to figure out the id of a test message
+// Returns id/-1 in case of error
+static int
+get_response_id(TSHttpTxn txnp)
+{
+  TSMBuffer bufp;
+  TSMLoc hdr_loc;
+  int id = -1;
+
+  if (TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
     return -1;
   }
 
-  id = TSMimeHdrFieldValueIntGet(bufp, hdr_loc, id_loc, 0);
-
-  TSHandleMLocRelease(bufp, hdr_loc, id_loc);
+  id = get_request_id_value(X_RESPONSE_ID, bufp, hdr_loc);
   TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
   return id;
 }
diff --git a/proxy/api/ts/ts.h b/proxy/api/ts/ts.h
index 1593784..a55408a 100644
--- a/proxy/api/ts/ts.h
+++ b/proxy/api/ts/ts.h
@@ -1455,7 +1455,7 @@ tsapi void TSHttpTxnErrorBodySet(TSHttpTxn txnp, char *buf, size_t buflength, ch
     @param port parent proxy's port.
 
  */
-tsapi TSReturnCode TSHttpTxnParentProxyGet(TSHttpTxn txnp, char **hostname, int *port);
+tsapi TSReturnCode TSHttpTxnParentProxyGet(TSHttpTxn txnp, const char **hostname, int *port);
 
 /**
     Sets the parent proxy name and port. The string hostname is copied
@@ -1467,7 +1467,7 @@ tsapi TSReturnCode TSHttpTxnParentProxyGet(TSHttpTxn txnp, char **hostname, int
     @param port parent proxy port to set.
 
  */
-tsapi void TSHttpTxnParentProxySet(TSHttpTxn txnp, char *hostname, int port);
+tsapi void TSHttpTxnParentProxySet(TSHttpTxn txnp, const char *hostname, int port);
 
 tsapi void TSHttpTxnUntransformedRespCache(TSHttpTxn txnp, int on);
 tsapi void TSHttpTxnTransformedRespCache(TSHttpTxn txnp, int on);

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