summaryrefslogtreecommitdiffstats
path: root/tests/test_uri.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_uri.c')
-rw-r--r--tests/test_uri.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/tests/test_uri.c b/tests/test_uri.c
new file mode 100644
index 0000000..a768c8c
--- /dev/null
+++ b/tests/test_uri.c
@@ -0,0 +1,300 @@
+// Tests for uri.h - URI parsing and serialization
+#define URI_IMPLEMENTATION
+#include "../include/uri.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ASSERT(cond, msg) \
+ do { \
+ if (!(cond)) { \
+ fprintf(stderr, "FAIL: %s (test_uri.c:%d)\n", msg, __LINE__); \
+ failures++; \
+ } \
+ } while (0)
+
+#define ASSERT_STR_EQ(a, b, msg) \
+ do { \
+ if ((a) == NULL || (b) == NULL || strcmp((a), (b)) != 0) { \
+ fprintf(stderr, "FAIL: %s (got '%s', expected '%s') (test_uri.c:%d)\n", \
+ msg, (a) ? (a) : "NULL", (b) ? (b) : "NULL", __LINE__); \
+ failures++; \
+ } \
+ } while (0)
+
+static int failures = 0;
+
+void test_init() {
+ uri_t *u = uri_init();
+ ASSERT(u != NULL, "init returns non-NULL");
+ for (int i = 0; i < URI_END; i++) {
+ ASSERT(u->data[i] == NULL, "all fields NULL");
+ }
+ uri_free(u);
+}
+
+void test_set_and_get() {
+ uri_t *u = uri_init();
+
+ uri_set(u, SCHEME, "https");
+ uri_set(u, HOST, "example.com");
+ uri_set(u, PATH, "/api/v1");
+
+ char *uri = uri_get(u);
+ ASSERT(uri != NULL, "get returns non-NULL");
+ ASSERT_STR_EQ(uri, "https://example.com/api/v1", "constructed URI");
+ free(uri);
+
+ uri_free(u);
+}
+
+void test_set_with_port() {
+ uri_t *u = uri_init();
+
+ uri_set(u, SCHEME, "http");
+ uri_set(u, HOST, "localhost");
+ uri_set(u, PORT, "8080");
+
+ char *uri = uri_get(u);
+ ASSERT_STR_EQ(uri, "http://localhost:8080", "URI with port");
+ free(uri);
+
+ uri_free(u);
+}
+
+void test_set_with_query() {
+ uri_t *u = uri_init();
+
+ uri_set(u, SCHEME, "https");
+ uri_set(u, HOST, "example.com");
+ uri_set(u, PATH, "/search");
+ uri_set(u, QUERY, "q=test");
+
+ char *uri = uri_get(u);
+ ASSERT_STR_EQ(uri, "https://example.com/search?q=test", "URI with query");
+ free(uri);
+
+ uri_free(u);
+}
+
+void test_set_with_fragment() {
+ uri_t *u = uri_init();
+
+ uri_set(u, SCHEME, "https");
+ uri_set(u, HOST, "example.com");
+ uri_set(u, PATH, "/page");
+ uri_set(u, FRAGMENT, "section");
+
+ char *uri = uri_get(u);
+ ASSERT_STR_EQ(uri, "https://example.com/page#section", "URI with fragment");
+ free(uri);
+
+ uri_free(u);
+}
+
+void test_full_uri() {
+ uri_t *u = uri_init();
+
+ uri_set(u, SCHEME, "https");
+ uri_set(u, USERINFO, "user:pass");
+ uri_set(u, HOST, "example.com");
+ uri_set(u, PORT, "443");
+ uri_set(u, PATH, "/path/to/resource");
+ uri_set(u, QUERY, "key=value");
+ uri_set(u, FRAGMENT, "anchor");
+
+ char *uri = uri_get(u);
+ ASSERT(uri != NULL, "full URI constructed");
+
+ uri_free(u);
+ free(uri);
+}
+
+void test_parse_basic() {
+ uri_t *u = uri_parse("https://example.com/path");
+ ASSERT(u != NULL, "parse returns non-NULL");
+
+ ASSERT_STR_EQ(u->data[SCHEME], "https", "parsed scheme");
+ ASSERT_STR_EQ(u->data[HOST], "example.com", "parsed host");
+ ASSERT_STR_EQ(u->data[PATH], "/path", "parsed path");
+
+ uri_free(u);
+}
+
+void test_parse_with_port() {
+ uri_t *u = uri_parse("http://localhost:8080/api");
+ ASSERT(u != NULL, "parse with port");
+
+ ASSERT_STR_EQ(u->data[SCHEME], "http", "scheme");
+ ASSERT_STR_EQ(u->data[HOST], "localhost", "host");
+ ASSERT_STR_EQ(u->data[PORT], "8080", "port");
+ ASSERT_STR_EQ(u->data[PATH], "/api", "path");
+
+ uri_free(u);
+}
+
+void test_parse_with_query() {
+ uri_t *u = uri_parse("https://example.com/search?q=hello");
+ ASSERT(u != NULL, "parse with query");
+
+ ASSERT_STR_EQ(u->data[QUERY], "q=hello", "query parsed");
+
+ uri_free(u);
+}
+
+void test_parse_with_fragment() {
+ uri_t *u = uri_parse("https://example.com/page#top");
+ ASSERT(u != NULL, "parse with fragment");
+
+ ASSERT_STR_EQ(u->data[FRAGMENT], "top", "fragment parsed");
+
+ uri_free(u);
+}
+
+void test_parse_full() {
+ uri_t *u = uri_parse("https://user:pass@example.com:443/path?q=1#frag");
+ ASSERT(u != NULL, "parse full URI");
+
+ ASSERT_STR_EQ(u->data[SCHEME], "https", "scheme");
+ ASSERT_STR_EQ(u->data[USERINFO], "user:pass", "userinfo parsed");
+ ASSERT_STR_EQ(u->data[HOST], "example.com", "host parsed");
+ ASSERT_STR_EQ(u->data[PORT], "443", "port parsed");
+ ASSERT_STR_EQ(u->data[PATH], "/path", "path");
+ ASSERT_STR_EQ(u->data[QUERY], "q=1", "query");
+ ASSERT_STR_EQ(u->data[FRAGMENT], "frag", "fragment");
+
+ uri_free(u);
+}
+
+void test_parse_invalid() {
+ uri_t *u = uri_parse("not-a-uri");
+ ASSERT(u == NULL, "invalid URI returns NULL");
+}
+
+void test_set_override() {
+ uri_t *u = uri_init();
+
+ uri_set(u, SCHEME, "http");
+ uri_set(u, HOST, "old.com");
+
+ uri_set(u, SCHEME, "https");
+ uri_set(u, HOST, "new.com");
+
+ char *uri = uri_get(u);
+ ASSERT_STR_EQ(uri, "https://new.com", "override works");
+ free(uri);
+
+ uri_free(u);
+}
+
+void test_roundtrip() {
+ char const *original = "https://example.com:8080/path?q=test#anchor";
+ uri_t *u = uri_parse(original);
+ ASSERT(u != NULL, "parse for roundtrip");
+ if (!u)
+ return;
+
+ char *rebuilt = uri_get(u);
+ ASSERT(rebuilt != NULL, "rebuilt URI");
+ if (!rebuilt) {
+ uri_free(u);
+ return;
+ }
+
+ ASSERT(strcmp(rebuilt, original) == 0, "roundtrip matches original");
+
+ uri_free(u);
+ free(rebuilt);
+}
+
+void test_minimal_uri() {
+ uri_t *u = uri_init();
+ uri_set(u, SCHEME, "file");
+ uri_set(u, HOST, "/tmp/file.txt");
+
+ char *uri = uri_get(u);
+ ASSERT(uri != NULL, "minimal URI");
+ free(uri);
+
+ uri_free(u);
+}
+
+void test_set_null() {
+ uri_t *u = uri_init();
+ uri_set(u, SCHEME, "http");
+ uri_set(u, HOST, "example.com");
+ uri_set(u, HOST, NULL);
+
+ char *uri = uri_get(u);
+ ASSERT(uri != NULL, "uri with NULL host");
+ ASSERT(strcmp(uri, "http:") == 0, "uri is just scheme");
+ free(uri);
+
+ uri_free(u);
+}
+
+void test_remove_element() {
+ uri_t *u = uri_init();
+ uri_set(u, SCHEME, "https");
+ uri_set(u, HOST, "example.com");
+ uri_set(u, PATH, "/path");
+
+ char *removed = uri_remove(u, SCHEME);
+ ASSERT(removed != NULL, "remove returns old value");
+ ASSERT(strcmp(removed, "https") == 0, "removed value matches");
+ free(removed);
+
+ char *uri = uri_get(u);
+ ASSERT(uri != NULL, "uri after remove");
+ ASSERT(strcmp(uri, "//example.com/path") == 0, "uri without scheme");
+ free(uri);
+
+ uri_free(u);
+}
+
+void test_null_guards() {
+ uri_set(NULL, SCHEME, "http");
+ uri_print(NULL);
+ uri_print_elements(NULL);
+ ASSERT(uri_get(NULL) == NULL, "uri_get(NULL) returns NULL");
+ ASSERT(uri_remove(NULL, HOST) == NULL, "uri_remove(NULL) returns NULL");
+ ASSERT(uri_parse(NULL) == NULL, "uri_parse(NULL) returns NULL");
+}
+
+void test_bounds_guards() {
+ uri_t *u = uri_init();
+
+ uri_set(u, (uri_element_t)999, "http");
+ ASSERT(u->data[SCHEME] == NULL, "out-of-bounds set is no-op");
+
+ char *r = uri_remove(u, (uri_element_t)-1);
+ ASSERT(r == NULL, "negative index remove returns NULL");
+
+ uri_free(u);
+}
+
+int main() {
+ test_init();
+ test_set_and_get();
+ test_set_with_port();
+ test_set_with_query();
+ test_set_with_fragment();
+ test_full_uri();
+ test_parse_basic();
+ test_parse_with_port();
+ test_parse_with_query();
+ test_parse_with_fragment();
+ test_parse_full();
+ test_parse_invalid();
+ test_set_override();
+ test_roundtrip();
+ test_minimal_uri();
+ test_set_null();
+ test_remove_element();
+ test_null_guards();
+ test_bounds_guards();
+
+ printf("test_uri: %d failures\n", failures);
+ return failures;
+}