summaryrefslogtreecommitdiff
path: root/test/test_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_context.c')
-rw-r--r--test/test_context.c850
1 files changed, 550 insertions, 300 deletions
diff --git a/test/test_context.c b/test/test_context.c
index d2a24d0..14d4fa9 100644
--- a/test/test_context.c
+++ b/test/test_context.c
@@ -43,6 +43,61 @@ typedef struct {
test_baton_t *tb;
} handler_baton_t;
+/* Helper function, runs the client and server context loops and validates
+ that no errors were encountered, and all messages were sent and received. */
+static apr_status_t
+test_helper_run_requests_no_check(CuTest *tc, test_baton_t *tb,
+ int num_requests,
+ handler_baton_t handler_ctx[],
+ apr_pool_t *pool)
+{
+ apr_pool_t *iter_pool;
+ int i, done = 0;
+ apr_status_t status;
+
+ apr_pool_create(&iter_pool, pool);
+
+ while (!done)
+ {
+ apr_pool_clear(iter_pool);
+
+ status = test_server_run(tb->serv_ctx, 0, iter_pool);
+ if (!APR_STATUS_IS_TIMEUP(status) &&
+ SERF_BUCKET_READ_ERROR(status))
+ return status;
+
+ status = serf_context_run(tb->context, 0, iter_pool);
+ if (!APR_STATUS_IS_TIMEUP(status) &&
+ SERF_BUCKET_READ_ERROR(status))
+ return status;
+
+ done = 1;
+ for (i = 0; i < num_requests; i++)
+ done &= handler_ctx[i].done;
+ }
+ apr_pool_destroy(iter_pool);
+
+ return APR_SUCCESS;
+}
+
+static void
+test_helper_run_requests_expect_ok(CuTest *tc, test_baton_t *tb,
+ int num_requests,
+ handler_baton_t handler_ctx[],
+ apr_pool_t *pool)
+{
+ apr_status_t status;
+
+ status = test_helper_run_requests_no_check(tc, tb, num_requests,
+ handler_ctx, pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Check that all requests were received */
+ CuAssertIntEquals(tc, num_requests, tb->sent_requests->nelts);
+ CuAssertIntEquals(tc, num_requests, tb->accepted_requests->nelts);
+ CuAssertIntEquals(tc, num_requests, tb->handled_requests->nelts);
+}
+
static serf_bucket_t* accept_response(serf_request_t *request,
serf_bucket_t *stream,
void *acceptor_baton,
@@ -133,15 +188,67 @@ static apr_status_t handle_response(serf_request_t *request,
return APR_SUCCESS;
}
+static void setup_handler(test_baton_t *tb, handler_baton_t *handler_ctx,
+ const char *method, const char *path,
+ int req_id,
+ serf_response_handler_t handler)
+{
+ handler_ctx->method = method;
+ handler_ctx->path = path;
+ handler_ctx->done = FALSE;
+
+ handler_ctx->acceptor = accept_response;
+ handler_ctx->acceptor_baton = NULL;
+ handler_ctx->handler = handler ? handler : handle_response;
+ handler_ctx->req_id = req_id;
+ handler_ctx->accepted_requests = tb->accepted_requests;
+ handler_ctx->sent_requests = tb->sent_requests;
+ handler_ctx->handled_requests = tb->handled_requests;
+ handler_ctx->tb = tb;
+}
+
+static void create_new_prio_request(test_baton_t *tb,
+ handler_baton_t *handler_ctx,
+ const char *method, const char *path,
+ int req_id)
+{
+ setup_handler(tb, handler_ctx, method, path, req_id, NULL);
+ serf_connection_priority_request_create(tb->connection,
+ setup_request,
+ handler_ctx);
+}
+
+static void create_new_request(test_baton_t *tb,
+ handler_baton_t *handler_ctx,
+ const char *method, const char *path,
+ int req_id)
+{
+ setup_handler(tb, handler_ctx, method, path, req_id, NULL);
+ serf_connection_request_create(tb->connection,
+ setup_request,
+ handler_ctx);
+}
+
+static void
+create_new_request_with_resp_hdlr(test_baton_t *tb,
+ handler_baton_t *handler_ctx,
+ const char *method, const char *path,
+ int req_id,
+ serf_response_handler_t handler)
+{
+ setup_handler(tb, handler_ctx, method, path, req_id, handler);
+ serf_connection_request_create(tb->connection,
+ setup_request,
+ handler_ctx);
+}
+
/* Validate that requests are sent and completed in the order of creation. */
static void test_serf_connection_request_create(CuTest *tc)
{
test_baton_t *tb;
- serf_request_t *request1, *request2;
- handler_baton_t handler_ctx, handler2_ctx;
+ handler_baton_t handler_ctx[2];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
apr_status_t status;
- apr_pool_t *iter_pool;
- apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
int i;
test_server_message_t message_list[] = {
{CHUNKED_REQUEST(1, "1")},
@@ -152,74 +259,31 @@ static void test_serf_connection_request_create(CuTest *tc)
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
};
- apr_pool_t *test_pool = test_setup();
- accepted_requests = apr_array_make(test_pool, 2, sizeof(int));
- sent_requests = apr_array_make(test_pool, 2, sizeof(int));
- handled_requests = apr_array_make(test_pool, 2, sizeof(int));
+ apr_pool_t *test_pool = test_setup();
/* Set up a test context with a server */
status = test_server_setup(&tb,
- message_list, 2,
- action_list, 2, 0, NULL,
+ message_list, num_requests,
+ action_list, num_requests, 0, NULL,
test_pool);
CuAssertIntEquals(tc, APR_SUCCESS, status);
- handler_ctx.method = "GET";
- handler_ctx.path = "/";
- handler_ctx.done = FALSE;
-
- handler_ctx.acceptor = accept_response;
- handler_ctx.acceptor_baton = NULL;
- handler_ctx.handler = handle_response;
- handler_ctx.req_id = 1;
- handler_ctx.accepted_requests = accepted_requests;
- handler_ctx.sent_requests = sent_requests;
- handler_ctx.handled_requests = handled_requests;
-
- request1 = serf_connection_request_create(tb->connection,
- setup_request,
- &handler_ctx);
+ create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
+ create_new_request(tb, &handler_ctx[1], "GET", "/", 2);
- handler2_ctx = handler_ctx;
- handler2_ctx.req_id = 2;
-
- request2 = serf_connection_request_create(tb->connection,
- setup_request,
- &handler2_ctx);
-
- apr_pool_create(&iter_pool, test_pool);
-
- while (!handler_ctx.done || !handler2_ctx.done)
- {
- apr_pool_clear(iter_pool);
-
- status = test_server_run(tb->serv_ctx, 0, iter_pool);
- if (APR_STATUS_IS_TIMEUP(status))
- status = APR_SUCCESS;
- CuAssertIntEquals(tc, APR_SUCCESS, status);
-
- status = serf_context_run(tb->context, 0, iter_pool);
- if (APR_STATUS_IS_TIMEUP(status))
- status = APR_SUCCESS;
- CuAssertIntEquals(tc, APR_SUCCESS, status);
- }
- apr_pool_destroy(iter_pool);
-
- /* Check that all requests were received */
- CuAssertIntEquals(tc, 2, sent_requests->nelts);
- CuAssertIntEquals(tc, 2, accepted_requests->nelts);
- CuAssertIntEquals(tc, 2, handled_requests->nelts);
+ test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
+ test_pool);
/* Check that the requests were sent in the order we created them */
- for (i = 0; i < sent_requests->nelts; i++) {
- int req_nr = APR_ARRAY_IDX(sent_requests, i, int);
+ for (i = 0; i < tb->sent_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int);
CuAssertIntEquals(tc, i + 1, req_nr);
}
/* Check that the requests were received in the order we created them */
- for (i = 0; i < handled_requests->nelts; i++) {
- int req_nr = APR_ARRAY_IDX(handled_requests, i, int);
+ for (i = 0; i < tb->handled_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int);
CuAssertIntEquals(tc, i + 1, req_nr);
}
@@ -232,11 +296,9 @@ static void test_serf_connection_request_create(CuTest *tc)
static void test_serf_connection_priority_request_create(CuTest *tc)
{
test_baton_t *tb;
- serf_request_t *request1, *request2, *request3;
- handler_baton_t handler_ctx, handler2_ctx, handler3_ctx;
+ handler_baton_t handler_ctx[3];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
apr_status_t status;
- apr_pool_t *iter_pool;
- apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
int i;
test_server_message_t message_list[] = {
@@ -253,81 +315,29 @@ static void test_serf_connection_priority_request_create(CuTest *tc)
apr_pool_t *test_pool = test_setup();
- accepted_requests = apr_array_make(test_pool, 3, sizeof(int));
- sent_requests = apr_array_make(test_pool, 3, sizeof(int));
- handled_requests = apr_array_make(test_pool, 3, sizeof(int));
-
/* Set up a test context with a server */
status = test_server_setup(&tb,
- message_list, 3,
- action_list, 3, 0, NULL,
+ message_list, num_requests,
+ action_list, num_requests, 0, NULL,
test_pool);
CuAssertIntEquals(tc, APR_SUCCESS, status);
- handler_ctx.method = "GET";
- handler_ctx.path = "/";
- handler_ctx.done = FALSE;
-
- handler_ctx.acceptor = accept_response;
- handler_ctx.acceptor_baton = NULL;
- handler_ctx.handler = handle_response;
- handler_ctx.req_id = 2;
- handler_ctx.accepted_requests = accepted_requests;
- handler_ctx.sent_requests = sent_requests;
- handler_ctx.handled_requests = handled_requests;
-
- request1 = serf_connection_request_create(tb->connection,
- setup_request,
- &handler_ctx);
-
- handler2_ctx = handler_ctx;
- handler2_ctx.req_id = 3;
+ create_new_request(tb, &handler_ctx[0], "GET", "/", 2);
+ create_new_request(tb, &handler_ctx[1], "GET", "/", 3);
+ create_new_prio_request(tb, &handler_ctx[2], "GET", "/", 1);
- request2 = serf_connection_request_create(tb->connection,
- setup_request,
- &handler2_ctx);
- handler3_ctx = handler_ctx;
- handler3_ctx.req_id = 1;
-
- request3 = serf_connection_priority_request_create(tb->connection,
- setup_request,
- &handler3_ctx);
-
- apr_pool_create(&iter_pool, test_pool);
-
- while (!handler_ctx.done || !handler2_ctx.done || !handler3_ctx.done)
- {
- apr_pool_clear(iter_pool);
-
- status = test_server_run(tb->serv_ctx, 0, iter_pool);
- if (APR_STATUS_IS_TIMEUP(status))
- status = APR_SUCCESS;
- CuAssertIntEquals(tc, APR_SUCCESS, status);
-
- status = serf_context_run(tb->context, 0, iter_pool);
- if (APR_STATUS_IS_TIMEUP(status))
- status = APR_SUCCESS;
- CuAssertIntEquals(tc, APR_SUCCESS, status);
-
- /* Debugging purposes only! */
- serf_debug__closed_conn(tb->bkt_alloc);
- }
- apr_pool_destroy(iter_pool);
-
- /* Check that all requests were received */
- CuAssertIntEquals(tc, 3, sent_requests->nelts);
- CuAssertIntEquals(tc, 3, accepted_requests->nelts);
- CuAssertIntEquals(tc, 3, handled_requests->nelts);
+ test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
+ test_pool);
/* Check that the requests were sent in the order we created them */
- for (i = 0; i < sent_requests->nelts; i++) {
- int req_nr = APR_ARRAY_IDX(sent_requests, i, int);
+ for (i = 0; i < tb->sent_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int);
CuAssertIntEquals(tc, i + 1, req_nr);
}
/* Check that the requests were received in the order we created them */
- for (i = 0; i < handled_requests->nelts; i++) {
- int req_nr = APR_ARRAY_IDX(handled_requests, i, int);
+ for (i = 0; i < tb->handled_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int);
CuAssertIntEquals(tc, i + 1, req_nr);
}
@@ -337,13 +347,12 @@ static void test_serf_connection_priority_request_create(CuTest *tc)
/* Test that serf correctly handles the 'Connection:close' header when the
server is planning to close the connection. */
-#define NUM_REQUESTS 10
static void test_serf_closed_connection(CuTest *tc)
{
test_baton_t *tb;
- apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
apr_status_t status;
- handler_baton_t handler_ctx[NUM_REQUESTS];
+ handler_baton_t handler_ctx[10];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
int done = FALSE, i;
test_server_message_t message_list[] = {
@@ -390,37 +399,18 @@ static void test_serf_closed_connection(CuTest *tc)
apr_pool_t *test_pool = test_setup();
- accepted_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
- sent_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
- handled_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
-
/* Set up a test context with a server. */
status = test_server_setup(&tb,
- message_list, 10,
+ message_list, num_requests,
action_list, 12,
0,
NULL,
test_pool);
CuAssertIntEquals(tc, APR_SUCCESS, status);
- for (i = 0 ; i < NUM_REQUESTS ; i++) {
- /* Send some requests on the connections */
- handler_ctx[i].method = "GET";
- handler_ctx[i].path = "/";
- handler_ctx[i].done = FALSE;
-
- handler_ctx[i].acceptor = accept_response;
- handler_ctx[i].acceptor_baton = NULL;
- handler_ctx[i].handler = handle_response;
- handler_ctx[i].req_id = i+1;
- handler_ctx[i].accepted_requests = accepted_requests;
- handler_ctx[i].sent_requests = sent_requests;
- handler_ctx[i].handled_requests = handled_requests;
- handler_ctx[i].tb = tb;
-
- serf_connection_request_create(tb->connection,
- setup_request,
- &handler_ctx[i]);
+ /* Send some requests on the connections */
+ for (i = 0 ; i < num_requests ; i++) {
+ create_new_request(tb, &handler_ctx[i], "GET", "/", i+1);
}
while (1) {
@@ -438,7 +428,7 @@ static void test_serf_closed_connection(CuTest *tc)
serf_debug__closed_conn(tb->bkt_alloc);
done = TRUE;
- for (i = 0 ; i < NUM_REQUESTS ; i++)
+ for (i = 0 ; i < num_requests ; i++)
if (handler_ctx[i].done == FALSE) {
done = FALSE;
break;
@@ -447,29 +437,26 @@ static void test_serf_closed_connection(CuTest *tc)
break;
}
- /* Check that all requests were received */
- CuAssertTrue(tc, sent_requests->nelts >= NUM_REQUESTS);
- CuAssertIntEquals(tc, NUM_REQUESTS, accepted_requests->nelts);
- CuAssertIntEquals(tc, NUM_REQUESTS, handled_requests->nelts);
+ /* Check that all requests were received */
+ CuAssertTrue(tc, tb->sent_requests->nelts >= num_requests);
+ CuAssertIntEquals(tc, num_requests, tb->accepted_requests->nelts);
+ CuAssertIntEquals(tc, num_requests, tb->handled_requests->nelts);
/* Cleanup */
test_server_teardown(tb, test_pool);
test_teardown(test_pool);
}
-#undef NUM_REQUESTS
/* Test if serf is sending the request to the proxy, not to the server
directly. */
static void test_serf_setup_proxy(CuTest *tc)
{
test_baton_t *tb;
- serf_request_t *request;
- handler_baton_t handler_ctx;
- apr_status_t status;
- apr_pool_t *iter_pool;
- apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
int i;
- int numrequests = 1;
+ handler_baton_t handler_ctx[1];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
+ apr_pool_t *iter_pool;
+ apr_status_t status;
test_server_message_t message_list[] = {
{"GET http://localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\
@@ -488,10 +475,6 @@ static void test_serf_setup_proxy(CuTest *tc)
apr_pool_t *test_pool = test_setup();
- accepted_requests = apr_array_make(test_pool, numrequests, sizeof(int));
- sent_requests = apr_array_make(test_pool, numrequests, sizeof(int));
- handled_requests = apr_array_make(test_pool, numrequests, sizeof(int));
-
/* Set up a test context with a server, no messages expected. */
status = test_server_proxy_setup(&tb,
/* server messages and actions */
@@ -504,25 +487,11 @@ static void test_serf_setup_proxy(CuTest *tc)
NULL, test_pool);
CuAssertIntEquals(tc, APR_SUCCESS, status);
- handler_ctx.method = "GET";
- handler_ctx.path = "/";
- handler_ctx.done = FALSE;
-
- handler_ctx.acceptor = accept_response;
- handler_ctx.acceptor_baton = NULL;
- handler_ctx.handler = handle_response;
- handler_ctx.req_id = 1;
- handler_ctx.accepted_requests = accepted_requests;
- handler_ctx.sent_requests = sent_requests;
- handler_ctx.handled_requests = handled_requests;
-
- request = serf_connection_request_create(tb->connection,
- setup_request,
- &handler_ctx);
+ create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
apr_pool_create(&iter_pool, test_pool);
- while (!handler_ctx.done)
+ while (!handler_ctx[0].done)
{
apr_pool_clear(iter_pool);
@@ -547,19 +516,20 @@ static void test_serf_setup_proxy(CuTest *tc)
apr_pool_destroy(iter_pool);
/* Check that all requests were received */
- CuAssertIntEquals(tc, numrequests, sent_requests->nelts);
- CuAssertIntEquals(tc, numrequests, accepted_requests->nelts);
- CuAssertIntEquals(tc, numrequests, handled_requests->nelts);
+ CuAssertIntEquals(tc, num_requests, tb->sent_requests->nelts);
+ CuAssertIntEquals(tc, num_requests, tb->accepted_requests->nelts);
+ CuAssertIntEquals(tc, num_requests, tb->handled_requests->nelts);
+
/* Check that the requests were sent in the order we created them */
- for (i = 0; i < sent_requests->nelts; i++) {
- int req_nr = APR_ARRAY_IDX(sent_requests, i, int);
+ for (i = 0; i < tb->sent_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int);
CuAssertIntEquals(tc, i + 1, req_nr);
}
/* Check that the requests were received in the order we created them */
- for (i = 0; i < handled_requests->nelts; i++) {
- int req_nr = APR_ARRAY_IDX(handled_requests, i, int);
+ for (i = 0; i < tb->handled_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int);
CuAssertIntEquals(tc, i + 1, req_nr);
}
@@ -617,7 +587,6 @@ handle_response_keepalive_limit(serf_request_t *request,
static void test_keepalive_limit_one_by_one(CuTest *tc)
{
test_baton_t *tb;
- apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
apr_status_t status;
handler_baton_t handler_ctx[SEND_REQUESTS];
int done = FALSE, i;
@@ -644,35 +613,17 @@ static void test_keepalive_limit_one_by_one(CuTest *tc)
apr_pool_t *test_pool = test_setup();
- accepted_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
- sent_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
- handled_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
-
/* Set up a test context with a server. */
status = test_server_setup(&tb,
- message_list, 7,
- action_list, 7, 0, NULL,
+ message_list, RCVD_REQUESTS,
+ action_list, RCVD_REQUESTS, 0, NULL,
test_pool);
CuAssertIntEquals(tc, APR_SUCCESS, status);
for (i = 0 ; i < SEND_REQUESTS ; i++) {
- /* Send some requests on the connections */
- handler_ctx[i].method = "GET";
- handler_ctx[i].path = "/";
- handler_ctx[i].done = FALSE;
-
- handler_ctx[i].acceptor = accept_response;
- handler_ctx[i].acceptor_baton = NULL;
- handler_ctx[i].handler = handle_response_keepalive_limit;
- handler_ctx[i].req_id = i+1;
- handler_ctx[i].accepted_requests = accepted_requests;
- handler_ctx[i].sent_requests = sent_requests;
- handler_ctx[i].handled_requests = handled_requests;
- handler_ctx[i].tb = tb;
-
- serf_connection_request_create(tb->connection,
- setup_request,
- &handler_ctx[i]);
+ create_new_request_with_resp_hdlr(tb, &handler_ctx[i], "GET", "/", i+1,
+ handle_response_keepalive_limit);
+ /* TODO: don't think this needs to be done in the loop. */
serf_connection_set_max_outstanding_requests(tb->connection, 1);
}
@@ -701,9 +652,9 @@ static void test_keepalive_limit_one_by_one(CuTest *tc)
}
/* Check that all requests were received */
- CuAssertIntEquals(tc, RCVD_REQUESTS, sent_requests->nelts);
- CuAssertIntEquals(tc, RCVD_REQUESTS, accepted_requests->nelts);
- CuAssertIntEquals(tc, RCVD_REQUESTS, handled_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, tb->sent_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, tb->accepted_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, tb->handled_requests->nelts);
/* Cleanup */
test_server_teardown(tb, test_pool);
@@ -771,8 +722,7 @@ handle_response_keepalive_limit_burst(serf_request_t *request,
static void test_keepalive_limit_one_by_one_and_burst(CuTest *tc)
{
test_baton_t *tb;
- apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
- apr_status_t status;
+ apr_status_t status;
handler_baton_t handler_ctx[SEND_REQUESTS];
int done = FALSE, i;
@@ -798,35 +748,16 @@ static void test_keepalive_limit_one_by_one_and_burst(CuTest *tc)
apr_pool_t *test_pool = test_setup();
- accepted_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
- sent_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
- handled_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
-
/* Set up a test context with a server. */
status = test_server_setup(&tb,
- message_list, 7,
- action_list, 7, 0, NULL,
+ message_list, RCVD_REQUESTS,
+ action_list, RCVD_REQUESTS, 0, NULL,
test_pool);
CuAssertIntEquals(tc, APR_SUCCESS, status);
for (i = 0 ; i < SEND_REQUESTS ; i++) {
- /* Send some requests on the connections */
- handler_ctx[i].method = "GET";
- handler_ctx[i].path = "/";
- handler_ctx[i].done = FALSE;
-
- handler_ctx[i].acceptor = accept_response;
- handler_ctx[i].acceptor_baton = NULL;
- handler_ctx[i].handler = handle_response_keepalive_limit_burst;
- handler_ctx[i].req_id = i+1;
- handler_ctx[i].accepted_requests = accepted_requests;
- handler_ctx[i].sent_requests = sent_requests;
- handler_ctx[i].handled_requests = handled_requests;
- handler_ctx[i].tb = tb;
-
- serf_connection_request_create(tb->connection,
- setup_request,
- &handler_ctx[i]);
+ create_new_request_with_resp_hdlr(tb, &handler_ctx[i], "GET", "/", i+1,
+ handle_response_keepalive_limit_burst);
serf_connection_set_max_outstanding_requests(tb->connection, 1);
}
@@ -855,9 +786,9 @@ static void test_keepalive_limit_one_by_one_and_burst(CuTest *tc)
}
/* Check that all requests were received */
- CuAssertIntEquals(tc, RCVD_REQUESTS, sent_requests->nelts);
- CuAssertIntEquals(tc, RCVD_REQUESTS, accepted_requests->nelts);
- CuAssertIntEquals(tc, RCVD_REQUESTS, handled_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, tb->sent_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, tb->accepted_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, tb->handled_requests->nelts);
/* Cleanup */
test_server_teardown(tb, test_pool);
@@ -866,7 +797,6 @@ static void test_keepalive_limit_one_by_one_and_burst(CuTest *tc)
#undef SEND_REQUESTS
#undef RCVD_REQUESTS
-#define NUM_REQUESTS 5
typedef struct {
apr_off_t read;
apr_off_t written;
@@ -896,10 +826,10 @@ static apr_status_t progress_conn_setup(apr_socket_t *skt,
static void test_serf_progress_callback(CuTest *tc)
{
test_baton_t *tb;
- apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
apr_status_t status;
- handler_baton_t handler_ctx[NUM_REQUESTS];
- int done = FALSE, i;
+ handler_baton_t handler_ctx[5];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
+ int i;
progress_baton_t *pb;
test_server_message_t message_list[] = {
@@ -919,15 +849,11 @@ static void test_serf_progress_callback(CuTest *tc)
};
apr_pool_t *test_pool = test_setup();
-
- accepted_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
- sent_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
- handled_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
-
+
/* Set up a test context with a server. */
status = test_server_setup(&tb,
- message_list, 5,
- action_list, 5, 0,
+ message_list, num_requests,
+ action_list, num_requests, 0,
progress_conn_setup, test_pool);
CuAssertIntEquals(tc, APR_SUCCESS, status);
@@ -936,64 +862,384 @@ static void test_serf_progress_callback(CuTest *tc)
tb->user_baton = pb;
serf_context_set_progress_cb(tb->context, progress_cb, tb);
- for (i = 0 ; i < NUM_REQUESTS ; i++) {
- /* Send some requests on the connections */
- handler_ctx[i].method = "GET";
- handler_ctx[i].path = "/";
- handler_ctx[i].done = FALSE;
-
- handler_ctx[i].acceptor = accept_response;
- handler_ctx[i].acceptor_baton = NULL;
- handler_ctx[i].handler = handle_response;
- handler_ctx[i].req_id = i+1;
- handler_ctx[i].accepted_requests = accepted_requests;
- handler_ctx[i].sent_requests = sent_requests;
- handler_ctx[i].handled_requests = handled_requests;
- handler_ctx[i].tb = tb;
-
- serf_connection_request_create(tb->connection,
+ /* Send some requests on the connections */
+ for (i = 0 ; i < num_requests ; i++) {
+ create_new_request(tb, &handler_ctx[i], "GET", "/", i+1);
+ }
+
+ test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
+ test_pool);
+
+ /* Check that progress was reported. */
+ CuAssertTrue(tc, pb->written > 0);
+ CuAssertTrue(tc, pb->read > 0);
+
+ /* Cleanup */
+ test_server_teardown(tb, test_pool);
+ test_teardown(test_pool);
+}
+
+
+/*****************************************************************************
+ * Issue #91: test that serf correctly handle an incoming 4xx reponse while
+ * the outgoing request wasn't written completely yet.
+ *****************************************************************************/
+
+#define REQUEST_PART1 "PROPFIND / HTTP/1.1" CRLF\
+"Host: lgo-ubuntu.local" CRLF\
+"User-Agent: SVN/1.8.0-dev (x86_64-apple-darwin11.4.2) serf/2.0.0" CRLF\
+"Content-Type: text/xml" CRLF\
+"Transfer-Encoding: chunked" CRLF \
+CRLF\
+"12d" CRLF\
+"<?xml version=""1.0"" encoding=""utf-8""?><propfind xmlns=""DAV:""><prop>"
+
+#define REQUEST_PART2 \
+"<resourcetype xmlns=""DAV:""/><getcontentlength xmlns=""DAV:""/>"\
+"<deadprop-count xmlns=""http://subversion.tigris.org/xmlns/dav/""/>"\
+"<version-name xmlns=""DAV:""/><creationdate xmlns=""DAV:""/>"\
+"<creator-displayname xmlns=""DAV:""/></prop></propfind>" CRLF\
+"0" CRLF \
+CRLF
+
+#define RESPONSE_408 "HTTP/1.1 408 Request Time-out" CRLF\
+"Date: Wed, 14 Nov 2012 19:50:35 GMT" CRLF\
+"Server: Apache/2.2.17 (Ubuntu)" CRLF\
+"Vary: Accept-Encoding" CRLF\
+"Content-Length: 305" CRLF\
+"Connection: close" CRLF\
+"Content-Type: text/html; charset=iso-8859-1" CRLF \
+CRLF\
+"<!DOCTYPE HTML PUBLIC ""-//IETF//DTD HTML 2.0//EN""><html><head>"\
+"<title>408 Request Time-out</title></head><body><h1>Request Time-out</h1>"\
+"<p>Server timeout waiting for the HTTP request from the client.</p><hr>"\
+"<address>Apache/2.2.17 (Ubuntu) Server at lgo-ubuntu.local Port 80</address>"\
+"</body></html>"
+
+
+static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
+{
+ serf_bucket_t *body_bkt;
+ handler_baton_t *ctx = baton;
+
+ if (ctx->done) {
+ body_bkt = serf_bucket_simple_create(REQUEST_PART1, strlen(REQUEST_PART2),
+ NULL, NULL,
+ ctx->tb->bkt_alloc);
+ serf_bucket_aggregate_append(aggregate_bucket, body_bkt);
+ }
+
+ return APR_EAGAIN;
+}
+
+static apr_status_t setup_request_timeout(
+ serf_request_t *request,
+ void *setup_baton,
+ serf_bucket_t **req_bkt,
+ serf_response_acceptor_t *acceptor,
+ void **acceptor_baton,
+ serf_response_handler_t *handler,
+ void **handler_baton,
+ apr_pool_t *pool)
+{
+ handler_baton_t *ctx = setup_baton;
+ serf_bucket_t *body_bkt;
+
+ *req_bkt = serf__bucket_stream_create(serf_request_get_alloc(request),
+ detect_eof,
+ ctx);
+
+ /* create a simple body text */
+ body_bkt = serf_bucket_simple_create(REQUEST_PART1, strlen(REQUEST_PART1),
+ NULL, NULL,
+ serf_request_get_alloc(request));
+ serf_bucket_aggregate_append(*req_bkt, body_bkt);
+
+ APR_ARRAY_PUSH(ctx->sent_requests, int) = ctx->req_id;
+
+ *acceptor = ctx->acceptor;
+ *acceptor_baton = ctx;
+ *handler = ctx->handler;
+ *handler_baton = ctx;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t handle_response_timeout(
+ serf_request_t *request,
+ serf_bucket_t *response,
+ void *handler_baton,
+ apr_pool_t *pool)
+{
+ handler_baton_t *ctx = handler_baton;
+ serf_status_line sl;
+ apr_status_t status;
+
+ if (! response) {
+ serf_connection_request_create(ctx->tb->connection,
setup_request,
- &handler_ctx[i]);
+ ctx);
+ return APR_SUCCESS;
}
- while (1) {
- status = test_server_run(tb->serv_ctx, 0, test_pool);
- if (APR_STATUS_IS_TIMEUP(status))
- status = APR_SUCCESS;
- CuAssertIntEquals(tc, APR_SUCCESS, status);
+ if (serf_request_is_written(request) != APR_EBUSY) {
+ return APR_EGENERAL;
+ }
- status = serf_context_run(tb->context, 0, test_pool);
- if (APR_STATUS_IS_TIMEUP(status))
- status = APR_SUCCESS;
- CuAssertIntEquals(tc, APR_SUCCESS, status);
- /* Debugging purposes only! */
- serf_debug__closed_conn(tb->bkt_alloc);
+ status = serf_bucket_response_status(response, &sl);
+ if (SERF_BUCKET_READ_ERROR(status)) {
+ return status;
+ }
+ if (!sl.version && (APR_STATUS_IS_EOF(status) ||
+ APR_STATUS_IS_EAGAIN(status))) {
+ return status;
+ }
+ if (sl.code == 408) {
+ APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id;
+ ctx->done = TRUE;
+ }
- done = TRUE;
- for (i = 0 ; i < NUM_REQUESTS ; i++)
- if (handler_ctx[i].done == FALSE) {
- done = FALSE;
- break;
- }
- if (done)
- break;
+ /* discard the rest of the body */
+ while (1) {
+ const char *data;
+ apr_size_t len;
+
+ status = serf_bucket_read(response, 2048, &data, &len);
+ if (SERF_BUCKET_READ_ERROR(status) ||
+ APR_STATUS_IS_EAGAIN(status) ||
+ APR_STATUS_IS_EOF(status))
+ return status;
}
- /* Check that all requests were received */
- CuAssertTrue(tc, sent_requests->nelts >= NUM_REQUESTS);
- CuAssertIntEquals(tc, NUM_REQUESTS, accepted_requests->nelts);
- CuAssertIntEquals(tc, NUM_REQUESTS, handled_requests->nelts);
+ return APR_SUCCESS;
+}
- /* Check that progress was reported. */
- CuAssertTrue(tc, pb->written > 0);
- CuAssertTrue(tc, pb->read > 0);
+static void test_serf_request_timeout(CuTest *tc)
+{
+ test_baton_t *tb;
+ apr_status_t status;
+ handler_baton_t handler_ctx[1];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
+
+ test_server_message_t message_list[] = {
+ {REQUEST_PART1},
+ {REQUEST_PART2},
+ };
+
+ test_server_action_t action_list[] = {
+ {SERVER_RESPOND, RESPONSE_408},
+ };
+
+ apr_pool_t *test_pool = test_setup();
+
+ /* Set up a test context with a server. */
+ status = test_server_setup(&tb,
+ message_list, 2,
+ action_list, 1, 0,
+ NULL, test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Send some requests on the connection */
+ handler_ctx[0].method = "PROPFIND";
+ handler_ctx[0].path = "/";
+ handler_ctx[0].done = FALSE;
+
+ handler_ctx[0].acceptor = accept_response;
+ handler_ctx[0].acceptor_baton = NULL;
+ handler_ctx[0].handler = handle_response_timeout;
+ handler_ctx[0].req_id = 1;
+ handler_ctx[0].accepted_requests = tb->accepted_requests;
+ handler_ctx[0].sent_requests = tb->sent_requests;
+ handler_ctx[0].handled_requests = tb->handled_requests;
+ handler_ctx[0].tb = tb;
+
+ serf_connection_request_create(tb->connection,
+ setup_request_timeout,
+ &handler_ctx[0]);
+
+ test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
+ test_pool);
/* Cleanup */
test_server_teardown(tb, test_pool);
test_teardown(test_pool);
}
-#undef NUM_REQUESTS
+
+static apr_status_t
+ssl_server_cert_cb_expect_failures(void *baton, int failures,
+ const serf_ssl_certificate_t *cert)
+{
+ /* We expect an error from the certificate validation function. */
+ if (failures)
+ return APR_SUCCESS;
+ else
+ return APR_EGENERAL;
+}
+
+static apr_status_t
+ssl_server_cert_cb_expect_allok(void *baton, int failures,
+ const serf_ssl_certificate_t *cert)
+{
+ /* No error expected, certificate is valid. */
+ if (failures)
+ return APR_EGENERAL;
+ else
+ return APR_SUCCESS;
+}
+
+/* Validate that we can connect successfully to an https server. */
+static void test_serf_ssl_handshake(CuTest *tc)
+{
+ test_baton_t *tb;
+ handler_baton_t handler_ctx[1];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
+ apr_status_t status;
+ test_server_message_t message_list[] = {
+ {CHUNKED_REQUEST(1, "1")},
+ };
+
+ test_server_action_t action_list[] = {
+ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
+ };
+
+
+ /* Set up a test context with a server */
+ apr_pool_t *test_pool = test_setup();
+ status = test_https_server_setup(&tb,
+ message_list, num_requests,
+ action_list, num_requests, 0,
+ NULL, /* default conn setup */
+ "test/server/serfserverkey.pem",
+ "test/server/serfservercert.pem",
+ ssl_server_cert_cb_expect_failures,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
+
+ test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
+ test_pool);
+
+ test_server_teardown(tb, test_pool);
+ test_teardown(test_pool);
+}
+
+static apr_status_t
+https_set_root_ca_conn_setup(apr_socket_t *skt,
+ serf_bucket_t **input_bkt,
+ serf_bucket_t **output_bkt,
+ void *setup_baton,
+ apr_pool_t *pool)
+{
+ serf_ssl_certificate_t *cacert, *rootcacert;
+ test_baton_t *tb = setup_baton;
+ apr_status_t status;
+
+ status = default_https_conn_setup(skt, input_bkt, output_bkt,
+ setup_baton, pool);
+ if (status)
+ return status;
+
+ status = serf_ssl_load_cert_file(&cacert, "test/server/serfcacert.pem",
+ pool);
+ if (status)
+ return status;
+ status = serf_ssl_trust_cert(tb->ssl_context, cacert);
+ if (status)
+ return status;
+
+ status = serf_ssl_load_cert_file(&rootcacert,
+ "test/server/serfrootcacert.pem",
+ pool);
+ if (status)
+ return status;
+ status = serf_ssl_trust_cert(tb->ssl_context, rootcacert);
+ if (status)
+ return status;
+
+ return status;
+}
+
+/* Validate that server certificate validation is ok when we
+ explicitly trust our self-signed root ca. */
+static void test_serf_ssl_trust_rootca(CuTest *tc)
+{
+ test_baton_t *tb;
+ handler_baton_t handler_ctx[1];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
+ apr_status_t status;
+ test_server_message_t message_list[] = {
+ {CHUNKED_REQUEST(1, "1")},
+ };
+
+ test_server_action_t action_list[] = {
+ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
+ };
+
+ /* Set up a test context with a server */
+ apr_pool_t *test_pool = test_setup();
+ status = test_https_server_setup(&tb,
+ message_list, num_requests,
+ action_list, num_requests, 0,
+ https_set_root_ca_conn_setup,
+ "test/server/serfserverkey.pem",
+ "test/server/serfservercert.pem",
+ ssl_server_cert_cb_expect_allok,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
+
+ test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
+ test_pool);
+
+ test_server_teardown(tb, test_pool);
+ test_teardown(test_pool);
+}
+
+/* Validate that when the application rejects the cert, the context loop
+ bails out with an error. */
+static void test_serf_ssl_application_rejects_cert(CuTest *tc)
+{
+ test_baton_t *tb;
+ handler_baton_t handler_ctx[1];
+ const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
+ apr_status_t status;
+ test_server_message_t message_list[] = {
+ {CHUNKED_REQUEST(1, "1")},
+ };
+
+ test_server_action_t action_list[] = {
+ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
+ };
+
+ /* Set up a test context with a server */
+ apr_pool_t *test_pool = test_setup();
+
+ /* The certificate is valid, but we tell serf to reject it by using the
+ ssl_server_cert_cb_expect_failures callback. */
+ status = test_https_server_setup(&tb,
+ message_list, num_requests,
+ action_list, num_requests, 0,
+ https_set_root_ca_conn_setup,
+ "test/server/serfserverkey.pem",
+ "test/server/serfservercert.pem",
+ ssl_server_cert_cb_expect_failures,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
+
+ status = test_helper_run_requests_no_check(tc, tb, num_requests,
+ handler_ctx, test_pool);
+ /* We expect an error from the certificate validation function. */
+ CuAssert(tc, "Application told serf the certificate should be rejected,"
+ " expected error!", status != APR_SUCCESS);
+
+ test_server_teardown(tb, test_pool);
+ test_teardown(test_pool);
+}
CuSuite *test_context(void)
{
@@ -1006,6 +1252,10 @@ CuSuite *test_context(void)
SUITE_ADD_TEST(suite, test_keepalive_limit_one_by_one);
SUITE_ADD_TEST(suite, test_keepalive_limit_one_by_one_and_burst);
SUITE_ADD_TEST(suite, test_serf_progress_callback);
+ SUITE_ADD_TEST(suite, test_serf_request_timeout);
+ SUITE_ADD_TEST(suite, test_serf_ssl_handshake);
+ SUITE_ADD_TEST(suite, test_serf_ssl_trust_rootca);
+ SUITE_ADD_TEST(suite, test_serf_ssl_application_rejects_cert);
return suite;
}