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
+142
View File
@@ -0,0 +1,142 @@
// retoor <retoor@molodetz.nl>
#include "../test_framework.h"
#include "../../src/auth/auth.h"
#include <string.h>
TEST_SUITE(auth_basic)
TEST(base64_encode_simple) {
const char *input = "user:pass";
char *encoded = auth_base64_encode((unsigned char *)input, strlen(input));
ASSERT_NOT_NULL(encoded);
ASSERT_STR_EQ("dXNlcjpwYXNz", encoded);
free(encoded);
}
TEST(base64_encode_empty) {
char *encoded = auth_base64_encode((unsigned char *)"", 0);
ASSERT_NOT_NULL(encoded);
ASSERT_STR_EQ("", encoded);
free(encoded);
}
TEST(base64_decode_simple) {
const char *encoded = "dXNlcjpwYXNz";
size_t out_len = 0;
unsigned char *decoded = auth_base64_decode(encoded, &out_len);
ASSERT_NOT_NULL(decoded);
ASSERT_EQUAL(9, out_len);
ASSERT_MEM_EQ("user:pass", decoded, out_len);
free(decoded);
}
TEST(base64_decode_invalid) {
size_t out_len = 0;
unsigned char *decoded = auth_base64_decode("not_valid_base64!", &out_len);
ASSERT_NULL(decoded);
}
TEST(parse_basic_auth_valid) {
const char *header = "Basic dXNlcjpwYXNz";
char username[64] = {0};
char password[256] = {0};
int ret = auth_parse_basic(header, username, sizeof(username),
password, sizeof(password));
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("user", username);
ASSERT_STR_EQ("pass", password);
}
TEST(parse_basic_auth_with_leading_spaces) {
const char *header = " Basic dXNlcjpwYXNz";
char username[64] = {0};
char password[256] = {0};
int ret = auth_parse_basic(header, username, sizeof(username),
password, sizeof(password));
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("user", username);
ASSERT_STR_EQ("pass", password);
}
TEST(parse_basic_auth_missing_basic_prefix) {
const char *header = "dXNlcjpwYXNz";
char username[64] = {0};
char password[256] = {0};
int ret = auth_parse_basic(header, username, sizeof(username),
password, sizeof(password));
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
}
TEST(parse_basic_auth_no_colon) {
const char *header = "Basic dXNlcm5vY29sb24=";
char username[64] = {0};
char password[256] = {0};
int ret = auth_parse_basic(header, username, sizeof(username),
password, sizeof(password));
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
}
TEST(parse_basic_auth_complex_password) {
const char *header = "Basic YWRtaW46cCFAc3N3MHJkIyQlXg==";
char username[64] = {0};
char password[256] = {0};
int ret = auth_parse_basic(header, username, sizeof(username),
password, sizeof(password));
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("admin", username);
ASSERT_STR_EQ("p!@ssw0rd#$%^", password);
}
TEST(parse_basic_auth_null_header) {
char username[64] = {0};
char password[256] = {0};
int ret = auth_parse_basic(NULL, username, sizeof(username),
password, sizeof(password));
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
}
TEST(parse_basic_auth_case_insensitive) {
const char *header = "BASIC dXNlcjpwYXNz";
char username[64] = {0};
char password[256] = {0};
int ret = auth_parse_basic(header, username, sizeof(username),
password, sizeof(password));
ASSERT_EQUAL(NWEDAV_OK, ret);
}
TEST(base64_roundtrip) {
const char *original = "Test:Complex!@#Password123";
char *encoded = auth_base64_encode((unsigned char *)original, strlen(original));
ASSERT_NOT_NULL(encoded);
size_t out_len = 0;
unsigned char *decoded = auth_base64_decode(encoded, &out_len);
ASSERT_NOT_NULL(decoded);
ASSERT_EQUAL(strlen(original), out_len);
ASSERT_MEM_EQ(original, decoded, out_len);
free(encoded);
free(decoded);
}
+128
View File
@@ -0,0 +1,128 @@
// retoor <retoor@molodetz.nl>
#include "../test_framework.h"
#include "../../src/auth/auth.h"
#include <string.h>
TEST_SUITE(auth_digest)
TEST(parse_digest_auth_valid) {
const char *header = "Digest username=\"admin\", realm=\"WebDAV\", "
"nonce=\"abc123\", uri=\"/folder\", nc=00000001, "
"cnonce=\"xyz789\", qop=auth, response=\"deadbeef\"";
char username[64] = {0};
char realm[128] = {0};
char nonce[64] = {0};
char uri[256] = {0};
char nc[16] = {0};
char cnonce[64] = {0};
char qop[16] = {0};
char response[64] = {0};
int ret = auth_parse_digest(header, username, realm, nonce, uri,
nc, cnonce, qop, response);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("admin", username);
ASSERT_STR_EQ("WebDAV", realm);
ASSERT_STR_EQ("abc123", nonce);
ASSERT_STR_EQ("/folder", uri);
ASSERT_STR_EQ("00000001", nc);
ASSERT_STR_EQ("xyz789", cnonce);
ASSERT_STR_EQ("auth", qop);
ASSERT_STR_EQ("deadbeef", response);
}
TEST(parse_digest_auth_with_spaces) {
const char *header = " Digest username=\"user\", realm=\"test\"";
char username[64] = {0};
char realm[128] = {0};
char nonce[64] = {0};
char uri[256] = {0};
char nc[16] = {0};
char cnonce[64] = {0};
char qop[16] = {0};
char response[64] = {0};
int ret = auth_parse_digest(header, username, realm, nonce, uri,
nc, cnonce, qop, response);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("user", username);
ASSERT_STR_EQ("test", realm);
}
TEST(parse_digest_auth_missing_prefix) {
const char *header = "username=\"admin\", realm=\"WebDAV\"";
char username[64] = {0};
char realm[128] = {0};
char nonce[64] = {0};
char uri[256] = {0};
char nc[16] = {0};
char cnonce[64] = {0};
char qop[16] = {0};
char response[64] = {0};
int ret = auth_parse_digest(header, username, realm, nonce, uri,
nc, cnonce, qop, response);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
}
TEST(parse_digest_auth_null) {
char username[64] = {0};
char realm[128] = {0};
char nonce[64] = {0};
char uri[256] = {0};
char nc[16] = {0};
char cnonce[64] = {0};
char qop[16] = {0};
char response[64] = {0};
int ret = auth_parse_digest(NULL, username, realm, nonce, uri,
nc, cnonce, qop, response);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
}
TEST(parse_digest_auth_unquoted_values) {
const char *header = "Digest username=admin, realm=test, qop=auth";
char username[64] = {0};
char realm[128] = {0};
char nonce[64] = {0};
char uri[256] = {0};
char nc[16] = {0};
char cnonce[64] = {0};
char qop[16] = {0};
char response[64] = {0};
int ret = auth_parse_digest(header, username, realm, nonce, uri,
nc, cnonce, qop, response);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("admin", username);
ASSERT_STR_EQ("test", realm);
ASSERT_STR_EQ("auth", qop);
}
TEST(parse_digest_auth_special_characters_in_uri) {
const char *header = "Digest username=\"user\", uri=\"/path/to/file%20name.txt?q=1&a=2\"";
char username[64] = {0};
char realm[128] = {0};
char nonce[64] = {0};
char uri[256] = {0};
char nc[16] = {0};
char cnonce[64] = {0};
char qop[16] = {0};
char response[64] = {0};
int ret = auth_parse_digest(header, username, realm, nonce, uri,
nc, cnonce, qop, response);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("/path/to/file%20name.txt?q=1&a=2", uri);
}
+160
View File
@@ -0,0 +1,160 @@
// retoor <retoor@molodetz.nl>
#include "../test_framework.h"
#include "../../src/http/parser.h"
#include <string.h>
TEST_SUITE(http_parser)
TEST(parse_get_request_valid) {
const char *raw = "GET /index.html HTTP/1.1\r\n"
"Host: localhost\r\n"
"User-Agent: TestClient/1.0\r\n"
"\r\n";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_EQUAL(HTTP_METHOD_GET, req.method);
ASSERT_STR_EQ("/index.html", req.uri);
ASSERT_EQUAL(1, req.version_major);
ASSERT_EQUAL(1, req.version_minor);
ASSERT_TRUE(consumed > 0);
}
TEST(parse_put_request_with_body) {
const char *raw = "PUT /file.txt HTTP/1.1\r\n"
"Host: localhost\r\n"
"Content-Length: 13\r\n"
"\r\n"
"Hello, World!";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_EQUAL(HTTP_METHOD_PUT, req.method);
ASSERT_STR_EQ("/file.txt", req.uri);
ASSERT_EQUAL(13, req.content_length);
}
TEST(parse_propfind_request) {
const char *raw = "PROPFIND /folder/ HTTP/1.1\r\n"
"Host: localhost\r\n"
"Depth: 1\r\n"
"\r\n";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_EQUAL(HTTP_METHOD_PROPFIND, req.method);
ASSERT_STR_EQ("/folder/", req.uri);
ASSERT_EQUAL(1, req.depth);
}
TEST(parse_copy_request_with_destination) {
const char *raw = "COPY /source.txt HTTP/1.1\r\n"
"Host: localhost\r\n"
"Destination: http://localhost/dest.txt\r\n"
"Overwrite: T\r\n"
"\r\n";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_EQUAL(HTTP_METHOD_COPY, req.method);
ASSERT_NOT_NULL(req.destination);
ASSERT_EQUAL(1, req.overwrite);
}
TEST(parse_request_with_basic_auth) {
const char *raw = "GET /protected HTTP/1.1\r\n"
"Host: localhost\r\n"
"Authorization: Basic dXNlcjpwYXNz\r\n"
"\r\n";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_NOT_NULL(req.authorization);
ASSERT_TRUE(strstr(req.authorization, "Basic") != NULL);
}
TEST(parse_malformed_request_no_method) {
const char *raw = "/index.html HTTP/1.1\r\n\r\n";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
}
TEST(parse_incomplete_request) {
const char *raw = "GET /index.html HTTP/1.1\r\n"
"Host: local";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
}
TEST(parse_request_with_lock_token) {
const char *raw = "PUT /locked.txt HTTP/1.1\r\n"
"Host: localhost\r\n"
"If: (<opaquelocktoken:abc123>)\r\n"
"\r\n";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_EQUAL(NWEDAV_OK, ret);
}
TEST(parse_options_request) {
const char *raw = "OPTIONS * HTTP/1.1\r\n"
"Host: localhost\r\n"
"\r\n";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_EQUAL(HTTP_METHOD_OPTIONS, req.method);
}
TEST(parse_mkcol_request) {
const char *raw = "MKCOL /newdir/ HTTP/1.1\r\n"
"Host: localhost\r\n"
"\r\n";
http_request_t req = {0};
size_t consumed = 0;
int ret = http_parse_request(raw, strlen(raw), &req, &consumed);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_EQUAL(HTTP_METHOD_MKCOL, req.method);
ASSERT_STR_EQ("/newdir/", req.uri);
}
+177
View File
@@ -0,0 +1,177 @@
// retoor <retoor@molodetz.nl>
#include "../test_framework.h"
#include "../../src/http/response.h"
#include "../../src/platform/memory.h"
#include <string.h>
TEST_SUITE(http_response)
TEST(response_init_defaults) {
http_response_t res;
http_response_init(&res);
ASSERT_EQUAL(HTTP_200_OK, res.status);
ASSERT_EQUAL(1, res.keep_alive);
ASSERT_EQUAL(-1, res.sendfile_fd);
ASSERT_NULL(res.body);
ASSERT_EQUAL(0, res.body_len);
}
TEST(response_set_status) {
http_response_t res;
http_response_init(&res);
http_response_set_status(&res, HTTP_404_NOT_FOUND);
ASSERT_EQUAL(HTTP_404_NOT_FOUND, res.status);
http_response_set_status(&res, HTTP_500_INTERNAL_SERVER_ERROR);
ASSERT_EQUAL(HTTP_500_INTERNAL_SERVER_ERROR, res.status);
http_response_free(&res);
}
TEST(response_add_header) {
http_response_t res;
http_response_init(&res);
int ret = http_response_add_header(&res, "Content-Type", "text/plain");
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_NOT_NULL(res.headers);
http_response_free(&res);
}
TEST(response_add_header_duplicate_replaces) {
http_response_t res;
http_response_init(&res);
http_response_add_header(&res, "X-Custom", "value1");
http_response_add_header(&res, "X-Custom", "value2");
response_header_t *h = res.headers;
int count = 0;
while (h) {
if (strcmp(h->name, "X-Custom") == 0) {
ASSERT_STR_EQ("value2", h->value);
count++;
}
h = h->next;
}
ASSERT_EQUAL(1, count);
http_response_free(&res);
}
TEST(response_set_body) {
http_response_t res;
http_response_init(&res);
const char *body = "Hello, World!";
int ret = http_response_set_body(&res, body, strlen(body));
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_NOT_NULL(res.body);
ASSERT_EQUAL(strlen(body), res.body_len);
ASSERT_STR_EQ(body, res.body);
http_response_free(&res);
}
TEST(response_set_body_str) {
http_response_t res;
http_response_init(&res);
const char *body = "Test body content";
int ret = http_response_set_body_str(&res, body);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ(body, res.body);
http_response_free(&res);
}
TEST(response_build_complete) {
http_response_t res;
http_response_init(&res);
http_response_set_status(&res, HTTP_200_OK);
http_response_add_header(&res, "Content-Type", "text/plain");
http_response_set_body_str(&res, "OK");
buffer_t *buf = buffer_create(1024);
int ret = http_response_build(&res, buf);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_TRUE(buf->size > 0);
ASSERT_TRUE(strstr(buf->data, "HTTP/1.1 200 OK") != NULL);
ASSERT_TRUE(strstr(buf->data, "Content-Type: text/plain") != NULL);
buffer_destroy(buf);
http_response_free(&res);
}
TEST(response_error_creates_html_body) {
http_response_t res;
http_response_init(&res);
int ret = http_response_error(&res, HTTP_404_NOT_FOUND, "File not found");
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_EQUAL(HTTP_404_NOT_FOUND, res.status);
ASSERT_NOT_NULL(res.body);
ASSERT_TRUE(strstr(res.body, "404") != NULL);
ASSERT_TRUE(strstr(res.body, "Not Found") != NULL);
http_response_free(&res);
}
TEST(response_redirect) {
http_response_t res;
http_response_init(&res);
int ret = http_response_redirect(&res, HTTP_301_MOVED_PERMANENTLY, "/new/location");
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_EQUAL(HTTP_301_MOVED_PERMANENTLY, res.status);
response_header_t *h = res.headers;
int found = 0;
while (h) {
if (strcmp(h->name, "Location") == 0) {
ASSERT_STR_EQ("/new/location", h->value);
found = 1;
}
h = h->next;
}
ASSERT_TRUE(found);
http_response_free(&res);
}
TEST(status_text_lookup) {
ASSERT_STR_EQ("OK", http_status_text(HTTP_200_OK));
ASSERT_STR_EQ("Created", http_status_text(HTTP_201_CREATED));
ASSERT_STR_EQ("Not Found", http_status_text(HTTP_404_NOT_FOUND));
ASSERT_STR_EQ("Internal Server Error", http_status_text(HTTP_500_INTERNAL_SERVER_ERROR));
ASSERT_STR_EQ("Multi-Status", http_status_text(HTTP_207_MULTI_STATUS));
ASSERT_STR_EQ("Locked", http_status_text(HTTP_423_LOCKED));
ASSERT_STR_EQ("Unknown", http_status_text(999));
}
TEST(response_build_headers_only) {
http_response_t res;
http_response_init(&res);
http_response_set_status(&res, HTTP_200_OK);
http_response_add_header(&res, "Content-Length", "1000");
buffer_t *buf = buffer_create(1024);
int ret = http_response_build_headers_only(&res, buf);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_TRUE(strstr(buf->data, "HTTP/1.1 200 OK") != NULL);
ASSERT_TRUE(strstr(buf->data, "\r\n\r\n") != NULL);
buffer_destroy(buf);
http_response_free(&res);
}
+216
View File
@@ -0,0 +1,216 @@
// retoor <retoor@molodetz.nl>
#include "../test_framework.h"
#include "../fixtures/fixtures.h"
#include "../../src/storage/locks.h"
#include <string.h>
TEST_SUITE(lock_manager)
TEST(create_lock_manager) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
ASSERT_NOT_NULL(fixture->locks);
fixture_destroy(fixture);
}
TEST(create_exclusive_lock) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
lock_entry_t lock;
memset(&lock, 0, sizeof(lock));
strncpy(lock.resource_path, "/testfile.txt", sizeof(lock.resource_path) - 1);
strncpy(lock.owner, "user1", sizeof(lock.owner) - 1);
lock.scope = LOCK_SCOPE_EXCLUSIVE;
lock.type = LOCK_TYPE_WRITE;
lock.depth = LOCK_DEPTH_0;
lock.timeout = 3600;
int ret = lock_manager_create_lock(fixture->locks, &lock);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_TRUE(strlen(lock.token) > 0);
fixture_destroy(fixture);
}
TEST(create_shared_lock) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
lock_entry_t lock;
memset(&lock, 0, sizeof(lock));
strncpy(lock.resource_path, "/shared.txt", sizeof(lock.resource_path) - 1);
strncpy(lock.owner, "user1", sizeof(lock.owner) - 1);
lock.scope = LOCK_SCOPE_SHARED;
lock.type = LOCK_TYPE_WRITE;
lock.depth = LOCK_DEPTH_0;
lock.timeout = 3600;
int ret = lock_manager_create_lock(fixture->locks, &lock);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_TRUE(strlen(lock.token) > 0);
fixture_destroy(fixture);
}
TEST(remove_lock) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
lock_entry_t lock;
memset(&lock, 0, sizeof(lock));
strncpy(lock.resource_path, "/locked.txt", sizeof(lock.resource_path) - 1);
strncpy(lock.owner, "user1", sizeof(lock.owner) - 1);
lock.scope = LOCK_SCOPE_EXCLUSIVE;
lock.type = LOCK_TYPE_WRITE;
lock.timeout = 3600;
lock_manager_create_lock(fixture->locks, &lock);
int ret = lock_manager_remove_lock(fixture->locks, lock.token);
ASSERT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(check_lock_exists) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
int is_locked = lock_manager_is_locked(fixture->locks, "/unlocked.txt");
ASSERT_FALSE(is_locked);
lock_entry_t lock;
memset(&lock, 0, sizeof(lock));
strncpy(lock.resource_path, "/nowlocked.txt", sizeof(lock.resource_path) - 1);
strncpy(lock.owner, "user1", sizeof(lock.owner) - 1);
lock.scope = LOCK_SCOPE_EXCLUSIVE;
lock.type = LOCK_TYPE_WRITE;
lock.timeout = 3600;
lock_manager_create_lock(fixture->locks, &lock);
is_locked = lock_manager_is_locked(fixture->locks, "/nowlocked.txt");
ASSERT_TRUE(is_locked);
fixture_destroy(fixture);
}
TEST(get_lock_by_token) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
lock_entry_t lock;
memset(&lock, 0, sizeof(lock));
strncpy(lock.resource_path, "/info.txt", sizeof(lock.resource_path) - 1);
strncpy(lock.owner, "testowner", sizeof(lock.owner) - 1);
lock.scope = LOCK_SCOPE_EXCLUSIVE;
lock.type = LOCK_TYPE_WRITE;
lock.depth = LOCK_DEPTH_0;
lock.timeout = 7200;
lock_manager_create_lock(fixture->locks, &lock);
lock_entry_t retrieved;
int ret = lock_manager_get_lock(fixture->locks, lock.token, &retrieved);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("testowner", retrieved.owner);
ASSERT_EQUAL(LOCK_SCOPE_EXCLUSIVE, retrieved.scope);
ASSERT_EQUAL(LOCK_TYPE_WRITE, retrieved.type);
fixture_destroy(fixture);
}
TEST(refresh_lock) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
lock_entry_t lock;
memset(&lock, 0, sizeof(lock));
strncpy(lock.resource_path, "/refresh.txt", sizeof(lock.resource_path) - 1);
strncpy(lock.owner, "user1", sizeof(lock.owner) - 1);
lock.scope = LOCK_SCOPE_EXCLUSIVE;
lock.type = LOCK_TYPE_WRITE;
lock.timeout = 100;
lock_manager_create_lock(fixture->locks, &lock);
int ret = lock_manager_refresh_lock(fixture->locks, lock.token, 7200);
ASSERT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(get_locks_for_path) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
lock_entry_t lock;
memset(&lock, 0, sizeof(lock));
strncpy(lock.resource_path, "/pathlocks.txt", sizeof(lock.resource_path) - 1);
strncpy(lock.owner, "user1", sizeof(lock.owner) - 1);
lock.scope = LOCK_SCOPE_EXCLUSIVE;
lock.type = LOCK_TYPE_WRITE;
lock.timeout = 3600;
lock_manager_create_lock(fixture->locks, &lock);
lock_entry_t *locks = NULL;
int count = 0;
int ret = lock_manager_get_locks_for_path(fixture->locks, "/pathlocks.txt", &locks, &count);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_TRUE(count >= 1);
if (locks) free(locks);
fixture_destroy(fixture);
}
TEST(check_lock_with_token) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
lock_entry_t lock;
memset(&lock, 0, sizeof(lock));
strncpy(lock.resource_path, "/check.txt", sizeof(lock.resource_path) - 1);
strncpy(lock.owner, "user1", sizeof(lock.owner) - 1);
lock.scope = LOCK_SCOPE_EXCLUSIVE;
lock.type = LOCK_TYPE_WRITE;
lock.timeout = 3600;
lock.user_id = 1;
lock_manager_create_lock(fixture->locks, &lock);
int ret = lock_manager_check_lock(fixture->locks, "/check.txt", lock.token, 1);
ASSERT_EQUAL(NWEDAV_OK, ret);
ret = lock_manager_check_lock(fixture->locks, "/check.txt", "wrong-token", 2);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(cleanup_expired_locks) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
int ret = lock_manager_cleanup_expired(fixture->locks);
ASSERT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(generate_unique_tokens) {
char *token1 = lock_generate_token();
char *token2 = lock_generate_token();
ASSERT_NOT_NULL(token1);
ASSERT_NOT_NULL(token2);
ASSERT_TRUE(strcmp(token1, token2) != 0);
free(token1);
free(token2);
}
+142
View File
@@ -0,0 +1,142 @@
// retoor <retoor@molodetz.nl>
#include "../test_framework.h"
#include "../fixtures/fixtures.h"
#include "../../src/storage/backend.h"
#include <string.h>
TEST_SUITE(storage_path)
TEST(path_traversal_blocked_dotdot) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
int exists = storage_exists(fixture->storage, "/../etc/passwd");
ASSERT_FALSE(exists);
exists = storage_exists(fixture->storage, "/folder/../../etc/passwd");
ASSERT_FALSE(exists);
fixture_destroy(fixture);
}
TEST(path_traversal_blocked_encoded) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
int exists = storage_exists(fixture->storage, "/%2e%2e/etc/passwd");
ASSERT_FALSE(exists);
fixture_destroy(fixture);
}
TEST(valid_path_normalized) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
int ret = storage_create_collection(fixture->storage, "/testdir");
ASSERT_EQUAL(NWEDAV_OK, ret);
int exists = storage_exists(fixture->storage, "/testdir");
ASSERT_TRUE(exists);
exists = storage_exists(fixture->storage, "/testdir/");
ASSERT_TRUE(exists);
fixture_destroy(fixture);
}
TEST(create_nested_path) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
int ret = storage_create_collection(fixture->storage, "/parent");
ASSERT_EQUAL(NWEDAV_OK, ret);
ret = storage_create_collection(fixture->storage, "/parent/child");
ASSERT_EQUAL(NWEDAV_OK, ret);
int exists = storage_exists(fixture->storage, "/parent/child");
ASSERT_TRUE(exists);
fixture_destroy(fixture);
}
TEST(create_collection_parent_missing) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
int ret = storage_create_collection(fixture->storage, "/missing/child");
ASSERT_EQUAL(NWEDAV_ERROR_CONFLICT, ret);
fixture_destroy(fixture);
}
TEST(write_file_creates_in_collection) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
int ret = storage_create_collection(fixture->storage, "/folder");
ASSERT_EQUAL(NWEDAV_OK, ret);
const char *content = "test content";
ret = storage_write_file(fixture->storage, "/folder/test.txt",
content, strlen(content));
ASSERT_EQUAL(NWEDAV_OK, ret);
int exists = storage_exists(fixture->storage, "/folder/test.txt");
ASSERT_TRUE(exists);
fixture_destroy(fixture);
}
TEST(write_file_parent_missing) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
const char *content = "test";
int ret = storage_write_file(fixture->storage, "/missing/file.txt",
content, strlen(content));
ASSERT_EQUAL(NWEDAV_ERROR_CONFLICT, ret);
fixture_destroy(fixture);
}
TEST(delete_empty_collection) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
storage_create_collection(fixture->storage, "/todelete");
int ret = storage_delete(fixture->storage, "/todelete");
ASSERT_EQUAL(NWEDAV_OK, ret);
int exists = storage_exists(fixture->storage, "/todelete");
ASSERT_FALSE(exists);
fixture_destroy(fixture);
}
TEST(delete_file) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
storage_write_file(fixture->storage, "/file.txt", "data", 4);
int ret = storage_delete(fixture->storage, "/file.txt");
ASSERT_EQUAL(NWEDAV_OK, ret);
int exists = storage_exists(fixture->storage, "/file.txt");
ASSERT_FALSE(exists);
fixture_destroy(fixture);
}
TEST(root_path_always_exists) {
test_fixture_t *fixture = fixture_create_with_storage();
ASSERT_NOT_NULL(fixture);
int exists = storage_exists(fixture->storage, "/");
ASSERT_TRUE(exists);
fixture_destroy(fixture);
}
+184
View File
@@ -0,0 +1,184 @@
// retoor <retoor@molodetz.nl>
#include "../test_framework.h"
#include "../fixtures/fixtures.h"
#include "../../src/user/usermgr.h"
#include <string.h>
TEST_SUITE(user_database)
TEST(create_user_manager) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
ASSERT_NOT_NULL(fixture->user_mgr);
fixture_destroy(fixture);
}
TEST(add_user_success) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
int ret = user_manager_add(fixture->user_mgr, "testuser", "password123",
"test@example.com", 10 * 1024 * 1024);
ASSERT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(add_user_duplicate_fails) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_manager_add(fixture->user_mgr, "alice", "pass1", "alice@test.com", 0);
int ret = user_manager_add(fixture->user_mgr, "alice", "pass2", "alice2@test.com", 0);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(get_user_by_username) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_manager_add(fixture->user_mgr, "bob", "secret", "bob@test.com", 5000000);
user_t user;
int ret = user_manager_get_by_username(fixture->user_mgr, "bob", &user);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("bob", user.username);
ASSERT_STR_EQ("bob@test.com", user.email);
ASSERT_EQUAL(5000000, user.quota_bytes);
ASSERT_EQUAL(1, user.enabled);
fixture_destroy(fixture);
}
TEST(get_user_not_found) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_t user;
int ret = user_manager_get_by_username(fixture->user_mgr, "nonexistent", &user);
ASSERT_EQUAL(NWEDAV_ERROR_NOT_FOUND, ret);
fixture_destroy(fixture);
}
TEST(authenticate_valid) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_manager_add(fixture->user_mgr, "charlie", "mypassword", "charlie@test.com", 0);
user_t user;
int ret = user_manager_authenticate(fixture->user_mgr, "charlie", "mypassword", &user);
ASSERT_EQUAL(NWEDAV_OK, ret);
ASSERT_STR_EQ("charlie", user.username);
fixture_destroy(fixture);
}
TEST(authenticate_wrong_password) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_manager_add(fixture->user_mgr, "dave", "correct", "dave@test.com", 0);
user_t user;
int ret = user_manager_authenticate(fixture->user_mgr, "dave", "wrong", &user);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(authenticate_disabled_user) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_manager_add(fixture->user_mgr, "eve", "pass", "eve@test.com", 0);
user_manager_enable(fixture->user_mgr, "eve", 0);
user_t user;
int ret = user_manager_authenticate(fixture->user_mgr, "eve", "pass", &user);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(delete_user) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_manager_add(fixture->user_mgr, "frank", "pass", "frank@test.com", 0);
int ret = user_manager_delete(fixture->user_mgr, "frank");
ASSERT_EQUAL(NWEDAV_OK, ret);
user_t user;
ret = user_manager_get_by_username(fixture->user_mgr, "frank", &user);
ASSERT_EQUAL(NWEDAV_ERROR_NOT_FOUND, ret);
fixture_destroy(fixture);
}
TEST(set_password) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_manager_add(fixture->user_mgr, "grace", "oldpass", "grace@test.com", 0);
user_manager_set_password(fixture->user_mgr, "grace", "newpass");
user_t user;
int ret = user_manager_authenticate(fixture->user_mgr, "grace", "newpass", &user);
ASSERT_EQUAL(NWEDAV_OK, ret);
ret = user_manager_authenticate(fixture->user_mgr, "grace", "oldpass", &user);
ASSERT_NOT_EQUAL(NWEDAV_OK, ret);
fixture_destroy(fixture);
}
TEST(user_count) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
ASSERT_EQUAL(0, user_manager_count(fixture->user_mgr));
user_manager_add(fixture->user_mgr, "user1", "p", "u1@test.com", 0);
ASSERT_EQUAL(1, user_manager_count(fixture->user_mgr));
user_manager_add(fixture->user_mgr, "user2", "p", "u2@test.com", 0);
ASSERT_EQUAL(2, user_manager_count(fixture->user_mgr));
user_manager_delete(fixture->user_mgr, "user1");
ASSERT_EQUAL(1, user_manager_count(fixture->user_mgr));
fixture_destroy(fixture);
}
TEST(enable_disable_user) {
test_fixture_t *fixture = fixture_create();
ASSERT_NOT_NULL(fixture);
user_manager_add(fixture->user_mgr, "henry", "pass", "h@test.com", 0);
user_t user;
user_manager_get_by_username(fixture->user_mgr, "henry", &user);
ASSERT_EQUAL(1, user.enabled);
user_manager_enable(fixture->user_mgr, "henry", 0);
user_manager_get_by_username(fixture->user_mgr, "henry", &user);
ASSERT_EQUAL(0, user.enabled);
user_manager_enable(fixture->user_mgr, "henry", 1);
user_manager_get_by_username(fixture->user_mgr, "henry", &user);
ASSERT_EQUAL(1, user.enabled);
fixture_destroy(fixture);
}