--- a/src/server/proxy/httpclient.c Sun Feb 15 12:24:38 2026 +0100 +++ b/src/server/proxy/httpclient.c Sun Feb 15 13:30:29 2026 +0100 @@ -359,7 +359,69 @@ static CX_TEST(test_http_client_send_request) { 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]; + + // create a large test buffer, that is bigger than the socket buffer + // 32mb should be enough + size_t len = 32*1024*1024; + char *str = malloc(len); + // init the buffer with random data + for(size_t i=0;i<len;i+=sizeof(int)) { + int *p = (int*)(str+i); + *p = rand();; + } + + client->req_buffer = str; + client->req_buffer_len = len; + + // test client_send_request + + int ret = client_send_request(client); + // It is very likely that the first client_send_request call doesn't + // fully write the request buffer to the socket + // In that case it returns 1 but without the error flag + CX_TEST_ASSERT(ret == 1 && !client->error); + CX_TEST_ASSERT(client->req_buffer_pos > 0); + CX_TEST_ASSERT(client->req_buffer_pos < len); + + // read the request buffer from sock and continue with client_send_request + CxBuffer buf; + cxBufferInit(&buf, cxDefaultAllocator, NULL, len, CX_BUFFER_AUTO_EXTEND); + char tmpbuf[1024]; + int writes = 1; + while(client->req_buffer_pos < client->req_buffer_len && writes < 2000000) { + ssize_t r = read(sock, tmpbuf, 1024); + CX_TEST_ASSERT(r >= 0); + cxBufferWrite(tmpbuf, 1, r, &buf); + ret = client_send_request(client); + CX_TEST_ASSERT(ret == 0 || (ret == 1 && !client->error)); + + writes++; + } + CX_TEST_ASSERT(client->req_buffer_pos == client->req_buffer_len); + + // finish reading the request buffer from sock + ssize_t r; + while((r = read(sock, tmpbuf, 1024)) > 0 && writes < 2000000) { + cxBufferWrite(tmpbuf, 1, r, &buf); + writes++; + } + + CX_TEST_ASSERT(buf.size == len); + CX_TEST_ASSERT(!memcmp(str, buf.space, len)); + + // cleanup + close(fds[0]); + close(fds[1]); + http_client_free(client); } }