chore: add CMake test infrastructure and placeholder unit test files for future coverage

This commit is contained in:
2025-11-28 05:41:42 +00:00
parent 4afdcf567b
commit 53a6179ede
38 changed files with 5192 additions and 21 deletions
+201
View File
@@ -0,0 +1,201 @@
// retoor <retoor@molodetz.nl>
#include "fixtures.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <time.h>
int fixture_create_temp_dir(char *path, size_t size) {
snprintf(path, size, "/tmp/nwedav_test_%d_%ld", getpid(), (long)time(NULL));
return mkdir(path, 0755);
}
static int remove_directory_recursive(const char *path) {
DIR *dir = opendir(path);
if (!dir) return -1;
struct dirent *entry;
char full_path[PATH_MAX];
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
struct stat st;
if (stat(full_path, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
remove_directory_recursive(full_path);
} else {
unlink(full_path);
}
}
}
closedir(dir);
return rmdir(path);
}
int fixture_remove_temp_dir(const char *path) {
return remove_directory_recursive(path);
}
int fixture_create_file(const char *path, const char *content, size_t len) {
FILE *f = fopen(path, "wb");
if (!f) return -1;
if (content && len > 0) {
fwrite(content, 1, len, f);
}
fclose(f);
return 0;
}
int fixture_file_exists(const char *path) {
struct stat st;
return stat(path, &st) == 0;
}
int fixture_read_file(const char *path, char *buf, size_t size) {
FILE *f = fopen(path, "rb");
if (!f) return -1;
size_t n = fread(buf, 1, size - 1, f);
buf[n] = '\0';
fclose(f);
return (int)n;
}
test_fixture_t *fixture_create(void) {
test_fixture_t *fixture = calloc(1, sizeof(test_fixture_t));
if (!fixture) return NULL;
if (fixture_create_temp_dir(fixture->temp_dir, sizeof(fixture->temp_dir)) != 0) {
free(fixture);
return NULL;
}
snprintf(fixture->db_path, sizeof(fixture->db_path), "%s/test.db", fixture->temp_dir);
fixture->user_mgr = user_manager_create(fixture->db_path);
if (!fixture->user_mgr) {
fixture_remove_temp_dir(fixture->temp_dir);
free(fixture);
return NULL;
}
char locks_path[PATH_MAX];
snprintf(locks_path, sizeof(locks_path), "%s/locks.db", fixture->temp_dir);
fixture->locks = lock_manager_create(locks_path);
char props_path[PATH_MAX];
snprintf(props_path, sizeof(props_path), "%s/props.db", fixture->temp_dir);
fixture->props = property_store_create(props_path);
return fixture;
}
void fixture_destroy(test_fixture_t *fixture) {
if (!fixture) return;
if (fixture->pathmapping) {
pathmapping_destroy(fixture->pathmapping);
}
if (fixture->locks) {
lock_manager_destroy(fixture->locks);
}
if (fixture->properties) {
property_store_destroy(fixture->properties);
}
if (fixture->props) {
property_store_destroy(fixture->props);
}
if (fixture->storage) {
storage_destroy(fixture->storage);
}
if (fixture->user_mgr) {
user_manager_destroy(fixture->user_mgr);
}
if (fixture->temp_dir[0]) {
fixture_remove_temp_dir(fixture->temp_dir);
}
free(fixture);
}
test_fixture_t *fixture_create_with_user(const char *username, const char *password) {
test_fixture_t *fixture = fixture_create();
if (!fixture) return NULL;
if (user_manager_add(fixture->user_mgr, username, password,
"test@example.com", 10 * 1024 * 1024) != NWEDAV_OK) {
fixture_destroy(fixture);
return NULL;
}
return fixture;
}
test_fixture_t *fixture_create_with_storage(void) {
test_fixture_t *fixture = fixture_create();
if (!fixture) return NULL;
char storage_path[PATH_MAX];
snprintf(storage_path, sizeof(storage_path), "%s/storage", fixture->temp_dir);
mkdir(storage_path, 0755);
fixture->storage = storage_create(storage_path);
if (!fixture->storage) {
fixture_destroy(fixture);
return NULL;
}
char props_path[PATH_MAX];
snprintf(props_path, sizeof(props_path), "%s/props.db", fixture->temp_dir);
fixture->properties = property_store_create(props_path);
char locks_path[PATH_MAX];
snprintf(locks_path, sizeof(locks_path), "%s/locks.db", fixture->temp_dir);
fixture->locks = lock_manager_create(locks_path);
sqlite3 *db = user_manager_get_db(fixture->user_mgr);
if (db) {
fixture->pathmapping = pathmapping_create(db);
}
return fixture;
}
webdav_context_t fixture_create_context(test_fixture_t *fixture, uint32_t user_id) {
webdav_context_t ctx = {0};
ctx.storage = fixture->storage;
ctx.properties = fixture->properties;
ctx.locks = fixture->locks;
ctx.user_id = user_id;
ctx.quota_bytes = 10 * 1024 * 1024;
ctx.used_bytes = 0;
ctx.perm_read = 1;
ctx.perm_write = 1;
ctx.perm_execute = 0;
user_t user;
if (user_manager_get_by_id(fixture->user_mgr, user_id, &user) == NWEDAV_OK) {
strncpy(ctx.username, user.username, sizeof(ctx.username) - 1);
ctx.quota_bytes = user.quota_bytes;
ctx.used_bytes = user.used_bytes;
ctx.perm_read = user.perm_read;
ctx.perm_write = user.perm_write;
ctx.perm_execute = user.perm_execute;
}
return ctx;
}
+39
View File
@@ -0,0 +1,39 @@
// retoor <retoor@molodetz.nl>
#ifndef TEST_FIXTURES_H
#define TEST_FIXTURES_H
#include "nwedav.h"
#include "../../src/user/usermgr.h"
#include "../../src/storage/backend.h"
#include "../../src/storage/properties.h"
#include "../../src/storage/locks.h"
#include "../../src/storage/pathmapping.h"
#include "../../src/auth/auth.h"
#include "../../src/webdav/methods.h"
typedef struct {
user_manager_t *user_mgr;
storage_backend_t *storage;
property_store_t *properties;
property_store_t *props;
lock_manager_t *locks;
path_mapping_manager_t *pathmapping;
char temp_dir[PATH_MAX];
char db_path[PATH_MAX];
} test_fixture_t;
test_fixture_t *fixture_create(void);
void fixture_destroy(test_fixture_t *fixture);
test_fixture_t *fixture_create_with_user(const char *username, const char *password);
test_fixture_t *fixture_create_with_storage(void);
webdav_context_t fixture_create_context(test_fixture_t *fixture, uint32_t user_id);
int fixture_create_temp_dir(char *path, size_t size);
int fixture_remove_temp_dir(const char *path);
int fixture_create_file(const char *path, const char *content, size_t len);
int fixture_file_exists(const char *path);
int fixture_read_file(const char *path, char *buf, size_t size);
#endif
+197
View File
@@ -0,0 +1,197 @@
// retoor <retoor@molodetz.nl>
#include "http_request_builder.h"
#include "../../src/platform/memory.h"
#include "../../src/auth/auth.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
http_request_t *http_request_new(const char *method, const char *uri) {
http_request_t *req = calloc(1, sizeof(http_request_t));
if (!req) return NULL;
http_request_init(req);
req->method = http_method_from_string(method);
req->version_major = 1;
req->version_minor = 1;
if (uri) {
if (req->uri) free(req->uri);
req->uri = strdup(uri);
}
req->depth = -1;
req->overwrite = 1;
return req;
}
void http_request_set_body(http_request_t *req, const char *body, size_t len) {
if (!req) return;
if (req->body) {
free(req->body);
req->body = NULL;
}
req->body_len = 0;
req->content_length = 0;
if (body && len > 0) {
req->body = malloc(len + 1);
if (req->body) {
memcpy(req->body, body, len);
req->body[len] = '\0';
req->body_len = len;
req->content_length = len;
}
}
}
char *http_build_basic_auth(const char *user, const char *pass) {
if (!user || !pass) return NULL;
size_t cred_len = strlen(user) + 1 + strlen(pass);
char *credentials = malloc(cred_len + 1);
if (!credentials) return NULL;
snprintf(credentials, cred_len + 1, "%s:%s", user, pass);
char *encoded = auth_base64_encode((unsigned char *)credentials, cred_len);
free(credentials);
if (!encoded) return NULL;
size_t auth_len = 6 + strlen(encoded) + 1;
char *auth_header = malloc(auth_len);
if (!auth_header) {
free(encoded);
return NULL;
}
snprintf(auth_header, auth_len, "Basic %s", encoded);
free(encoded);
return auth_header;
}
void http_request_set_auth_basic(http_request_t *req, const char *user, const char *pass) {
if (!req || !user || !pass) return;
char *auth_header = http_build_basic_auth(user, pass);
if (auth_header) {
if (req->authorization) free(req->authorization);
req->authorization = auth_header;
http_add_header(req, "Authorization", auth_header);
}
}
void http_request_set_auth_digest(http_request_t *req, const char *user,
const char *realm, const char *nonce,
const char *uri, const char *response) {
if (!req || !user) return;
char header[1024];
snprintf(header, sizeof(header),
"Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", "
"uri=\"%s\", response=\"%s\", qop=auth, nc=00000001, cnonce=\"abc123\"",
user, realm ? realm : "", nonce ? nonce : "",
uri ? uri : "", response ? response : "");
if (req->authorization) free(req->authorization);
req->authorization = strdup(header);
http_add_header(req, "Authorization", header);
}
void http_request_set_destination(http_request_t *req, const char *dest) {
if (!req) return;
if (req->destination) free(req->destination);
req->destination = dest ? strdup(dest) : NULL;
if (dest) http_add_header(req, "Destination", dest);
}
void http_request_set_depth(http_request_t *req, int depth) {
if (!req) return;
req->depth = depth;
char depth_str[16];
if (depth < 0) {
strcpy(depth_str, "infinity");
} else {
snprintf(depth_str, sizeof(depth_str), "%d", depth);
}
http_add_header(req, "Depth", depth_str);
}
void http_request_set_overwrite(http_request_t *req, int overwrite) {
if (!req) return;
req->overwrite = overwrite;
http_add_header(req, "Overwrite", overwrite ? "T" : "F");
}
void http_request_set_lock_token(http_request_t *req, const char *token) {
if (!req) return;
if (req->lock_token) free(req->lock_token);
req->lock_token = token ? strdup(token) : NULL;
if (token) {
char header[512];
snprintf(header, sizeof(header), "<%s>", token);
http_add_header(req, "Lock-Token", header);
}
}
void http_request_set_if_match(http_request_t *req, const char *etag) {
if (req && etag) {
http_add_header(req, "If-Match", etag);
}
}
void http_request_set_if_none_match(http_request_t *req, const char *etag) {
if (req && etag) {
http_add_header(req, "If-None-Match", etag);
}
}
void http_request_set_range(http_request_t *req, int64_t start, int64_t end) {
if (!req) return;
char range[64];
if (end >= 0) {
snprintf(range, sizeof(range), "bytes=%lld-%lld",
(long long)start, (long long)end);
} else {
snprintf(range, sizeof(range), "bytes=%lld-", (long long)start);
}
http_add_header(req, "Range", range);
}
void http_request_destroy(http_request_t *req) {
if (!req) return;
http_request_free(req);
free(req);
}
http_response_t *http_response_new(void) {
http_response_t *res = calloc(1, sizeof(http_response_t));
if (res) {
http_response_init(res);
}
return res;
}
const char *http_response_get_header_value(http_response_t *res, const char *name) {
if (!res || !name) return NULL;
response_header_t *h = res->headers;
while (h) {
if (strcasecmp(h->name, name) == 0) {
return h->value;
}
h = h->next;
}
return NULL;
}
void http_response_destroy(http_response_t *res) {
if (!res) return;
http_response_free(res);
free(res);
}
+30
View File
@@ -0,0 +1,30 @@
// retoor <retoor@molodetz.nl>
#ifndef HTTP_REQUEST_BUILDER_H
#define HTTP_REQUEST_BUILDER_H
#include "../../src/http/parser.h"
#include "../../src/http/response.h"
#include "../../src/auth/auth.h"
http_request_t *http_request_new(const char *method, const char *uri);
void http_request_set_body(http_request_t *req, const char *body, size_t len);
void http_request_set_auth_basic(http_request_t *req, const char *user, const char *pass);
void http_request_set_auth_digest(http_request_t *req, const char *user,
const char *realm, const char *nonce,
const char *uri, const char *response);
void http_request_set_destination(http_request_t *req, const char *dest);
void http_request_set_depth(http_request_t *req, int depth);
void http_request_set_overwrite(http_request_t *req, int overwrite);
void http_request_set_lock_token(http_request_t *req, const char *token);
void http_request_set_if_match(http_request_t *req, const char *etag);
void http_request_set_if_none_match(http_request_t *req, const char *etag);
void http_request_set_range(http_request_t *req, int64_t start, int64_t end);
void http_request_destroy(http_request_t *req);
http_response_t *http_response_new(void);
const char *http_response_get_header_value(http_response_t *res, const char *name);
void http_response_destroy(http_response_t *res);
char *http_build_basic_auth(const char *user, const char *pass);
#endif