// SPDX-License-Identifier: GPL-2.0-only
/*
 *  ppm/tests/test_path.c
 *
 *  Copyright (C) 2026 Project Tick
 */

#include "util/path.h"

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#define CHECK(expr) do {                                            \
    if (!(expr)) {                                                  \
        fprintf(stderr, "FAIL: %s:%d: %s\n", __FILE__, __LINE__, #expr); \
        return 1;                                                   \
    }                                                               \
} while (0)

static char *make_tmp_root(void) {
    char tpl[] = "/tmp/ppm-test-XXXXXX";
    char *p = mkdtemp(tpl);
    if (!p) return NULL;
    return strdup(p);
}

int main(void) {
    /* Path join basics. */
    char *p = NULL;
    CHECK(ppm_path_join("a", "b", &p) == PPM_OK);
    CHECK(strcmp(p, "a/b") == 0); free(p);
    CHECK(ppm_path_join("a/", "/b", &p) == PPM_OK);
    CHECK(strcmp(p, "a/b") == 0); free(p);
    CHECK(ppm_path_join("/root", "sub", &p) == PPM_OK);
    CHECK(strcmp(p, "/root/sub") == 0); free(p);

    /* mkdirs + rmrf round-trip. */
    char *root = make_tmp_root();
    CHECK(root != NULL);

    char *deep;
    CHECK(ppm_path_join(root, "a/b/c/d", &deep) == PPM_OK);
    CHECK(ppm_path_mkdirs(deep, 0755) == PPM_OK);
    CHECK(ppm_path_is_dir(deep));

    /* mkdirs is idempotent. */
    CHECK(ppm_path_mkdirs(deep, 0755) == PPM_OK);

    /* fsync_dir should succeed on a real directory. */
    CHECK(ppm_path_fsync_dir(deep) == PPM_OK);

    /* rmrf wipes the whole tree, including a file inside it. */
    char *leaf;
    CHECK(ppm_path_join(deep, "file.txt", &leaf) == PPM_OK);
    FILE *f = fopen(leaf, "w");
    CHECK(f != NULL);
    fputs("hello", f);
    fclose(f);

    CHECK(ppm_path_rmrf(root) == PPM_OK);
    CHECK(!ppm_path_is_dir(root));

    /* rmrf of a missing path is OK. */
    CHECK(ppm_path_rmrf(root) == PPM_OK);

    free(leaf);
    free(deep);
    free(root);

    printf("ok\n");
    return 0;
}
