commit 914e7d9bda7ee8ed47bd99dffbfcc17917cd7ea7
parent 976c3a99f2a1c89fe5ad944e2dea2a5921b7f53d
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 7 Dec 2025 00:31:03 +0100
tons of header and cookie parsing tests
Diffstat:
1 file changed, 519 insertions(+), 15 deletions(-)
diff --git a/src/tests/raw/test_raw.c b/src/tests/raw/test_raw.c
@@ -107,6 +107,416 @@ static struct Test tests[] = {
.expect_parser = "H-Host:example.com",
},
{
+ .name = "Multi-header HTTP/1.1 GET with query parameters",
+ .upload = "GET /?k=v&a HTTP/1.1\r\nHost: example.com\r\nKey: value\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-Key:value\nQ-k:v\nQ-a",
+ },
+ {
+ .name = "Empty header value",
+ .upload = "GET / HTTP/1.1\r\nHost: example.com\r\nX-Empty:\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-X-Empty:",
+ },
+ {
+ .name = "Header with leading/trailing whitespace",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nX-Space: value \r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-X-Space:value",
+ },
+ {
+ .name = "Multiple headers with same name",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nX-Dup: first\r\nX-Dup: second\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-X-Dup:first",
+ },
+ {
+ .name = "Case insensitive header names",
+ .upload =
+ "GET / HTTP/1.1\r\nhost: example.com\r\nContent-TYPE: text/plain\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-Content-Type:text/plain",
+ },
+ {
+ .name = "Query parameter with empty value",
+ .upload = "GET /?key= HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-key:",
+ },
+ {
+ .name = "Query parameter without value",
+ .upload = "GET /?flag HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-flag",
+ },
+ {
+ .name = "Multiple query parameters",
+ .upload = "GET /?a=1&b=2&c=3 HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-a:1\nQ-b:2\nQ-c:3",
+ },
+ {
+ .name = "URL encoded query parameter",
+ .upload =
+ "GET /?name=hello%20world&special=%21%40%23 HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-name:hello world\nQ-special:!@#",
+ },
+ {
+ .name = "Simple cookie",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nCookie: session=abc123\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nC-session:abc123",
+ },
+ {
+ .name = "Multiple cookies in one header",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nCookie: a=1; b=2; c=3\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nC-a:1\nC-b:2\nC-c:3",
+ },
+#if COMPATIBILITY_QUESTION
+ {
+ .name = "Cookie with spaces",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nCookie: key = value\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nC-key:value",
+ },
+#endif
+ {
+ .name = "POST with Content-Length",
+ .upload =
+ "POST /submit HTTP/1.1\r\nHost: example.com\r\nContent-Length: 5\r\n\r\nhello",
+ .expect_method = MHD_HTTP_METHOD_POST,
+ .expect_path = "/submit",
+ .expect_upload_size = 5,
+ .expect_parser = "H-Host:example.com\nH-Content-Length:5",
+ },
+#if VERY_BAD_BUG
+ {
+ .name = "Path with special characters",
+ .upload =
+ "GET /path/to/resource%20file.html HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/path/to/resource file.html",
+ .expect_parser = "H-Host:example.com",
+ },
+#endif
+ {
+ .name = "Long header value",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nX-Long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser =
+ "H-Host:example.com\nH-X-Long:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ },
+ {
+ .name = "Query string with equals sign in value",
+ .upload = "GET /?expr=a=b HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-expr:a=b",
+ },
+ {
+ .name = "Mixed query parameters with and without values",
+ .upload =
+ "GET /?debug&level=5&verbose HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-debug\nQ-level:5\nQ-verbose",
+ },
+#if PARSER_BUG
+ {
+ .name = "Continuation header (folded)",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nX-Multi: line one\r\n line two\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-X-Multi:line one line two",
+ },
+#endif
+ {
+ .name = "Empty query string",
+ .upload = "GET /? HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com",
+ },
+#if UNDERSPECIFIED_LIKELY_BAD
+ {
+ .name = "Fragment in URI (should probably be stripped!)",
+ .upload = "GET /page#section HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/page",
+ .expect_parser = "H-Host:example.com",
+ },
+#endif
+ {
+ .name = "PUT request with headers",
+ .upload =
+ "PUT /resource HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/json\r\nContent-Length: 0\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_PUT,
+ .expect_path = "/resource",
+ .expect_upload_size = 0,
+ .expect_parser =
+ "H-Host:example.com\nH-Content-Type:application/json\nH-Content-Length:0",
+ },
+ {
+ .name = "DELETE request",
+ .upload = "DELETE /resource/123 HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_DELETE,
+ .expect_path = "/resource/123",
+ .expect_parser = "H-Host:example.com",
+ },
+
+ {
+ .name = "Header with colon in value",
+ .upload = "GET / HTTP/1.1\r\nHost: example.com\r\nX-Time: 12:34:56\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-X-Time:12:34:56",
+ },
+ {
+ .name = "Cookie with empty value",
+ .upload = "GET / HTTP/1.1\r\nHost: example.com\r\nCookie: empty=\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nC-empty:",
+ },
+ {
+ .name = "Query parameter with plus sign encoding",
+ .upload = "GET /?text=hello+world HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-text:hello world",
+ },
+ {
+ .name = "Multiple Cookie headers",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nCookie: a=1\r\nCookie: b=2\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nC-a:1\nC-b:2",
+ },
+ {
+ .name = "HEAD request",
+ .upload = "HEAD /resource HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_HEAD,
+ .expect_path = "/resource",
+ .expect_parser = "H-Host:example.com",
+ },
+ {
+ .name = "OPTIONS request",
+ .upload = "OPTIONS * HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_OPTIONS,
+ .expect_path = "*",
+ .expect_parser = "H-Host:example.com",
+ },
+ {
+ .name = "Query with ampersand in value",
+ .upload = "GET /?code=a%26b HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-code:a&b",
+ },
+ {
+ .name = "Query with percent sign in value",
+ .upload = "GET /?percent=100%25 HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-percent:100%",
+ },
+ {
+ .name = "Root path with trailing slash",
+ .upload = "GET // HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "//",
+ .expect_parser = "H-Host:example.com",
+ },
+ {
+ .name = "Deep path nesting",
+ .upload = "GET /a/b/c/d/e/f/g HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/a/b/c/d/e/f/g",
+ .expect_parser = "H-Host:example.com",
+ },
+ {
+ .name = "Authorization header",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nAuthorization: Bearer token123\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-Authorization:Bearer token123",
+ },
+ {
+ .name = "User-Agent header",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nUser-Agent: Mozilla/5.0\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-User-Agent:Mozilla/5.0",
+ },
+ {
+ .name = "Accept header with multiple values",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nAccept: text/html, application/json\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-Accept:text/html, application/json",
+ },
+ {
+ .name = "Connection keep-alive",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: keep-alive\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-Connection:keep-alive",
+ },
+ {
+ .name = "Query with duplicate parameters",
+ .upload = "GET /?id=1&id=2&id=3 HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-id:1",
+ },
+ {
+ .name = "Cookie with quoted value",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nCookie: session=\"abc123\"\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nC-session:abc123",
+ },
+ {
+ .name = "Query with UTF-8 encoding",
+ .upload = "GET /?name=%E2%9C%93 HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-name:✓",
+ },
+ {
+ .name = "Referer header",
+ .upload =
+ "GET /page HTTP/1.1\r\nHost: example.com\r\nReferer: https://google.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/page",
+ .expect_parser = "H-Host:example.com\nH-Referer:https://google.com",
+ },
+ {
+ .name = "Content-Type with charset",
+ .upload =
+ "POST / HTTP/1.1\r\nHost: example.com\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 0\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_POST,
+ .expect_path = "/",
+ .expect_upload_size = 0,
+ .expect_parser =
+ "H-Host:example.com\nH-Content-Type:text/html; charset=utf-8\nH-Content-Length:0",
+ },
+ {
+ .name = "Cache-Control header",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nCache-Control: no-cache\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-Cache-Control:no-cache",
+ },
+ {
+ .name = "If-None-Match header",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nIf-None-Match: \"etag123\"\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-If-None-Match:\"etag123\"",
+ },
+ {
+ .name = "Range header",
+ .upload =
+ "GET /file HTTP/1.1\r\nHost: example.com\r\nRange: bytes=0-1023\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/file",
+ .expect_parser = "H-Host:example.com\nH-Range:bytes=0-1023",
+ },
+ {
+ .name = "X-Forwarded-For header",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nX-Forwarded-For: 192.168.1.1\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nH-X-Forwarded-For:192.168.1.1",
+ },
+ {
+ .name = "Query with empty parameter name",
+ .upload = "GET /?=value HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-:value",
+ },
+#if QUESTIONABLE_TEST
+ {
+ .name = "Absolute URI in request line",
+ .upload = "GET http://example.com/ HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com",
+ },
+#endif
+ {
+ .name = "Query with semicolon separator",
+ .upload = "GET /?a=1;b=2 HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-a:1;b=2",
+ },
+ {
+ .name = "Cookie with special characters",
+ .upload =
+ "GET / HTTP/1.1\r\nHost: example.com\r\nCookie: data=value_with-special.chars\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nC-data:value_with-special.chars",
+ },
+ {
+ .name = "Minimal HTTP/1.0 request with path only",
+ .upload = "GET /path HTTP/1.0\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/path",
+ },
+ {
+ .name = "POST with form data Content-Type",
+ .upload =
+ "POST /form HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 0\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_POST,
+ .expect_path = "/form",
+ .expect_upload_size = 0,
+ .expect_parser =
+ "H-Host:example.com\nH-Content-Type:application/x-www-form-urlencoded\nH-Content-Length:0",
+ },
+ {
+ .name = "Query with trailing ampersand",
+ .upload = "GET /?a=1& HTTP/1.1\r\nHost: example.com\r\n\r\n",
+ .expect_method = MHD_HTTP_METHOD_GET,
+ .expect_path = "/",
+ .expect_parser = "H-Host:example.com\nQ-a:1",
+ },
+
+ {
.name = NULL,
}
};
@@ -137,9 +547,11 @@ check_headers (struct MHD_Request *MHD_RESTRICT request,
tok = strtok (NULL,
"\n"))
{
+ char dummy;
+
if (2 ==
sscanf (tok,
- "H-%[^:]:%s",
+ "H-%[^:]:%[^\n]s",
key,
value))
{
@@ -160,15 +572,16 @@ check_headers (struct MHD_Request *MHD_RESTRICT request,
value)) )
{
fprintf (stderr,
- "Wrong header value `%s' under key `%s'\n",
+ "Wrong header value `%s' under key `%s', expected `%s'\n",
have.cstr,
- key);
+ key,
+ value);
ok = false;
}
}
else if (2 ==
sscanf (tok,
- "C-%[^:]:%s",
+ "C-%[^:]:%[^\n]",
key,
value))
{
@@ -189,15 +602,16 @@ check_headers (struct MHD_Request *MHD_RESTRICT request,
value)) )
{
fprintf (stderr,
- "Wrong cookie value `%s' under key `%s'\n",
+ "Wrong cookie value `%s' under key `%s', expected `%s'\n",
have.cstr,
- key);
+ key,
+ value);
ok = false;
}
}
else if (2 ==
sscanf (tok,
- "Q-%[^:]:%s",
+ "Q-%[^:]:%[^\n]",
key,
value))
{
@@ -218,15 +632,16 @@ check_headers (struct MHD_Request *MHD_RESTRICT request,
value)) )
{
fprintf (stderr,
- "Wrong URI query parameter value `%s' under key `%s'\n",
+ "Wrong URI query parameter value `%s' under key `%s', expected `%s'\n",
have.cstr,
- key);
+ key,
+ value);
ok = false;
}
}
else if (1 ==
sscanf (tok,
- "H-%[^:]:%s",
+ "H-%[^:]:%[^\n]",
key,
value))
{
@@ -241,11 +656,43 @@ check_headers (struct MHD_Request *MHD_RESTRICT request,
"Expected header `%s' missing\n",
key);
ok = false;
+ } /* HTTP header can never be "NULL", only empty string */
+ else if ( (NULL == have.cstr) ||
+ (0 != strcmp (have.cstr,
+ "")) )
+ {
+ fprintf (stderr,
+ "Unexpected non-empty header value `%s' under key `%s'\n",
+ have.cstr,
+ key);
+ ok = false;
}
- else if (NULL != have.cstr)
+ }
+ else if (2 ==
+ sscanf (tok,
+ "C-%[^:]%c%[^\n]",
+ key,
+ &dummy,
+ value))
+ {
+ struct MHD_StringNullable have;
+
+ if (! MHD_request_get_value (request,
+ MHD_VK_COOKIE,
+ key,
+ &have))
+ {
+ fprintf (stderr,
+ "Expected cookie `%s' missing\n",
+ key);
+ ok = false;
+ }
+ else if ( (NULL == have.cstr) ||
+ (0 != strcmp (have.cstr,
+ "")) )
{
fprintf (stderr,
- "Unexpected non-NULL header value `%s' under key `%s'\n",
+ "Unexpected non-empty cookie value `%s' under key `%s'\n",
have.cstr,
key);
ok = false;
@@ -253,7 +700,7 @@ check_headers (struct MHD_Request *MHD_RESTRICT request,
}
else if (1 ==
sscanf (tok,
- "C-%[^:]:%s",
+ "C-%[^:]:%[^\n]",
key,
value))
{
@@ -278,9 +725,39 @@ check_headers (struct MHD_Request *MHD_RESTRICT request,
ok = false;
}
}
+ else if (2 ==
+ sscanf (tok,
+ "Q-%[^:]%c%[^\n]",
+ key,
+ &dummy,
+ value))
+ {
+ struct MHD_StringNullable have;
+
+ if (! MHD_request_get_value (request,
+ MHD_VK_URI_QUERY_PARAM,
+ key,
+ &have))
+ {
+ fprintf (stderr,
+ "Expected URI query parameter `%s' missing\n",
+ key);
+ ok = false;
+ }
+ else if ( (NULL == have.cstr) ||
+ (0 != strcmp (have.cstr,
+ "")) )
+ {
+ fprintf (stderr,
+ "Unexpected non-empty URI query parameter value `%s' under key `%s'\n",
+ have.cstr,
+ key);
+ ok = false;
+ }
+ }
else if (1 ==
sscanf (tok,
- "Q-%[^:]:%s",
+ "Q-%[^:]:%[^\n]",
key,
value))
{
@@ -305,6 +782,33 @@ check_headers (struct MHD_Request *MHD_RESTRICT request,
ok = false;
}
}
+ else if (1 ==
+ sscanf (tok,
+ "Q-:%[^\n]",
+ value))
+ {
+ struct MHD_StringNullable have;
+
+ if (! MHD_request_get_value (request,
+ MHD_VK_URI_QUERY_PARAM,
+ "",
+ &have))
+ {
+ fprintf (stderr,
+ "Expected URI query parameter without key missing\n");
+ ok = false;
+ }
+ else if ( (NULL == have.cstr) ||
+ (0 != strcmp (have.cstr,
+ value)) )
+ {
+ fprintf (stderr,
+ "Wrong URI query parameter value `%s' under missing key, expected `%s'\n",
+ have.cstr,
+ value);
+ ok = false;
+ }
+ }
else
{
fprintf (stderr,
@@ -484,7 +988,7 @@ run_tests (void)
if (0 != run_test ())
{
fprintf (stderr,
- "Test %s failed\n",
+ "Test `%s' failed\n",
current->name);
return 1;
}