add skeleton for postprocessor test

This commit is contained in:
Christian Grothoff committed 2024-08-01 09:14:31 +02:00
1 parent 517976484a
commit cc3433f697
5 files changed
+313 -1

No files matched your search

+8 -1
View File
@@ -25,7 +25,8 @@ $(top_builddir)/src/mhd2/libmicrohttpd2.la: $(top_builddir)/src/mhd2/Makefile
$(am__cd) $(top_builddir)/src/mhd2 && $(MAKE) $(AM_MAKEFLAGS) libmicrohttpd2.la
check_PROGRAMS = \
test_client_server
test_client_server \
test_postprocessor
TESTS = $(check_PROGRAMS)
@@ -47,3 +48,9 @@ test_client_server_SOURCES = \
test_client_server.c
test_client_server_LDADD = \
libmhdt.la
test_postprocessor_SOURCES = \
test_postprocessor.c
test_postprocessor_LDADD = \
libmhdt.la
+65
View File
@@ -144,6 +144,44 @@ MHDT_client_chunk_data (void *cls,
const struct MHDT_PhaseContext *pc);
/**
* Arguments and state for the #MHDT_server_reply_check_post and
* #MHDT_client_do_post() functions.
*/
struct MHDT_PostInstructions
{
/**
* Encoding to use when decoding.
*/
enum MHD_HTTP_PostEncoding enc;
/**
* size to use for the buffer.
*/
size_t buffer_size;
/**
* Size above which we switch to stream processing.
*/
size_t auto_stream_size;
};
/**
* Perform POST request suitable for testing the
* post processor and expect a
* 204 No Content response.
*
* @param cls 0-terminated string with `struct MHDT_PostInstructions`
* @param pc context for the client
* @return error message, NULL on success
*/
const char *
MHDT_client_do_post (
void *cls,
const struct MHDT_PhaseContext *pc);
/**
* A phase defines some server and client-side
* behaviors to execute.
@@ -386,6 +424,33 @@ MHDT_server_reply_check_upload (
uint_fast64_t upload_size);
/**
* Checks that the client request against the expected
* POST data. If so, returns #MHD_HTTP_STATUS_NO_CONTENT.
*
* @param cls expected upload data as a 0-terminated string.
* @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_check_post (
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);
/**
* Initialize options for an MHD daemon for a test.
*
@@ -566,3 +566,60 @@ MHDT_client_chunk_data (
curl_easy_cleanup (c);
return NULL;
}
const char *
MHDT_client_do_post (
void *cls,
const struct MHDT_PhaseContext *pc)
{
struct MHDT_PostInstructions *pi = cls;
const char *text = "fixme";
struct ReadBuffer rb = {
.buf = text,
.len = strlen (text),
.chunks = 2
};
CURL *c;
c = curl_easy_init ();
if (NULL == c)
return "Failed to initialize Curl handle";
if (CURLE_OK !=
curl_easy_setopt (c,
CURLOPT_URL,
pc->base_url))
{
curl_easy_cleanup (c);
return "Failed to set URL for curl request";
}
if (CURLE_OK !=
curl_easy_setopt (c,
CURLOPT_UPLOAD,
1L))
{
curl_easy_cleanup (c);
return "Failed to set PUT method for curl request";
}
if (CURLE_OK !=
curl_easy_setopt (c,
CURLOPT_READFUNCTION,
&read_cb))
{
curl_easy_cleanup (c);
return "Failed to set READFUNCTION for curl request";
}
if (CURLE_OK !=
curl_easy_setopt (c,
CURLOPT_READDATA,
&rb))
{
curl_easy_cleanup (c);
return "Failed to set READFUNCTION for curl request";
}
PERFORM_REQUEST (c);
CHECK_STATUS (c,
MHD_HTTP_STATUS_NO_CONTENT);
curl_easy_cleanup (c);
return NULL;
}
@@ -448,3 +448,84 @@ MHDT_server_reply_chunked_text (
cc,
&free));
}
/**
* "Stream" reader for POST data.
* This callback is called to incrementally process parsed POST data sent by
* the client.
*
* @param cls user-specified closure
* @param name 0-terminated key for the value
* @param filename name of the uploaded file, NULL if not known
* @param content_type mime-type of the data, NULL if not known
* @param encoding the encoding of the data
* @param data pointer to @a size bytes of data at the
* specified @a off offset,
* NOT zero-terminated
* @param off offset of data in the overall value
* @param size number of bytes in @a data available
* @return action specifying how to proceed:
* #MHD_upload_action_continue() if all is well,
* #MHD_upload_action_suspend() to stop reading the upload until
* the request is resumed,
* #MHD_upload_action_abort_request() to close the socket,
* or a response to discard the rest of the upload and transmit
* the response
* @ingroup action
*/
static const struct MHD_UploadAction *
post_stream_reader (void *cls,
const struct MHD_String *name,
const struct MHD_StringNullable *filename,
const struct MHD_StringNullable *content_type,
const struct MHD_StringNullable *encoding,
const void *data,
uint_fast64_t off,
size_t size)
{
struct MHDT_PostInstructions *pi = cls;
return MHD_upload_action_continue (NULL);
}
/**
* The callback to be called when finished with processing
* of the postprocessor upload data.
* @param req the request
* @param cls the closure
* @return the action to proceed
*/
static const struct MHD_UploadAction *
post_stream_done (struct MHD_Request *req,
void *cls)
{
struct MHDT_PostInstructions *pi = cls;
return MHD_upload_action_from_response (
req,
MHD_response_from_empty (
MHD_HTTP_STATUS_NO_CONTENT));
}
const struct MHD_Action *
MHDT_server_reply_check_post (
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)
{
struct MHDT_PostInstructions *pi = cls;
return MHD_action_parse_post (request,
pi->buffer_size,
pi->auto_stream_size,
pi->enc,
&post_stream_reader,
pi,
&post_stream_done,
pi);
}
@@ -0,0 +1,102 @@
/*
This file is part of GNU libmicrohttpd
Copyright (C) 2016, 2024 Christian Grothoff & Evgeny Grin (Karlson2k)
GNU libmicrohttpd is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
GNU libmicrohttpd is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file test_postprocessor.c
* @brief test with client against server
* @author Christian Grothoff
*/
#include <microhttpd2.h>
#include "mhd_config.h"
#include "libtest.h"
int
main (int argc, char *argv[])
{
struct MHD_DaemonOptionAndValue thread1auto[] = {
MHD_D_OPTION_POLL_SYSCALL (MHD_SPS_AUTO),
MHD_D_OPTION_WM_WORKER_THREADS (1),
MHD_D_OPTION_TERMINATE ()
};
struct ServerType
{
const char *label;
MHDT_ServerSetup server_setup;
void *server_setup_cls;
MHDT_ServerRunner server_runner;
void *server_runner_cls;
} configs[] = {
{
.label = "auto-selected mode, single threaded",
.server_setup = &MHDT_server_setup_minimal,
.server_setup_cls = thread1auto,
.server_runner = &MHDT_server_run_minimal,
},
{
.label = "END"
}
};
struct MHDT_PostInstructions simple_pi = {
.enc = MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
.buffer_size = 32,
.auto_stream_size = 16
};
struct MHDT_Phase phases[] = {
{
.label = "simple post",
.server_cb = &MHDT_server_reply_check_post,
.server_cb_cls = &simple_pi,
.client_cb = &MHDT_client_do_post,
.client_cb_cls = &simple_pi,
.timeout_ms = 2500,
},
{
.label = NULL,
},
};
unsigned int i;
(void) argc; /* Unused. Silence compiler warning. */
(void) argv; /* Unused. Silence compiler warning. */
for (i = 0; NULL != configs[i].server_setup; i++)
{
int ret;
fprintf (stderr,
"Running tests with server setup `%s'\n",
configs[i].label);
ret = MHDT_test (configs[i].server_setup,
configs[i].server_setup_cls,
configs[i].server_runner,
configs[i].server_runner_cls,
phases);
if (0 != ret)
{
fprintf (stderr,
"Test failed with server of type `%s' (%u)\n",
configs[i].label,
i);
return ret;
}
}
return 0;
}