From bf19b9938508f70011395f4dc283ca758ec6a8d3 Mon Sep 17 00:00:00 2001 From: Ethan Werner Date: Sat, 19 Sep 2026 06:09:54 +0000 Subject: llm tooling --- tests/test_uri.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 tests/test_uri.c (limited to 'tests/test_uri.c') 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 +#include +#include + +#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; +} -- cgit v1.3.1