Sat, 21 Feb 2026 11:17:37 +0100
add large io http client tests
| src/server/proxy/httpclient.c | file | annotate | diff | comparison | revisions |
--- a/src/server/proxy/httpclient.c Fri Feb 20 14:15:52 2026 +0100 +++ b/src/server/proxy/httpclient.c Sat Feb 21 11:17:37 2026 +0100 @@ -32,6 +32,7 @@ #include <cx/buffer.h> #include <cx/string.h> +#include <cx/printf.h> #include <stdlib.h> #include <string.h> #include <errno.h> @@ -891,7 +892,7 @@ } } -static CX_TEST_SUBROUTINE(test_http_client_io, const char *response_str, int status_code, const char *msg, CxBuffer *out_buf, size_t write_blocksz) { +static CX_TEST_SUBROUTINE(test_http_client_io, cxstring response, int status_code, const char *msg, CxBuffer *out_buf, size_t write_blocksz) { EventHandler dummy; HttpClient *client = http_client_new(&dummy); @@ -941,8 +942,9 @@ CX_TEST_ASSERT(ret == 1); } CX_TEST_ASSERT(req_header_pos == req_header_len); - - size_t response_str_len = strlen(response_str); + + const char *response_str = response.ptr; + size_t response_str_len = response.length; size_t response_str_pos = 0; // send response and do IO @@ -975,12 +977,12 @@ } static CX_TEST_SUBROUTINE(test_http_client_io_simple, size_t blocksz) { - char *response_str = + cxstring response_str = cx_str( "HTTP/1.1 200 OK\r\n" "Host: localhost\r\n" "Content-length: 13\r\n" "\r\n" - "Hello World!\n"; + "Hello World!\n"); CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz); @@ -1020,8 +1022,45 @@ } } +static CX_TEST_SUBROUTINE(test_http_client_io_large, size_t blocksz) { + int ctlen = 1024*1024*32; + CxBuffer *resp = cxBufferCreate(NULL, NULL, ctlen + 128, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); + cx_bprintf(resp, + "HTTP/1.1 200 OK\r\n" + "Host: localhost\r\n" + "Content-length: %d\r\n" + "\r\n", + ctlen); + size_t content_start = resp->pos; + CX_TEST_ASSERT(resp->pos + ctlen < resp->capacity); + memset(resp->space + resp->pos, 'x', ctlen); + resp->pos += ctlen; + resp->size += ctlen; + + CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); + + CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz); + CX_TEST_ASSERT(buf->size == ctlen); + CX_TEST_ASSERT(!memcmp(buf->space, resp->space + content_start, ctlen)); + + cxBufferFree(resp); + cxBufferFree(buf); +} + +static CX_TEST(test_http_client_io_large_128b) { + CX_TEST_DO { + CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 128); + } +} + +static CX_TEST(test_http_client_io_large_4096b) { + CX_TEST_DO { + CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 1024); + } +} + static CX_TEST_SUBROUTINE(test_http_client_io_chunked_transfer, size_t blocksz) { - char *response_str = + cxstring response_str = cx_str( "HTTP/1.1 200 OK\r\n" "Host: localhost\r\n" "Transfer-encoding: chunked\r\n" @@ -1029,7 +1068,7 @@ "d\r\n" "Hello World!\n" "\r\n" - "0\r\n\r\n"; + "0\r\n\r\n"); CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz); @@ -1063,6 +1102,76 @@ } } +static CX_TEST_SUBROUTINE(test_http_client_io_large_chunked_transfer, size_t blocksz) { + int chunk1 = 1024*1024*2; + int chunk2 = 1024*128; + int chunk3 = 123; + int chunk4 = 1024*1024*5; + int chunk5 = 1024*16; + + char *chunkbuf = malloc(chunk4); + + int ctlen = chunk1 + chunk2 + chunk3 + chunk4 + chunk5; + CxBuffer *resp = cxBufferCreate(NULL, NULL, ctlen * 128, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); + cx_bprintf(resp, + "HTTP/1.1 200 OK\r\n" + "Transfer-encoding: chunked\r\n" + "\r\n", + ctlen); + size_t content_start = resp->pos; + CX_TEST_ASSERT(resp->pos + ctlen < resp->capacity); + + memset(chunkbuf, 'x', chunk1); + cx_bprintf(resp, "%x\r\n", chunk1); + int chunk1_pos = resp->pos; + cxBufferWrite(chunkbuf, 1, chunk1, resp); + cxBufferPutString(resp, "\r\n"); + + memset(chunkbuf, '2', chunk2); + cx_bprintf(resp, "%x\r\n", chunk2); + int chunk2_pos = resp->pos; + cxBufferWrite(chunkbuf, 1, chunk2, resp); + cxBufferPutString(resp, "\r\n"); + + memset(chunkbuf, 'c', chunk3); + cx_bprintf(resp, "%x\r\n", chunk3); + int chunk3_pos = resp->pos; + cxBufferWrite(chunkbuf, 1, chunk3, resp); + cxBufferPutString(resp, "\r\n"); + + memset(chunkbuf, '4', chunk4); + cx_bprintf(resp, "%x\r\n", chunk4); + int chunk4_pos = resp->pos; + cxBufferWrite(chunkbuf, 1, chunk4, resp); + cxBufferPutString(resp, "\r\n"); + + memset(chunkbuf, 'z', chunk5); + cx_bprintf(resp, "%x\r\n", chunk5); + int chunk5_pos = resp->pos; + cxBufferWrite(chunkbuf, 1, chunk5, resp); + cxBufferPutString(resp, "\r\n0\r\n\r\n"); + + + CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); + + CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz); + CX_TEST_ASSERT(buf->size == ctlen); + CX_TEST_ASSERT(!memcmp(buf->space, resp->space + chunk1_pos, chunk1)); + CX_TEST_ASSERT(!memcmp(buf->space + chunk1, resp->space + chunk2_pos, chunk2)); + CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2, resp->space + chunk3_pos, chunk3)); + CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3, resp->space + chunk4_pos, chunk4)); + CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3 + chunk4, resp->space + chunk5_pos, chunk5)); + + cxBufferFree(resp); + cxBufferFree(buf); +} + +static CX_TEST(test_http_client_io_large_chunked_transfer_1024b) { + CX_TEST_DO { + CX_TEST_CALL_SUBROUTINE(test_http_client_io_large_chunked_transfer, 1024); + } +} + void http_client_add_tests(CxTestSuite *suite) { cx_test_register(suite, test_http_client_send_request); cx_test_register(suite, test_http_client_send_request_body_chunked); @@ -1074,8 +1183,11 @@ cx_test_register(suite, test_http_client_io_simple_3b); cx_test_register(suite, test_http_client_io_simple_16b); cx_test_register(suite, test_http_client_io_simple_512b); + cx_test_register(suite, test_http_client_io_large_128b); + cx_test_register(suite, test_http_client_io_large_4096b); cx_test_register(suite, test_http_client_io_chunked_transfer_1b); cx_test_register(suite, test_http_client_io_chunked_transfer_2b); cx_test_register(suite, test_http_client_io_chunked_transfer_8b); cx_test_register(suite, test_http_client_io_chunked_transfer_64b); + cx_test_register(suite, test_http_client_io_large_chunked_transfer_1024b); }