chore: add CMake test infrastructure and placeholder unit test files for future coverage
This commit is contained in:
Vendored
+201
@@ -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;
|
||||
}
|
||||
Vendored
+39
@@ -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
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user