// SPDX-License-Identifier: GPL-3.0-or-later // // This file is part of CProof. // See LICENSE for the full GPLv3 text and the special OpenSSL linking exception. /* * bench_stubs.c * vim: expandtab:ts=4:sts=4:sw=4 * * Minimal stubs so we can link the flat-file backend (database_flatfile*.c) * into the bench harness without pulling in the rest of profanity (xmpp, * ui, prefs, connection state, ...). * * Only ff_* helpers and ff_state_* / ff_verify_integrity are exercised * by the harness, so most code paths inside database_flatfile.c that * reference these symbols are never reached. The stubs exist purely to * resolve the linker. * * log_* writes to stderr when BENCH_LOG=1 in the environment, otherwise * silent — keeps the harness output clean while still letting us debug. */ #include "config.h" #include #include #include #include #include #include "log.h" #include "common.h" #include "config/files.h" #include "config/preferences.h" #include "database.h" #include "database_flatfile.h" // for ff_jid_to_dir() in stub #include "xmpp/xmpp.h" #include "xmpp/jid.h" #include "xmpp/message.h" #include "ui/ui.h" // --------------------------------------------------------------------------- // log_* (real impl, gated by BENCH_LOG=1) static int _bench_log_enabled(void) { static int cached = -1; if (cached == -1) { const char* env = getenv("BENCH_LOG"); cached = (env && env[0] && env[0] != '0') ? 1 : 0; } return cached; } static void _bench_log(const char* level, const char* fmt, va_list ap) { if (!_bench_log_enabled()) return; fprintf(stderr, "[%s] ", level); vfprintf(stderr, fmt, ap); fputc('\n', stderr); } void log_debug(const char* const msg, ...) { va_list ap; va_start(ap, msg); _bench_log("DEBUG", msg, ap); va_end(ap); } void log_info(const char* const msg, ...) { va_list ap; va_start(ap, msg); _bench_log("INFO", msg, ap); va_end(ap); } void log_warning(const char* const msg, ...) { va_list ap; va_start(ap, msg); _bench_log("WARN", msg, ap); va_end(ap); } void log_error(const char* const msg, ...) { va_list ap; va_start(ap, msg); _bench_log("ERROR", msg, ap); va_end(ap); } void log_init(log_level_t filter, const char* const log_file) { (void)filter; (void)log_file; } void log_close(void) { } void log_msg(log_level_t level, const char* const area, const char* const msg) { (void)level; (void)area; (void)msg; } const char* get_log_file_location(void) { return ""; } log_level_t log_get_filter(void) { return PROF_LEVEL_INFO; } int log_level_from_string(char* log_level, log_level_t* level) { (void)log_level; if (level) *level = PROF_LEVEL_INFO; return 0; } void log_stderr_init(log_level_t level) { (void)level; } void log_stderr_handler(void) { } // --------------------------------------------------------------------------- // prefs / files / xmpp / ui — never reached by the harness, but database_flatfile.c // references them, so we resolve the symbols. gchar* prefs_get_string(preference_t pref) { (void)pref; return NULL; } gboolean prefs_get_boolean(preference_t pref) { (void)pref; return FALSE; } void prefs_set_string(preference_t pref, const gchar* new_value) { (void)pref; (void)new_value; } void prefs_set_boolean(preference_t pref, gboolean value) { (void)pref; (void)value; } gchar* files_get_data_path(const char* const location) { const char* base = getenv("BENCH_DATA_DIR"); if (!base || !base[0]) base = "/tmp/cproof-bench"; if (location && location[0]) return g_strdup_printf("%s/%s", base, location); return g_strdup(base); } gchar* files_get_config_path(const char* const location) { const char* base = getenv("BENCH_DATA_DIR"); if (!base || !base[0]) base = "/tmp/cproof-bench"; if (location && location[0]) return g_strdup_printf("%s/%s", base, location); return g_strdup(base); } // $BENCH_DATA_DIR/$location/$jid_dir/$filename — mirrors the canonical // per-account layout. Caller g_free's. Required by _get_db_filename in // database_sqlite.c during _sqlite_init. char* files_file_in_account_data_path(const char* const location, const char* const account_jid, const char* const filename) { if (!account_jid || !filename) return NULL; const char* base = getenv("BENCH_DATA_DIR"); if (!base || !base[0]) base = "/tmp/cproof-bench"; auto_gchar gchar* jid_dir = ff_jid_to_dir(account_jid); auto_gchar gchar* parent = g_strdup_printf("%s/%s/%s", base, location && location[0] ? location : "", jid_dir); g_mkdir_with_parents(parent, 0755); return g_strdup_printf("%s/%s", parent, filename); } // jid_destroy is the public name; bench doesn't define a jid_destroy stub // because src/xmpp/jid.c isn't linked in. We emulate just enough for cleanup. static void _bench_jid_free(Jid* j) { if (!j) return; g_free(j->barejid); g_free(j->fulljid); g_free(j->resourcepart); g_free(j); } Jid* jid_create(const gchar* const fulljid) { if (!fulljid) return NULL; Jid* j = g_malloc0(sizeof(Jid)); j->fulljid = g_strdup(fulljid); const char* slash = strchr(fulljid, '/'); if (slash) { j->barejid = g_strndup(fulljid, slash - fulljid); j->resourcepart = g_strdup(slash + 1); } else { j->barejid = g_strdup(fulljid); } return j; } void jid_destroy(Jid* jid) { _bench_jid_free(jid); } // Weak so that bench targets which also link real database.c (which defines // the same symbol) take the strong version. bench_runner / bench_long_messages / // bench_failure_modes don't link database.c and rely on this stub. __attribute__((weak)) void integrity_issue_free(integrity_issue_t* issue) { if (!issue) return; g_free(issue->file); g_free(issue->message); g_free(issue); } void message_free(ProfMessage* m) { if (!m) return; _bench_jid_free(m->from_jid); _bench_jid_free(m->to_jid); g_free(m->id); g_free(m->originid); g_free(m->replace_id); g_free(m->stanzaid); g_free(m->body); g_free(m->encrypted); g_free(m->plain); if (m->timestamp) g_date_time_unref(m->timestamp); g_free(m); } // connection_get_jid: returns a process-wide stub Jid built from // $BENCH_ACCOUNT_JID (default "bench@bench.example"). Allocated lazily on // first call, freed at exit via atexit(). static Jid* g_bench_jid; static void _bench_jid_atexit(void) { if (!g_bench_jid) return; g_free(g_bench_jid->barejid); g_free(g_bench_jid->fulljid); g_free(g_bench_jid->resourcepart); g_free(g_bench_jid); g_bench_jid = NULL; } const Jid* connection_get_jid(void) { if (g_bench_jid) return g_bench_jid; const char* env = getenv("BENCH_ACCOUNT_JID"); if (!env || !env[0]) env = "bench@bench.example"; g_bench_jid = g_malloc0(sizeof(Jid)); g_bench_jid->barejid = g_strdup(env); g_bench_jid->fulljid = g_strdup(env); g_bench_jid->resourcepart = NULL; atexit(_bench_jid_atexit); return g_bench_jid; } ProfMessage* message_init(void) { return g_malloc0(sizeof(ProfMessage)); } Jid* jid_create_from_bare_and_resource(const char* const barejid, const char* const resource) { if (!barejid) return NULL; Jid* j = g_malloc0(sizeof(Jid)); j->barejid = g_strdup(barejid); j->resourcepart = resource ? g_strdup(resource) : NULL; j->fulljid = resource ? g_strdup_printf("%s/%s", barejid, resource) : g_strdup(barejid); return j; } void cons_show(const char* const msg, ...) { (void)msg; } void cons_show_error(const char* const cmd, ...) { (void)cmd; } // session/account stubs — used by database.c when wiring up backend switch. // Bench never goes through the dispatcher's switch path; just satisfy linker. const char* session_get_account_name(void) { return NULL; } ProfAccount* accounts_get_account(const char* const name) { (void)name; return NULL; } void account_free(ProfAccount* account) { if (!account) return; g_free(account->jid); g_free(account); }