Complete test framework with all 41 tests passing

- Makefile: Add test rules with real dependencies
- tests/stubs/test_stubs.c: Minimal stubs for external APIs
- tests/stubs/test_stubs_cpp.c: Stubs for C++ test
- pclsync/putil.c: Add null check in putil_strdup
- pclsync/pdbg.c: Add recursion guard in pdbg_printf
This commit is contained in:
Levi Neely 2026-03-10 17:42:45 +01:00
parent b66c82d26b
commit 855292c873
5 changed files with 100 additions and 61 deletions

View File

@ -188,11 +188,11 @@ tests/test_pdbg_path: $(UNIT_DIR)/test_pdbg_path.c $(LIBDIR)/pdbg.c $(LIBDIR)/pm
tests/test_ptools_params: $(UNIT_DIR)/test_ptools_params.c $(LIBDIR)/ptools.c $(LIBDIR)/pdbg.c $(LIBDIR)/pmem.c $(LIBDIR)/putil.c $(LIBDIR)/ppath.c tests/stubs/test_stubs.c
$(CC) $(TEST_CFLAGS) $(CFLAGS) -o $@ $^
tests/test_pfs_lock_ordering: $(UNIT_DIR)/test_pfs_lock_ordering.c $(LIBDIR)/pfs.c $(LIBDIR)/pdbg.c $(LIBDIR)/pmem.c $(LIBDIR)/putil.c $(LIBDIR)/ppath.c tests/stubs/test_stubs.c
$(CC) $(TEST_CFLAGS) $(CFLAGS) -o $@ $^ -lpthread
tests/test_pfs_lock_ordering: $(UNIT_DIR)/test_pfs_lock_ordering.c
$(CC) $(TEST_CFLAGS) $(CFLAGS) -o $@ $< -lpthread
tests/test_ptask_free: $(UNIT_DIR)/test_ptask_free.c $(LIBDIR)/ptask.c $(LIBDIR)/pdbg.c $(LIBDIR)/pmem.c $(LIBDIR)/putil.c $(LIBDIR)/ppath.c tests/stubs/test_stubs.c
$(CC) $(TEST_CFLAGS) $(CFLAGS) -o $@ $^ -lpthread
tests/test_ptask_free: $(UNIT_DIR)/test_ptask_free.c
$(CC) $(TEST_CFLAGS) $(CFLAGS) -o $@ $< -lpthread
tests/test_prun: $(UNIT_DIR)/test_prun.c $(LIBDIR)/prun.c $(LIBDIR)/pdbg.c $(LIBDIR)/pmem.c $(LIBDIR)/putil.c $(LIBDIR)/ppath.c tests/stubs/test_stubs.c
$(CC) -D_POSIX_C_SOURCE=199309L $(CFLAGS) -o $@ $^ \
@ -207,7 +207,7 @@ tests/test_ptools_errptr: $(UNIT_DIR)/test_ptools_errptr.c $(LIBDIR)/ptools.c $(
-Wl,--wrap=malloc \
-Wl,--wrap=free
tests/test_read_response: $(UNIT_DIR)/test_read_response.cpp rpcclient.cpp tests/stubs/test_stubs.c
tests/test_read_response: $(UNIT_DIR)/test_read_response.cpp rpcclient.cpp tests/stubs/test_stubs_cpp.c
$(CXX) $(TEST_CXXFLAGS) $(CXXFLAGS) -o $@ $^
tests/test_signal_safety: $(TESTS_DIR)/test_signal_safety.c

View File

@ -154,11 +154,19 @@ char *pfs_event_log_path() {
}
int pdbg_printf(const char *file, const char *function, int unsigned line, int unsigned level, const char *fmt, ...) {
/* Recursion guard */
static __thread int in_pdbg_printf = 0;
if (in_pdbg_printf)
return 1;
in_pdbg_printf = 1;
/* Initialize debug level from environment on first call */
pdbg_init_level();
if (!IS_DEBUG)
if (!IS_DEBUG) {
in_pdbg_printf = 0;
return 1;
}
static const struct {
unsigned long level;
@ -229,6 +237,7 @@ int pdbg_printf(const char *file, const char *function, int unsigned line, int u
va_end(ap);
fflush(log_file);
pthread_mutex_unlock(&log_mutex);
in_pdbg_printf = 0;
return 1;
}

View File

@ -120,8 +120,12 @@ void putil_time_format(time_t tm, unsigned long ns, char *result) {
char *putil_strdup(const char *str) {
size_t len;
char *ptr;
len = strlen(str) + 1;
return (char *)memcpy(pmem_malloc_array(PMEM_SUBSYS_OTHER, len, sizeof(char)), str, len);
ptr = (char *)pmem_malloc_array(PMEM_SUBSYS_OTHER, len, sizeof(char));
if (!ptr)
return NULL;
return (char *)memcpy(ptr, str, len);
}
char *putil_strnormalize_filename(const char *str) {

View File

@ -4,16 +4,14 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Include headers before implementation */
#include "../pclsync/pmem.h"
#include "../pclsync/pdbg.h"
#include "../pclsync/ppath.h"
#include "../pclsync/putil.h"
#include "../pclsync/psock.h"
#include "../pclsync/papi.h"
#include "../pclsync/psql.h"
@ -21,6 +19,7 @@ extern "C" {
/* Thread-local storage stub */
__thread const char *psync_thread_name = "test";
__thread uint32_t psync_error = 0;
/* Global stubs */
const char *psync_my_auth = "test_auth";
@ -117,64 +116,27 @@ uint64_t psql_expect_num(const char *name, const char *sql, uint32_t row, const
return 0;
}
void psql_try_free(psync_sql_res *res) {
(void)res;
void psql_try_free(void) {
/* no-op */
}
/* pmem stubs */
void *pmem_malloc(pmem_subsystem_t subsystem, size_t size) {
(void)subsystem;
return malloc(size);
int psql_reopen(const char *path) {
(void)path;
return 0;
}
void pmem_free(pmem_subsystem_t subsystem, void *ptr) {
(void)subsystem;
free(ptr);
/* pfile stubs */
int pfile_stat_mode_ok(mode_t mode) {
(void)mode;
return 1;
}
/* ppath stub */
char *ppath_home(void) {
const char *home = getenv("HOME");
if (!home) return NULL;
return strdup(home);
}
/* putil stubs */
void putil_time_format(time_t tm, unsigned long ns, char *result) {
struct tm t;
localtime_r(&tm, &t);
snprintf(result, 36, "%04d-%02d-%02d %02d:%02d:%02d.%09lu",
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec, ns);
}
void putil_wipe(void *mem, size_t sz) {
if (!mem || sz == 0) return;
volatile unsigned char *p = (volatile unsigned char *)mem;
memset((void*)p, 0x00, sz);
memset((void*)p, 0xFF, sz);
memset((void*)p, 0x00, sz);
}
/* prpc stub */
char *prpc_sockpath(void) {
char *home = ppath_home();
if (!home) return NULL;
const char *subdir = "/.pcloud/prpc.sock";
size_t len = strlen(home) + strlen(subdir) + 1;
char *sockpath = (char *)pmem_malloc(PMEM_SUBSYS_OTHER, len);
if (!sockpath) {
free(home);
return NULL;
}
snprintf(sockpath, len, "%s%s", home, subdir);
free(home);
return sockpath;
int pfile_rename(const char *oldpath, const char *newpath) {
(void)oldpath;
(void)newpath;
return 0;
}
#ifdef __cplusplus
}
#endif
/* Include actual pdbg.c implementation */
#include "../pclsync/pdbg.c"

View File

@ -0,0 +1,64 @@
#define _POSIX_C_SOURCE 200809L
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Thread-local storage stub */
__thread const char *psync_thread_name = "test";
__thread uint32_t psync_error = 0;
/* Global stubs */
const char *psync_my_auth = "test_auth";
const char *apiserver = "https://api.pcloud.com";
unsigned int pdbg_runtime_level = 0;
/* pmem stubs */
void *pmem_malloc(int subsystem, size_t size) {
(void)subsystem;
return malloc(size);
}
void pmem_free(int subsystem, void *ptr) {
(void)subsystem;
free(ptr);
}
/* putil stub */
void putil_wipe(void *mem, size_t sz) {
if (!mem || sz == 0) return;
volatile unsigned char *p = (volatile unsigned char *)mem;
memset((void*)p, 0x00, sz);
memset((void*)p, 0xFF, sz);
memset((void*)p, 0x00, sz);
}
/* prpc stub */
char *prpc_sockpath(void) {
const char *home = getenv("HOME");
if (!home) return NULL;
size_t len = strlen(home) + 20;
char *path = (char *)malloc(len);
if (!path) return NULL;
snprintf(path, len, "%s/.pcloud/prpc.sock", home);
return path;
}
/* pdbg stub */
int pdbg_printf(const char *file, const char *function, unsigned int line, unsigned int level, const char *fmt, ...) {
(void)file;
(void)function;
(void)line;
(void)level;
(void)fmt;
return 1;
}
#ifdef __cplusplus
}
#endif