pcloudcc-lneely/tests/unit-tests/test_pfstasks_tree.c

290 lines
10 KiB
C

/*
* Test: pfstasks_tree.c — pure tree layer for fstask structs
*
* Builds psync_fstask_folder_t fixtures directly (no DB, no psql) and
* verifies pfs_task_find_mkdir, pfs_task_find_rmdir, pfs_task_find_creat,
* pfs_task_find_unlink, pfs_task_find_mkdir_by_folderid, and
* pfs_task_find_creat_by_fileid.
*/
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include "pfstasks_tree.h"
/* ------------------------------------------------------------------ */
/* Harness */
/* ------------------------------------------------------------------ */
static int passes = 0, failures = 0;
#define PASS(n) do { printf("PASS: %s\n", n); passes++; } while (0)
#define FAIL(n, ...) do { printf("FAIL: %s — ", n); printf(__VA_ARGS__); printf("\n"); failures++; } while (0)
/* ------------------------------------------------------------------ */
/* Node builders (stack / malloc, NOT pmem) */
/* ------------------------------------------------------------------ */
/* Allocate a psync_fstask_mkdir_t with a given name, taskid, folderid */
static psync_fstask_mkdir_t *mk_mkdir(const char *name, uint64_t taskid,
psync_fsfolderid_t folderid) {
size_t len = strlen(name) + 1;
psync_fstask_mkdir_t *n = (psync_fstask_mkdir_t *)
calloc(1, offsetof(psync_fstask_mkdir_t, name) + len);
n->taskid = taskid;
n->folderid = folderid;
memcpy(n->name, name, len);
return n;
}
static psync_fstask_rmdir_t *mk_rmdir(const char *name, uint64_t taskid,
psync_fsfolderid_t folderid) {
size_t len = strlen(name) + 1;
psync_fstask_rmdir_t *n = (psync_fstask_rmdir_t *)
calloc(1, offsetof(psync_fstask_rmdir_t, name) + len);
n->taskid = taskid;
n->folderid = folderid;
memcpy(n->name, name, len);
return n;
}
static psync_fstask_creat_t *mk_creat(const char *name, uint64_t taskid,
psync_fsfileid_t fileid) {
size_t len = strlen(name) + 1;
psync_fstask_creat_t *n = (psync_fstask_creat_t *)
calloc(1, offsetof(psync_fstask_creat_t, name) + len);
n->taskid = taskid;
n->fileid = fileid;
memcpy(n->name, name, len);
return n;
}
static psync_fstask_unlink_t *mk_unlink(const char *name, uint64_t taskid,
psync_fsfileid_t fileid) {
size_t len = strlen(name) + 1;
psync_fstask_unlink_t *n = (psync_fstask_unlink_t *)
calloc(1, offsetof(psync_fstask_unlink_t, name) + len);
n->taskid = taskid;
n->fileid = fileid;
memcpy(n->name, name, len);
return n;
}
/* Build a clean empty folder */
static void folder_init(psync_fstask_folder_t *f, psync_fsfolderid_t folderid) {
memset(f, 0, sizeof(*f));
f->folderid = folderid;
}
/* ------------------------------------------------------------------ */
/* Tests */
/* ------------------------------------------------------------------ */
/* find_mkdir: basic hit and miss */
static void test_find_mkdir_basic(void) {
psync_fstask_folder_t f;
folder_init(&f, 1);
psync_fstask_mkdir_t *a = mk_mkdir("alpha", 10, -10);
psync_fstask_mkdir_t *b = mk_mkdir("beta", 20, -20);
psync_fstask_mkdir_t *c = mk_mkdir("gamma", 30, -30);
pfs_task_insert_into_tree(&f.mkdirs, offsetof(psync_fstask_mkdir_t, name), &a->tree);
pfs_task_insert_into_tree(&f.mkdirs, offsetof(psync_fstask_mkdir_t, name), &b->tree);
pfs_task_insert_into_tree(&f.mkdirs, offsetof(psync_fstask_mkdir_t, name), &c->tree);
psync_fstask_mkdir_t *found = pfs_task_find_mkdir(&f, "beta", 0);
if (!found || found->taskid != 20)
FAIL("find_mkdir basic: hit", "found=%p taskid=%llu",
(void*)found, found ? (unsigned long long)found->taskid : 0);
else
PASS("find_mkdir: finds 'beta' by name");
if (pfs_task_find_mkdir(&f, "delta", 0) != NULL)
FAIL("find_mkdir basic: miss", "found non-NULL for absent key");
else
PASS("find_mkdir: returns NULL for absent name");
free(a); free(b); free(c);
}
/* find_mkdir: taskid discriminator with same-name duplicates */
static void test_find_mkdir_taskid(void) {
psync_fstask_folder_t f;
folder_init(&f, 2);
/* Two mkdirs with same name "foo" but different taskids */
psync_fstask_mkdir_t *x = mk_mkdir("foo", 100, -100);
psync_fstask_mkdir_t *y = mk_mkdir("foo", 200, -200);
pfs_task_insert_into_tree(&f.mkdirs, offsetof(psync_fstask_mkdir_t, name), &x->tree);
pfs_task_insert_into_tree(&f.mkdirs, offsetof(psync_fstask_mkdir_t, name), &y->tree);
psync_fstask_mkdir_t *found100 = pfs_task_find_mkdir(&f, "foo", 100);
psync_fstask_mkdir_t *found200 = pfs_task_find_mkdir(&f, "foo", 200);
if (!found100 || found100->taskid != 100)
FAIL("find_mkdir taskid: find taskid=100", "got %p", (void*)found100);
else
PASS("find_mkdir: taskid discriminator finds correct node (100)");
if (!found200 || found200->taskid != 200)
FAIL("find_mkdir taskid: find taskid=200", "got %p", (void*)found200);
else
PASS("find_mkdir: taskid discriminator finds correct node (200)");
free(x); free(y);
}
/* find_rmdir: basic */
static void test_find_rmdir_basic(void) {
psync_fstask_folder_t f;
folder_init(&f, 3);
psync_fstask_rmdir_t *a = mk_rmdir("dirA", 11, 101);
psync_fstask_rmdir_t *b = mk_rmdir("dirB", 22, 102);
pfs_task_insert_into_tree(&f.rmdirs, offsetof(psync_fstask_rmdir_t, name), &a->tree);
pfs_task_insert_into_tree(&f.rmdirs, offsetof(psync_fstask_rmdir_t, name), &b->tree);
psync_fstask_rmdir_t *r = pfs_task_find_rmdir(&f, "dirA", 0);
if (!r || r->taskid != 11)
FAIL("find_rmdir basic", "taskid=%llu", r ? (unsigned long long)r->taskid : 0);
else
PASS("find_rmdir: finds 'dirA'");
if (pfs_task_find_rmdir(&f, "dirC", 0) != NULL)
FAIL("find_rmdir miss", "non-NULL for absent");
else
PASS("find_rmdir: NULL for absent name");
free(a); free(b);
}
/* find_creat: basic */
static void test_find_creat_basic(void) {
psync_fstask_folder_t f;
folder_init(&f, 4);
psync_fstask_creat_t *a = mk_creat("file.txt", 55, 1001);
psync_fstask_creat_t *b = mk_creat("photo.jpg", 66, 1002);
pfs_task_insert_into_tree(&f.creats, offsetof(psync_fstask_creat_t, name), &a->tree);
pfs_task_insert_into_tree(&f.creats, offsetof(psync_fstask_creat_t, name), &b->tree);
psync_fstask_creat_t *r = pfs_task_find_creat(&f, "photo.jpg", 0);
if (!r || r->fileid != 1002)
FAIL("find_creat basic", "fileid=%lld", r ? (long long)r->fileid : 0);
else
PASS("find_creat: finds 'photo.jpg'");
free(a); free(b);
}
/* find_unlink: basic */
static void test_find_unlink_basic(void) {
psync_fstask_folder_t f;
folder_init(&f, 5);
psync_fstask_unlink_t *a = mk_unlink("old.txt", 77, 2001);
psync_fstask_unlink_t *b = mk_unlink("tmp.log", 88, 2002);
pfs_task_insert_into_tree(&f.unlinks, offsetof(psync_fstask_unlink_t, name), &a->tree);
pfs_task_insert_into_tree(&f.unlinks, offsetof(psync_fstask_unlink_t, name), &b->tree);
psync_fstask_unlink_t *r = pfs_task_find_unlink(&f, "old.txt", 0);
if (!r || r->fileid != 2001)
FAIL("find_unlink basic", "fileid=%lld", r ? (long long)r->fileid : 0);
else
PASS("find_unlink: finds 'old.txt'");
if (pfs_task_find_unlink(&f, "missing.txt", 0) != NULL)
FAIL("find_unlink miss", "non-NULL");
else
PASS("find_unlink: NULL for absent name");
free(a); free(b);
}
/* find_mkdir_by_folderid: walk tree by folderid */
static void test_find_mkdir_by_folderid(void) {
psync_fstask_folder_t f;
folder_init(&f, 6);
psync_fstask_mkdir_t *a = mk_mkdir("one", 1, -101);
psync_fstask_mkdir_t *b = mk_mkdir("two", 2, -202);
psync_fstask_mkdir_t *c = mk_mkdir("three", 3, -303);
pfs_task_insert_into_tree(&f.mkdirs, offsetof(psync_fstask_mkdir_t, name), &a->tree);
pfs_task_insert_into_tree(&f.mkdirs, offsetof(psync_fstask_mkdir_t, name), &b->tree);
pfs_task_insert_into_tree(&f.mkdirs, offsetof(psync_fstask_mkdir_t, name), &c->tree);
psync_fstask_mkdir_t *r = pfs_task_find_mkdir_by_folderid(&f, -202);
if (!r || strcmp(r->name, "two") != 0)
FAIL("find_mkdir_by_folderid", "name=%s", r ? r->name : "(null)");
else
PASS("find_mkdir_by_folderid: finds node with folderid=-202");
if (pfs_task_find_mkdir_by_folderid(&f, -999) != NULL)
FAIL("find_mkdir_by_folderid miss", "non-NULL for absent folderid");
else
PASS("find_mkdir_by_folderid: NULL for absent folderid");
free(a); free(b); free(c);
}
/* find_creat_by_fileid: walk tree by fileid */
static void test_find_creat_by_fileid(void) {
psync_fstask_folder_t f;
folder_init(&f, 7);
psync_fstask_creat_t *a = mk_creat("a.txt", 10, 5001);
psync_fstask_creat_t *b = mk_creat("b.txt", 20, 5002);
psync_fstask_creat_t *c = mk_creat("c.txt", 30, 5003);
pfs_task_insert_into_tree(&f.creats, offsetof(psync_fstask_creat_t, name), &a->tree);
pfs_task_insert_into_tree(&f.creats, offsetof(psync_fstask_creat_t, name), &b->tree);
pfs_task_insert_into_tree(&f.creats, offsetof(psync_fstask_creat_t, name), &c->tree);
psync_fstask_creat_t *r = pfs_task_find_creat_by_fileid(&f, 5002);
if (!r || strcmp(r->name, "b.txt") != 0)
FAIL("find_creat_by_fileid", "name=%s", r ? r->name : "(null)");
else
PASS("find_creat_by_fileid: finds node with fileid=5002");
free(a); free(b); free(c);
}
/* Empty folder: all finds return NULL */
static void test_empty_folder(void) {
psync_fstask_folder_t f;
folder_init(&f, 8);
int ok = 1;
if (pfs_task_find_mkdir(&f, "x", 0) != NULL) ok = 0;
if (pfs_task_find_rmdir(&f, "x", 0) != NULL) ok = 0;
if (pfs_task_find_creat(&f, "x", 0) != NULL) ok = 0;
if (pfs_task_find_unlink(&f, "x", 0) != NULL) ok = 0;
if (ok)
PASS("empty folder: all finds return NULL");
else
FAIL("empty folder", "unexpected non-NULL");
}
/* ------------------------------------------------------------------ */
int main(void) {
test_find_mkdir_basic();
test_find_mkdir_taskid();
test_find_rmdir_basic();
test_find_creat_basic();
test_find_unlink_basic();
test_find_mkdir_by_folderid();
test_find_creat_by_fileid();
test_empty_folder();
printf("\n%d passed, %d failed\n", passes, failures);
return failures ? 1 : 0;
}