src/server/test/httpparser.c

changeset 662
70fdf948b642
child 663
bd116bd44926
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/test/httpparser.c	Fri Feb 06 14:06:04 2026 +0100
@@ -0,0 +1,136 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "httpparser.h"
+
+#include "../daemon/httpparser.h"
+
+CX_TEST(test_parse_request_line) {
+    CX_TEST_DO {
+        HttpParser parser;
+        memset(&parser, 0, sizeof(HttpParser));
+        parser.start_line = cx_mutstr("GET / HTTP/1.1\r\n");
+        
+        int ret1 = parse_request_line(&parser);
+        CX_TEST_ASSERT(!ret1);
+        CX_TEST_ASSERT(!cx_strcmp(parser.method, "GET"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.uri, "/"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.httpv, "HTTP/1.1"));
+        
+        memset(&parser, 0, sizeof(HttpParser));
+        parser.start_line = cx_mutstr("POST /longer/url/test/path/ HTTP/1.0\r\n");
+        int ret2 = parse_request_line(&parser);
+        CX_TEST_ASSERT(!ret2);
+        CX_TEST_ASSERT(!cx_strcmp(parser.method, "POST"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.uri, "/longer/url/test/path/"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.httpv, "HTTP/1.0"));
+        
+        memset(&parser, 0, sizeof(HttpParser));
+        parser.start_line = cx_mutstr("G / v\r\n");
+        int ret3 = parse_request_line(&parser);
+        CX_TEST_ASSERT(!ret3);
+        CX_TEST_ASSERT(!cx_strcmp(parser.method, "G"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.uri, "/"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.httpv, "v"));
+        
+        memset(&parser, 0, sizeof(HttpParser));
+        parser.start_line = cx_mutstr("HEAD   /space      HTTP/0.9    \r\n");
+        int ret4 = parse_request_line(&parser);
+        CX_TEST_ASSERT(!ret4);
+        CX_TEST_ASSERT(!cx_strcmp(parser.method, "HEAD"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.uri, "/space"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.httpv, "HTTP/0.9"));
+        
+        // unix-style line break tests
+        memset(&parser, 0, sizeof(HttpParser));
+        parser.start_line = cx_mutstr("PROPFIND /collection/ HTTP/1.1\n");
+        int uret1 = parse_request_line(&parser);
+        CX_TEST_ASSERT(!uret1);
+        CX_TEST_ASSERT(!cx_strcmp(parser.method, "PROPFIND"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.uri, "/collection/"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.httpv, "HTTP/1.1"));
+        
+        // negative tests
+        parser.start_line = cx_mutstr("\r\n");
+        int nret1 = parse_request_line(&parser);
+        CX_TEST_ASSERT(nret1);
+        
+        parser.start_line = cx_mutstr("GET\r\n");
+        int nret2 = parse_request_line(&parser);
+        CX_TEST_ASSERT(nret2);
+        
+        parser.start_line = cx_mutstr("GET /test\r\n");
+        int nret3 = parse_request_line(&parser);
+        CX_TEST_ASSERT(nret3);
+        
+        parser.start_line = cx_mutstr("GET /test   \r\n");
+        int nret4 = parse_request_line(&parser);
+        CX_TEST_ASSERT(nret4);
+        
+        parser.start_line = cx_mutstr("/test HTTP/1.1\r\n");
+        int nret5 = parse_request_line(&parser);
+        CX_TEST_ASSERT(nret5);
+        
+        parser.start_line = cx_mutstr("GET /uri HTTP/1.1 test\r\n");
+        int nret6 = parse_request_line(&parser);
+        CX_TEST_ASSERT(nret6);
+    }
+}
+
+CX_TEST(test_parse_response_line) {
+    CX_TEST_DO {
+        HttpParser parser;
+        memset(&parser, 0, sizeof(HttpParser));
+        parser.start_line = cx_mutstr("HTTP/1.1 200 OK\r\n");
+        parser.type = 1;
+        
+        int ret1 = parse_response_line(&parser);
+        CX_TEST_ASSERT(!ret1);
+        CX_TEST_ASSERT(!cx_strcmp(parser.httpv, "HTTP/1.1"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.msg, "OK"));
+        CX_TEST_ASSERT(parser.status == 200);
+        
+        memset(&parser, 0, sizeof(HttpParser));
+        parser.start_line = cx_mutstr("HTTP/1.0 201 Created\r\n");
+        parser.type = 1;
+        int ret2 = parse_response_line(&parser);
+        CX_TEST_ASSERT(!ret2);
+        CX_TEST_ASSERT(!cx_strcmp(parser.httpv, "HTTP/1.0"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.msg, "Created"));
+        CX_TEST_ASSERT(parser.status == 201);
+        
+        memset(&parser, 0, sizeof(HttpParser));
+        parser.start_line = cx_mutstr("HTTP/0.9    204    No Content\r\n");
+        parser.type = 1;
+        int ret3 = parse_response_line(&parser);
+        CX_TEST_ASSERT(!ret3);
+        CX_TEST_ASSERT(!cx_strcmp(parser.httpv, "HTTP/0.9"));
+        CX_TEST_ASSERT(!cx_strcmp(parser.msg, "No Content"));
+        CX_TEST_ASSERT(parser.status == 204);
+    }
+}

mercurial