add test_io_httpstream_chunked_write_partial_writev

Tue, 17 Mar 2026 20:49:37 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 17 Mar 2026 20:49:37 +0100
changeset 734
a5f3e1e5e744
parent 733
66bde992ebd0
child 735
902b417ab6d2

add test_io_httpstream_chunked_write_partial_writev

src/server/test/io.c file | annotate | diff | comparison | revisions
src/server/test/io.h file | annotate | diff | comparison | revisions
src/server/test/main.c file | annotate | diff | comparison | revisions
src/server/util/io.c file | annotate | diff | comparison | revisions
--- a/src/server/test/io.c	Mon Mar 16 19:44:18 2026 +0100
+++ b/src/server/test/io.c	Tue Mar 17 20:49:37 2026 +0100
@@ -675,6 +675,41 @@
     }
 }
 
+CX_TEST(test_io_httpstream_chunked_write_partial_writev) {
+    Session *sn = testutil_session();
+    
+    TestIOStream *st = testutil_iostream(2048, TRUE);
+    IOStream *http = httpstream_new(sn->pool, (IOStream*)st);
+    httpstream_enable_chunked_write(http);
+    io_set_max_writes(1);
+    
+    CX_TEST_DO {
+    
+        memset(st->buf->space, 0, st->buf->capacity);
+
+        char *msg = "hello world!";
+        size_t msglen = strlen(msg);
+
+        // Test: write complete chunk header, zero data
+
+        st->max_write = 3;
+        ssize_t w = net_write(http, msg, msglen);
+        
+        CX_TEST_ASSERT(w == 0);
+        
+        st->max_write = 1000;
+        w = net_write(http, msg, msglen);
+        
+        CX_TEST_ASSERT(w == msglen);
+        
+        CX_TEST_ASSERT(!memcmp(st->buf->space, "c\r\nhello world!\r\n", st->buf->size));
+
+        testutil_destroy_session(sn);
+        testutil_iostream_destroy(st);
+    
+    }
+}
+
 CX_TEST(test_io_httpstream_chunked_write_data_2x) {
     Session *sn = testutil_session();
     
--- a/src/server/test/io.h	Mon Mar 16 19:44:18 2026 +0100
+++ b/src/server/test/io.h	Tue Mar 17 20:49:37 2026 +0100
@@ -57,6 +57,7 @@
 CX_TEST(test_io_httpstream_chunked_write_partial_data);
 CX_TEST(test_io_httpstream_chunked_write_partial_trailer);
 CX_TEST(test_io_httpstream_chunked_write_partial_trailer_partial_header);
+CX_TEST(test_io_httpstream_chunked_write_partial_writev);
 CX_TEST(test_io_httpstream_chunked_write_data_2x);
 CX_TEST(test_io_httpstream_chunked_write_xx_limit);
 
--- a/src/server/test/main.c	Mon Mar 16 19:44:18 2026 +0100
+++ b/src/server/test/main.c	Tue Mar 17 20:49:37 2026 +0100
@@ -147,6 +147,7 @@
     cx_test_register(suite, test_io_httpstream_chunked_write_partial_data);
     cx_test_register(suite, test_io_httpstream_chunked_write_partial_trailer);
     cx_test_register(suite, test_io_httpstream_chunked_write_partial_trailer_partial_header);
+    cx_test_register(suite, test_io_httpstream_chunked_write_partial_writev);
     cx_test_register(suite, test_io_httpstream_chunked_write_data_2x);
     cx_test_register(suite, test_io_httpstream_chunked_write_xx_limit);
     
@@ -209,6 +210,7 @@
     
     
     // http tests
+    /*
     http_client_add_tests(suite);
     cx_test_register(suite, test_http_client_simple_get1);
     cx_test_register(suite, test_http_client_simple_get_line_io);
@@ -219,6 +221,7 @@
     cx_test_register(suite, test_http_client_post_ctlen_large);
     cx_test_register(suite, test_http_client_get_incorrect_ctlen);
     cx_test_register(suite, test_http_client_broken_response);
+     * */
     
     // plugin tests
 #ifdef ENABLE_POSTGRESQL
--- a/src/server/util/io.c	Mon Mar 16 19:44:18 2026 +0100
+++ b/src/server/util/io.c	Tue Mar 17 20:49:37 2026 +0100
@@ -68,6 +68,8 @@
 #include "../daemon/event.h"
 #include <cx/printf.h>
 
+#include <openssl/err.h>
+
 IOStream native_io_funcs = {
     (io_write_f)net_sys_write,
     (io_writev_f)net_sys_writev,
@@ -490,6 +492,7 @@
         
         ssize_t wv = fd->writev(fd, io, iovec_len);
         if(wv <= 0) {
+            log_ereport(LOG_INFORM, "net_http_write chunk writev ret %d", (int)wv);
             st->st.io_errno = net_errno(st->fd);
             return wv;
         }
@@ -864,11 +867,17 @@
 
 ssize_t net_ssl_write(SSLStream *st, const void *buf, size_t nbytes) {
     int ret = SSL_write(st->ssl, buf, nbytes);
+    log_ereport(LOG_INFORM, "SSL_write(%p, %d) -> %d", buf, (int)nbytes, ret);
     if(ret <= 0) {
         st->error = SSL_get_error(st->ssl, ret);
         if(st->error == SSL_ERROR_WANT_WRITE || st->error == SSL_ERROR_WANT_READ) {
             st->st.io_errno = EWOULDBLOCK;
         } else {
+            log_ereport(LOG_FAILURE, "net_ssl_write SSL error: %d , nbytes: %d, ret: %d", st->error, (int)nbytes, ret);
+            unsigned long e;
+            while ((e = ERR_get_error())) {
+                fprintf(stderr, "%s\n", ERR_error_string(e, NULL));
+            }
             st->st.io_errno = -1;
         }
         ret = -1;
@@ -879,10 +888,13 @@
 ssize_t net_ssl_writev(SSLStream *st, struct iovec *iovec, int iovcnt) {
     ssize_t r = 0;
     for(int i=0;i<iovcnt;i++) {
+        int ml = iovec[i].iov_len > 10 ? 10 : iovec[i].iov_len;
         int ret = SSL_write(st->ssl, iovec[i].iov_base, iovec[i].iov_len);
+        log_ereport(LOG_INFORM, "SSL_write(%p {%.*s}, %d) -> %d", iovec[i].iov_base, ml, iovec[i].iov_base, (int)iovec[i].iov_len, ret);
         if(ret <= 0) {
             if(r == 0) {
                 st->error = SSL_get_error(st->ssl, ret);
+                log_ereport(LOG_FAILURE, "net_ssl_write SSL error: %d , iov_len: %d, ret: %d", st->error, (int)iovec[i].iov_len, ret);
                 if(st->error == SSL_ERROR_WANT_WRITE || st->error == SSL_ERROR_WANT_READ) {
                     st->st.io_errno = EWOULDBLOCK;
                 } else {

mercurial