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]>.
