Mon, 16 Feb 2026 18:45:17 +0100
add test_http_client_io_simple
| src/server/proxy/httpclient.c | file | annotate | diff | comparison | revisions |
--- a/src/server/proxy/httpclient.c Mon Feb 16 17:43:14 2026 +0100 +++ b/src/server/proxy/httpclient.c Mon Feb 16 18:45:17 2026 +0100 @@ -451,7 +451,7 @@ // read the request buffer from sock and continue with client_send_request CxBuffer buf; - cxBufferInit(&buf, cxDefaultAllocator, NULL, len, CX_BUFFER_AUTO_EXTEND); + cxBufferInit(&buf, cxDefaultAllocator, NULL, len, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); char tmpbuf[1024]; int writes = 1; while(client->req_buffer_pos < client->req_buffer_len && writes < 2000000) { @@ -479,9 +479,129 @@ close(fds[0]); close(fds[1]); http_client_free(client); + cxBufferDestroy(&buf); + } +} + +typedef struct TestResponse { + int status; + char *msg; + CxBuffer *response; +} TestResponse; + +static int test_response_start(HttpClient *client, int status, char *msg, void *userdata) { + TestResponse *test = userdata; + test->status = status; + test->msg = strdup(msg); + return 0; +} + +static ssize_t test_response_body_write(HttpClient *client, void *buf, size_t size, void *userdata) { + TestResponse *test = userdata; + cxBufferWrite(buf, 1, size, test->response); + return size; +} + +static CX_TEST(test_http_client_io_simple) { + CX_TEST_DO { + EventHandler dummy; + HttpClient *client = http_client_new(&dummy); + + int fds[2]; + util_socketpair(fds); + util_socket_setnonblock(fds[0], 1); + util_socket_setnonblock(fds[1], 1); + client->socketfd = fds[0]; + int sock = fds[1]; + + // setup client + http_client_set_uri(client, "/test/uri/"); + http_client_set_method(client, "GET"); + http_client_add_request_header(client, cx_mutstr("Host"), cx_mutstr("localhost")); + http_client_add_request_header(client, cx_mutstr("Test1"), cx_mutstr("value1")); + http_client_add_request_header(client, cx_mutstr("Test2"), cx_mutstr("value2")); + create_req_buffer(client); + + size_t req_header_len = client->req_buffer_len; + + // response buffer + CxBuffer buf; + cxBufferInit(&buf, cxDefaultAllocator, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); + + TestResponse testr = { 0 }; + testr.response = &buf; + client->response_start = test_response_start; + client->response_start_userdata = &testr; + client->response_body_write = test_response_body_write; + client->response_body_write_userdata = &testr; + + // test IO + Event event; + event.cookie = client; + int ret = client_io(&dummy, &event); + CX_TEST_ASSERT(!client->error); + CX_TEST_ASSERT(ret == 1); + + // do IO and read request until the header is processed + size_t req_header_pos = 0; + char req_buf[4]; + while(req_header_pos < req_header_len) { + ssize_t r = read(sock, req_buf, 4); + if(r == 0) { + break; + } + CX_TEST_ASSERT(r > 0); + req_header_pos += r; + ret = client_io(&dummy, &event); + CX_TEST_ASSERT(!client->error); + CX_TEST_ASSERT(ret == 1); + } + CX_TEST_ASSERT(req_header_pos == req_header_len); + + char *response_str = + "HTTP/1.1 200 OK\r\n" + "Host: localhost\r\n" + "Content-length: 13\r\n" + "\r\n" + "Hello World!\n"; + size_t response_str_len = strlen(response_str); + size_t response_str_pos = 0; + + // send response and do IO + while(response_str_pos < response_str_len) { + size_t len = response_str_len - response_str_pos; + if(len > 3) { + //len = 3; + } + ssize_t w = write(sock, response_str + response_str_pos, len); + if(w == 0) { + break; + } + CX_TEST_ASSERT(w > 0); + response_str_pos += w; + + ret = client_io(&dummy, &event); + + CX_TEST_ASSERT(!client->error); + CX_TEST_ASSERT(ret == 1); + } + CX_TEST_ASSERT(response_str_pos == response_str_len); + CX_TEST_ASSERT(testr.status == 200); + CX_TEST_ASSERT(testr.msg); + CX_TEST_ASSERT(!strcmp(testr.msg, "OK")); + CX_TEST_ASSERT(testr.response->size == 13); + CX_TEST_ASSERT(!cx_strcmp(cx_strn(testr.response->space, testr.response->size), "Hello World!\n")); + + // cleanup + free(testr.msg); + close(fds[0]); + close(fds[1]); + http_client_free(client); + cxBufferDestroy(&buf); } } void http_client_add_tests(CxTestSuite *suite) { cx_test_register(suite, test_http_client_send_request); + cx_test_register(suite, test_http_client_io_simple); }