commit 6abf440a7148642864d570c313eca3f29ac4be64
parent d85d8e86350e1788ad5f8915ba9eb64e9d718bcc
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Thu, 27 Aug 2026 11:33:26 +0200
test_client_server: added testing on responses with unknwon size
Diffstat:
4 files changed, 121 insertions(+), 14 deletions(-)
diff --git a/src/tests/client_server/libtest.h b/src/tests/client_server/libtest.h
@@ -559,6 +559,39 @@ MHDT_server_reply_file (
/**
+ * Writes text from @a cls to a temporary file and then uses the file
+ * descriptor to serve the content to the client without indicating the size
+ * of the content.
+ *
+ * The reply is sent by chunked encoding (HTTP/1.1) or is terminated by
+ * the end of the stream (HTTP/2), the size of the content is detected by
+ * the end of the file.
+ *
+ * @param cls argument given together with the function
+ * pointer when the handler was registered with MHD
+ * @param request the request object
+ * @param path the requested uri (without arguments after "?")
+ * @param method the HTTP method used (#MHD_HTTP_METHOD_GET,
+ * #MHD_HTTP_METHOD_PUT, etc.)
+ * @param upload_size the size of the message upload content payload,
+ * #MHD_SIZE_UNKNOWN for chunked uploads (if the
+ * final chunk has not been processed yet)
+ * @return action how to proceed, NULL
+ * if the request must be aborted due to a serious
+ * error while handling the request (implies closure
+ * of underling data stream, for HTTP/1.1 it means
+ * socket closure).
+ */
+const struct MHD_Action *
+MHDT_server_reply_file_unknown_size (
+ void *cls,
+ struct MHD_Request *MHD_RESTRICT request,
+ const struct MHD_String *MHD_RESTRICT path,
+ enum MHD_HTTP_Method method,
+ uint_fast64_t upload_size);
+
+
+/**
* Returns an emtpy response with a custom header
* set from @a cls and the #MHD_HTTP_STATUS_NO_CONTENT.
*
diff --git a/src/tests/client_server/libtest_convenience_server_reply.c b/src/tests/client_server/libtest_convenience_server_reply.c
@@ -84,23 +84,20 @@ MHDT_server_reply_text (
}
-const struct MHD_Action *
-MHDT_server_reply_file (
- void *cls,
- struct MHD_Request *MHD_RESTRICT request,
- const struct MHD_String *MHD_RESTRICT path,
- enum MHD_HTTP_Method method,
- uint_fast64_t upload_size)
+/**
+ * Create a temporary file and put the @a text to it.
+ * Exit the test if the file cannot be created or written.
+ *
+ * @param text the text to put to the file
+ * @return the FD of the file with the @a text
+ */
+static int
+tmpfile_with_text (const char *text)
{
- const char *text = cls;
size_t written = 0u;
size_t tlen = strlen (text);
int fd;
- (void)path;
- (void)method;
- (void)upload_size; /* Unused */
-
fd = MHDT_create_tmpfile ();
if (-1 == fd)
{
@@ -134,12 +131,53 @@ MHDT_server_reply_file (
fflush (stderr);
exit (99);
}
+ return fd;
+}
+
+
+const struct MHD_Action *
+MHDT_server_reply_file (
+ void *cls,
+ struct MHD_Request *MHD_RESTRICT request,
+ const struct MHD_String *MHD_RESTRICT path,
+ enum MHD_HTTP_Method method,
+ uint_fast64_t upload_size)
+{
+ const char *text = cls;
+
+ (void)path;
+ (void)method;
+ (void)upload_size; /* Unused */
+
+ return MHD_action_from_response (
+ request,
+ MHD_response_from_fd (MHD_HTTP_STATUS_OK,
+ tmpfile_with_text (text),
+ 0 /* offset */,
+ strlen (text)));
+}
+
+
+const struct MHD_Action *
+MHDT_server_reply_file_unknown_size (
+ void *cls,
+ struct MHD_Request *MHD_RESTRICT request,
+ const struct MHD_String *MHD_RESTRICT path,
+ enum MHD_HTTP_Method method,
+ uint_fast64_t upload_size)
+{
+ const char *text = cls;
+
+ (void)path;
+ (void)method;
+ (void)upload_size; /* Unused */
+
return MHD_action_from_response (
request,
MHD_response_from_fd (MHD_HTTP_STATUS_OK,
- fd,
+ tmpfile_with_text (text),
0 /* offset */,
- tlen));
+ MHD_SIZE_UNKNOWN));
}
diff --git a/src/tests/client_server/test_client_server.c b/src/tests/client_server/test_client_server.c
@@ -232,6 +232,23 @@ main (int argc, char *argv[])
.timeout_ms = 5000,
},
{
+ .label = "simple get, file response, unknown size",
+ .server_cb = &MHDT_server_reply_file_unknown_size,
+ .server_cb_cls = (void *)"Hello world",
+ .client_cb = &MHDT_client_get_root,
+ .client_cb_cls = "Hello world",
+ .timeout_ms = 2500,
+ },
+ {
+ /* The end of the content is detected by the end of the file */
+ .label = "medium body get, file response, unknown size",
+ .server_cb = &MHDT_server_reply_file_unknown_size,
+ .server_cb_cls = medium_text,
+ .client_cb = &MHDT_client_get_root,
+ .client_cb_cls = medium_text,
+ .timeout_ms = 5000,
+ },
+ {
.label = "medium body get, file response",
.server_cb = &MHDT_server_reply_file,
.server_cb_cls = medium_text,
diff --git a/src/tests/client_server/test_http2.c b/src/tests/client_server/test_http2.c
@@ -200,6 +200,25 @@ main (int argc, char *argv[])
.http_version = 2,
},
{
+ .label = "simple get, file response, unknown size",
+ .server_cb = &MHDT_server_reply_file_unknown_size,
+ .server_cb_cls = (void *)"Hello world",
+ .client_cb = &MHDT_client_get_root,
+ .client_cb_cls = "Hello world",
+ .timeout_ms = 2500,
+ .http_version = 2,
+ },
+ {
+ /* The end of the content is detected by the end of the file */
+ .label = "medium body get, file response, unknown size",
+ .server_cb = &MHDT_server_reply_file_unknown_size,
+ .server_cb_cls = medium_text,
+ .client_cb = &MHDT_client_get_root,
+ .client_cb_cls = medium_text,
+ .timeout_ms = 5000,
+ .http_version = 2,
+ },
+ {
.label = "medium body get, file response",
.server_cb = &MHDT_server_reply_file,
.server_cb_cls = medium_text,