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

jpeach pushed a commit to branch master
in repository https://git-dual.apache.org/repos/asf/trafficserver.git

commit 600f4bc4d0754f7e028836f597a4a34f180be0c4
Author: James Peach <[email protected]>
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.
---
 proxy/InkAPITest.cc     | 133 ++++++++++++++++++++++++++++++++++++++++++++++++
 proxy/InkAPITestTool.cc |  40 ++++++++++++---
 2 files changed, 166 insertions(+), 7 deletions(-)

diff --git a/proxy/InkAPITest.cc b/proxy/InkAPITest.cc
index cec0c35..cb883ec 100644
--- a/proxy/InkAPITest.cc
+++ b/proxy/InkAPITest.cc
@@ -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;
 }

-- 
To stop receiving notification emails like this one, please contact
"[email protected]" <[email protected]>.

Reply via email to