diff --git a/src/database_export.c b/src/database_export.c index e16660c1..5fe24c51 100644 --- a/src/database_export.c +++ b/src/database_export.c @@ -379,7 +379,7 @@ log_database_export_to_flatfile(const gchar* const contact_jid) g_slist_free_full(merged, (GDestroyNotify)ff_parsed_line_free); fflush(fp); - fsync(fd); // ensure data is on disk before atomic rename + fsync(fd); // ensure data is on disk before atomic rename fclose(fp); // also releases flock // Atomic rename diff --git a/src/database_sqlite.c b/src/database_sqlite.c index 75af6b03..ec3ceb8b 100644 --- a/src/database_sqlite.c +++ b/src/database_sqlite.c @@ -55,7 +55,7 @@ static sqlite3* g_chatlog_database; -static void _add_to_db(ProfMessage* message, char* type, const Jid* const from_jid, const Jid* const to_jid); +static void _add_to_db(ProfMessage* message, const char* type, const Jid* const from_jid, const Jid* const to_jid); static char* _get_db_filename(ProfAccount* account); static prof_msg_type_t _get_message_type_type(const char* const type); static prof_enc_t _get_message_enc_type(const char* const encstr); @@ -147,22 +147,22 @@ _sqlite_init(ProfAccount* account) return TRUE; } - char* query = "CREATE TABLE IF NOT EXISTS `ChatLogs` (" - "`id` INTEGER PRIMARY KEY AUTOINCREMENT, " - "`from_jid` TEXT NOT NULL, " - "`to_jid` TEXT NOT NULL, " - "`from_resource` TEXT, " - "`to_resource` TEXT, " - "`message` TEXT, " - "`timestamp` TEXT, " - "`type` TEXT, " - "`stanza_id` TEXT, " - "`archive_id` TEXT, " - "`encryption` TEXT, " - "`marked_read` INTEGER, " - "`replace_id` TEXT, " - "`replaces_db_id` INTEGER, " - "`replaced_by_db_id` INTEGER)"; + const char* query = "CREATE TABLE IF NOT EXISTS `ChatLogs` (" + "`id` INTEGER PRIMARY KEY AUTOINCREMENT, " + "`from_jid` TEXT NOT NULL, " + "`to_jid` TEXT NOT NULL, " + "`from_resource` TEXT, " + "`to_resource` TEXT, " + "`message` TEXT, " + "`timestamp` TEXT, " + "`type` TEXT, " + "`stanza_id` TEXT, " + "`archive_id` TEXT, " + "`encryption` TEXT, " + "`marked_read` INTEGER, " + "`replace_id` TEXT, " + "`replaces_db_id` INTEGER, " + "`replaced_by_db_id` INTEGER)"; if (SQLITE_OK != sqlite3_exec(g_chatlog_database, query, NULL, 0, &err_msg)) { goto out; } @@ -251,7 +251,7 @@ _sqlite_add_incoming(ProfMessage* message) } static void -_log_database_add_outgoing(char* type, const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc) +_log_database_add_outgoing(const char* type, const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc) { ProfMessage* msg = message_init(); @@ -350,8 +350,8 @@ _sqlite_get_previous_chat(const gchar* const contact_barejid, const gchar* start return DB_RESPONSE_ERROR; } - gchar* sort1 = from_start ? "ASC" : "DESC"; - gchar* sort2 = !flip ? "ASC" : "DESC"; + const gchar* sort1 = from_start ? "ASC" : "DESC"; + const gchar* sort2 = !flip ? "ASC" : "DESC"; GDateTime* now = g_date_time_new_now_local(); auto_gchar gchar* end_date_fmt = end_time ? g_strdup(end_time) : g_date_time_format_iso8601(now); auto_sqlite gchar* query = sqlite3_mprintf("SELECT * FROM (" @@ -571,7 +571,7 @@ _get_message_enc_type(const char* const encstr) // --- Core write logic --- static void -_add_to_db(ProfMessage* message, char* type, const Jid* const from_jid, const Jid* const to_jid) +_add_to_db(ProfMessage* message, const char* type, const Jid* const from_jid, const Jid* const to_jid) { auto_gchar gchar* pref_dblog = prefs_get_string(PREF_DBLOG); sqlite_int64 original_message_id = -1; diff --git a/tests/functionaltests/functionaltests.c b/tests/functionaltests/functionaltests.c index b9c35214..db1a7ff3 100644 --- a/tests/functionaltests/functionaltests.c +++ b/tests/functionaltests/functionaltests.c @@ -66,7 +66,7 @@ int main(int argc, char* argv[]) { - int group = 0; /* 0 = all groups */ + int group = 0; /* 0 = all groups */ if (argc > 1) { group = atoi(argv[1]); if (group < 1 || group > 4) { @@ -79,7 +79,7 @@ main(int argc, char* argv[]) char group_env[16]; snprintf(group_env, sizeof(group_env), "%d", group); setenv("PROF_TEST_GROUP", group_env, 1); - + fprintf(stderr, "[PROF_TEST] Starting functional tests, group=%d\n", group); /* ============================================================ @@ -268,7 +268,8 @@ main(int argc, char* argv[]) }; /* Test group registry for easy extension */ - struct { + struct + { const char* name; const struct CMUnitTest* tests; size_t count; diff --git a/tests/functionaltests/proftest.c b/tests/functionaltests/proftest.c index 84e818f8..1b708308 100644 --- a/tests/functionaltests/proftest.c +++ b/tests/functionaltests/proftest.c @@ -20,8 +20,8 @@ /* Number of parallel test groups for CI builds */ #define TEST_GROUPS 4 -char *config_orig; -char *data_orig; +char* config_orig; +char* data_orig; int fd = 0; int stub_port = 5230; @@ -47,7 +47,7 @@ static size_t output_len = 0; static int expect_timeout = 30; gboolean -_create_dir(const char *name) +_create_dir(const char* name) { struct stat sb; @@ -65,14 +65,14 @@ _create_dir(const char *name) } gboolean -_mkdir_recursive(const char *dir) +_mkdir_recursive(const char* dir) { int i; gboolean result = TRUE; for (i = 1; i <= strlen(dir); i++) { if (dir[i] == '/' || dir[i] == '\0') { - gchar *next_dir = g_strndup(dir, i); + gchar* next_dir = g_strndup(dir, i); result = _create_dir(next_dir); g_free(next_dir); if (!result) { @@ -87,7 +87,7 @@ _mkdir_recursive(const char *dir) void _create_config_dir(void) { - GString *profanity_dir = g_string_new(xdg_config_home); + GString* profanity_dir = g_string_new(xdg_config_home); g_string_append(profanity_dir, "/profanity"); if (!_mkdir_recursive(profanity_dir->str)) { @@ -100,7 +100,7 @@ _create_config_dir(void) void _create_data_dir(void) { - GString *profanity_dir = g_string_new(xdg_data_home); + GString* profanity_dir = g_string_new(xdg_data_home); g_string_append(profanity_dir, "/profanity"); if (!_mkdir_recursive(profanity_dir->str)) { @@ -113,7 +113,7 @@ _create_data_dir(void) void _create_chatlogs_dir(void) { - GString *chatlogs_dir = g_string_new(xdg_data_home); + GString* chatlogs_dir = g_string_new(xdg_data_home); g_string_append(chatlogs_dir, "/profanity/chatlogs"); if (!_mkdir_recursive(chatlogs_dir->str)) { @@ -126,7 +126,7 @@ _create_chatlogs_dir(void) void _create_logs_dir(void) { - GString *logs_dir = g_string_new(xdg_data_home); + GString* logs_dir = g_string_new(xdg_data_home); g_string_append(logs_dir, "/profanity/logs"); if (!_mkdir_recursive(logs_dir->str)) { @@ -139,12 +139,12 @@ _create_logs_dir(void) void _cleanup_dirs(void) { - const char *group_env = getenv("PROF_TEST_GROUP"); + const char* group_env = getenv("PROF_TEST_GROUP"); int group = group_env ? atoi(group_env) : 0; int dir_id = (group >= 1 && group <= TEST_GROUPS) ? group : stub_port; - + printf("[PROF_TEST] Cleaning up directories for group %d (dir_id %d)\n", group, dir_id); - + char cmd[512]; snprintf(cmd, sizeof(cmd), "rm -rf ./test-files/%d", dir_id); int res = system(cmd); @@ -162,26 +162,26 @@ _read_output(int timeout_ms) { fd_set readfds; struct timeval tv; - + FD_ZERO(&readfds); FD_SET(fd, &readfds); - + tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; - + int ret = select(fd + 1, &readfds, NULL, NULL, &tv); if (ret <= 0) { return ret; } - + size_t space = OUTPUT_BUF_SIZE - output_len - 1; if (space <= 0) { /* Buffer full, shift content */ - memmove(output_buffer, output_buffer + OUTPUT_BUF_SIZE/2, OUTPUT_BUF_SIZE/2); - output_len = OUTPUT_BUF_SIZE/2; + memmove(output_buffer, output_buffer + OUTPUT_BUF_SIZE / 2, OUTPUT_BUF_SIZE / 2); + output_len = OUTPUT_BUF_SIZE / 2; space = OUTPUT_BUF_SIZE - output_len - 1; } - + ssize_t n = read(fd, output_buffer + output_len, space); if (n > 0) { output_len += n; @@ -199,69 +199,69 @@ prof_start(void) { struct winsize ws; ws.ws_row = 24; - ws.ws_col = 300; /* Match COLUMNS=300 from start_profanity.sh */ + ws.ws_col = 300; /* Match COLUMNS=300 from start_profanity.sh */ ws.ws_xpixel = 0; ws.ws_ypixel = 0; - + /* Reset output buffer */ output_len = 0; output_buffer[0] = '\0'; - + child_pid = forkpty(&fd, NULL, NULL, &ws); - + if (child_pid < 0) { fd = -1; return; } - + if (child_pid == 0) { /* Child process */ setenv("COLUMNS", "300", 1); setenv("TERM", "xterm", 1); - + execl("./profanity", "./profanity", "-l", "DEBUG", NULL); - + /* If exec fails */ fprintf(stderr, "execl failed: %s\n", strerror(errno)); _exit(127); } - + /* Parent process */ /* Set non-blocking mode for reading */ int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); - + /* Brief wait for process to initialize */ - usleep(50000); /* 50ms */ + usleep(50000); /* 50ms */ } int -init_prof_test(void **state) +init_prof_test(void** state) { /* Get test group from environment for static resource allocation */ - const char *group_env = getenv("PROF_TEST_GROUP"); + const char* group_env = getenv("PROF_TEST_GROUP"); int group = group_env ? atoi(group_env) : 0; - + /* Get build index for port offset (for parallel CI builds) */ - const char *build_env = getenv("PROF_BUILD_INDEX"); + const char* build_env = getenv("PROF_BUILD_INDEX"); int build_idx = build_env ? atoi(build_env) : 0; - + /* Calculate port base: each build uses a different range of TEST_GROUPS ports. * Build 0 (local/default): 5230-5233, Full: 5230-5233, Minimal: 5234-5237, etc. * Build 0 and Full share the same range because build 0 is for local runs or sequential run (no parallel builds), * while Full/Minimal/NoEncrypt/Default are used in CI where they run in parallel. */ int port_base = 5230 + ((build_idx > 0 ? build_idx - 1 : 0) * TEST_GROUPS); - + /* Static resource allocation to avoid conflicts in parallel execution. * Group 1-4: use static port assignment. * Group 0 (all groups): use dynamic allocation as fallback. */ gboolean started = FALSE; - + if (group >= 1 && group <= TEST_GROUPS) { /* Static allocation: each group gets a dedicated port */ stub_port = port_base + group - 1; printf("[PROF_TEST] Build %d, Group %d: trying port %d\n", build_idx, group, stub_port); - + if (stbbr_start(STBBR_LOGDEBUG, stub_port, 0) == 0) { started = TRUE; printf("[PROF_TEST] Started stabber on port %d\n", stub_port); @@ -269,7 +269,7 @@ init_prof_test(void **state) printf("[PROF_TEST] Failed to start stabber on port %d\n", stub_port); } } - + /* Fallback to dynamic allocation if static failed or group=0 */ if (!started) { printf("[PROF_TEST] Using dynamic port allocation\n"); @@ -282,7 +282,7 @@ init_prof_test(void **state) } } } - + if (!started) { fprintf(stderr, "[PROF_TEST] ERROR: could not start stabber on any port\n"); return -1; @@ -295,8 +295,8 @@ init_prof_test(void **state) "./test-files/%d/xdg_config_home", dir_id); snprintf(xdg_data_home, sizeof(xdg_data_home), "./test-files/%d/xdg_data_home", dir_id); - - printf("[PROF_TEST] Group %d using directories: config=%s, data=%s\n", + + printf("[PROF_TEST] Group %d using directories: config=%s, data=%s\n", group, xdg_config_home, xdg_data_home); // Give stabber server thread time to start listening @@ -316,12 +316,12 @@ init_prof_test(void **state) _create_logs_dir(); /* If PROF_FLATFILE=1 is set, write a profrc that selects the flat-file backend */ - const char *flatfile_env = getenv("PROF_FLATFILE"); + const char* flatfile_env = getenv("PROF_FLATFILE"); if (flatfile_env && strcmp(flatfile_env, "1") == 0) { char profrc_path[512]; snprintf(profrc_path, sizeof(profrc_path), "%s/profanity/profrc", xdg_config_home); - FILE *prc = fopen(profrc_path, "w"); + FILE* prc = fopen(profrc_path, "w"); if (prc) { fprintf(prc, "[logging]\ndblog=flatfile\n"); fclose(prc); @@ -365,7 +365,7 @@ init_prof_test(void **state) } int -close_prof_test(void **state) +close_prof_test(void** state) { if (fd > 0 && child_pid > 0) { prof_input("/quit"); @@ -391,7 +391,7 @@ close_prof_test(void **state) * to ensure the port is released before the next test starts. * See: https://git.jabber.space/devs/stabber/issues/3 */ - usleep(100000); // 100ms + usleep(100000); // 100ms return 0; } @@ -410,18 +410,18 @@ prof_stop(void) output_len = 0; output_buffer[0] = '\0'; /* Brief delay to let stabber release old connection state */ - usleep(200000); /* 200ms */ + usleep(200000); /* 200ms */ } void -prof_input(const char *input) +prof_input(const char* input) { - GString *inp_str = g_string_new(input); + GString* inp_str = g_string_new(input); g_string_append(inp_str, "\r"); ssize_t _wn = write(fd, inp_str->str, inp_str->len); (void)_wn; g_string_free(inp_str, TRUE); - + /* Small delay to let profanity process input */ usleep(10000); } @@ -431,24 +431,24 @@ prof_input(const char *input) * Returns 1 if found, 0 if timeout. */ int -prof_output_exact(const char *text) +prof_output_exact(const char* text) { time_t start = time(NULL); - + while (time(NULL) - start < expect_timeout) { /* Read any available output */ while (_read_output(100) > 0) { /* Keep reading while data available */ } - + /* Check if text is in buffer */ if (strstr(output_buffer, text) != NULL) { return 1; } - - usleep(50000); /* 50ms */ + + usleep(50000); /* 50ms */ } - + return 0; } @@ -457,34 +457,34 @@ prof_output_exact(const char *text) * Returns 1 if found, 0 if timeout. */ int -prof_output_regex(const char *pattern) +prof_output_regex(const char* pattern) { regex_t regex; int ret; - + ret = regcomp(®ex, pattern, REG_EXTENDED | REG_NOSUB); if (ret != 0) { return 0; } - + time_t start = time(NULL); - + while (time(NULL) - start < expect_timeout) { /* Read any available output */ while (_read_output(100) > 0) { /* Keep reading while data available */ } - + /* Check if pattern matches */ ret = regexec(®ex, output_buffer, 0, NULL, 0); if (ret == 0) { regfree(®ex); return 1; } - - usleep(50000); /* 50ms */ + + usleep(50000); /* 50ms */ } - + /* Timeout reached - log diagnostic info */ fprintf(stderr, "Timeout waiting for regex '%s' after %d seconds. Last output:\n", pattern, expect_timeout); size_t len = strlen(output_buffer); @@ -494,23 +494,21 @@ prof_output_regex(const char *pattern) fprintf(stderr, "%s", output_buffer); } fprintf(stderr, "\n"); - + regfree(®ex); return 0; } void -prof_connect_with_roster(const char *roster) +prof_connect_with_roster(const char* roster) { - GString *roster_str = g_string_new( + GString* roster_str = g_string_new( "" - "" - ); + ""); g_string_append(roster_str, roster); g_string_append(roster_str, - "" - "" - ); + "" + ""); stbbr_for_query("jabber:iq:roster", roster_str->str); g_string_free(roster_str, TRUE); @@ -520,7 +518,7 @@ prof_connect_with_roster(const char *roster) char connect_cmd[128]; snprintf(connect_cmd, sizeof(connect_cmd), "/connect stabber@localhost server 127.0.0.1 port %d tls disable auth legacy", stub_port); prof_input(connect_cmd); - + assert_true(prof_output_regex("password:")); prof_input("password"); @@ -528,15 +526,14 @@ prof_connect_with_roster(const char *roster) assert_true(prof_output_regex("Connecting as stabber@localhost")); assert_true(prof_output_regex("logged in successfully")); assert_true(prof_output_regex(".+online.+ \\(priority 0\\)\\.")); - + expect_timeout = 60; // Wait for presence stanza to be sent (content-based, not ID-based) // Match the actual attribute order from stanza_attach_caps assert_true(stbbr_received( "" - "" - "" - )); + "" + "")); } void @@ -556,6 +553,5 @@ prof_connect(void) { prof_connect_with_roster( "" - "" - ); + ""); } diff --git a/tests/functionaltests/proftest.h b/tests/functionaltests/proftest.h index c1d9d218..4e4bd255 100644 --- a/tests/functionaltests/proftest.h +++ b/tests/functionaltests/proftest.h @@ -11,17 +11,17 @@ extern char xdg_data_home[256]; extern int stub_port; -int init_prof_test(void **state); -int close_prof_test(void **state); +int init_prof_test(void** state); +int close_prof_test(void** state); void prof_start(void); void prof_stop(void); void prof_connect(void); -void prof_connect_with_roster(const char *roster); -void prof_input(const char *input); +void prof_connect_with_roster(const char* roster); +void prof_input(const char* input); -int prof_output_exact(const char *text); -int prof_output_regex(const char *text); +int prof_output_exact(const char* text); +int prof_output_regex(const char* text); void prof_timeout(int timeout); void prof_timeout_reset(void); diff --git a/tests/functionaltests/test_history.c b/tests/functionaltests/test_history.c index 5242e6d9..61b2dfba 100644 --- a/tests/functionaltests/test_history.c +++ b/tests/functionaltests/test_history.c @@ -36,7 +36,7 @@ * it was persisted to and read back from the database */ void -message_db_history_on_reopen(void **state) +message_db_history_on_reopen(void** state) { prof_connect(); @@ -81,7 +81,7 @@ message_db_history_on_reopen(void **state) * we can reliably synchronise on each delivery before proceeding. */ void -message_db_history_multiple(void **state) +message_db_history_multiple(void** state) { prof_connect(); @@ -131,7 +131,7 @@ message_db_history_multiple(void **state) * 3. Open buddy1 → verify buddy1's body present, buddy2's body absent */ void -message_db_history_contact_isolation(void **state) +message_db_history_contact_isolation(void** state) { prof_connect(); @@ -177,7 +177,7 @@ message_db_history_contact_isolation(void **state) * characters and return them unchanged. */ void -message_db_history_special_chars(void **state) +message_db_history_special_chars(void** state) { prof_connect(); @@ -210,7 +210,7 @@ message_db_history_special_chars(void **state) * and catches crashes in the outgoing DB code. */ void -message_db_history_outgoing(void **state) +message_db_history_outgoing(void** state) { prof_connect(); @@ -238,7 +238,7 @@ message_db_history_outgoing(void **state) * and the outgoing write path completed without error. */ void -message_db_history_dialog(void **state) +message_db_history_dialog(void** state) { prof_connect(); @@ -279,7 +279,7 @@ message_db_history_dialog(void **state) * does not crash and the window is usable. */ void -message_db_history_empty(void **state) +message_db_history_empty(void** state) { prof_connect(); @@ -299,7 +299,7 @@ message_db_history_empty(void **state) * Test: a long message (1000+ characters) is not truncated by the DB. */ void -message_db_history_long_message(void **state) +message_db_history_long_message(void** state) { prof_connect(); @@ -313,10 +313,11 @@ message_db_history_long_message(void **state) char xml[1500]; snprintf(xml, sizeof(xml), - "" - "%s" - "", body); + "" + "%s" + "", + body); stbbr_send(xml); assert_true(prof_output_exact("<< chat message: Buddy1/phone (win 2)")); @@ -335,7 +336,7 @@ message_db_history_long_message(void **state) * Uses XML character reference for literal newline in body. */ void -message_db_history_newline(void **state) +message_db_history_newline(void** state) { prof_connect(); @@ -364,7 +365,7 @@ message_db_history_newline(void **state) * percent, braces, brackets, equals) survive DB round-trip. */ void -message_db_history_service_chars(void **state) +message_db_history_service_chars(void** state) { prof_connect(); @@ -389,7 +390,7 @@ message_db_history_service_chars(void **state) * Test: /history verify reports no issues after normal message writes. */ void -message_db_history_verify(void **state) +message_db_history_verify(void** state) { prof_connect(); @@ -425,7 +426,7 @@ message_db_history_verify(void **state) * text should appear — the original should be absent. */ void -message_db_history_lmc(void **state) +message_db_history_lmc(void** state) { prof_connect(); diff --git a/tests/functionaltests/test_history.h b/tests/functionaltests/test_history.h index 551bfc8d..14fc6cd2 100644 --- a/tests/functionaltests/test_history.h +++ b/tests/functionaltests/test_history.h @@ -1,12 +1,12 @@ -void message_db_history_on_reopen(void **state); -void message_db_history_multiple(void **state); -void message_db_history_contact_isolation(void **state); -void message_db_history_special_chars(void **state); -void message_db_history_outgoing(void **state); -void message_db_history_dialog(void **state); -void message_db_history_empty(void **state); -void message_db_history_long_message(void **state); -void message_db_history_newline(void **state); -void message_db_history_service_chars(void **state); -void message_db_history_verify(void **state); -void message_db_history_lmc(void **state); +void message_db_history_on_reopen(void** state); +void message_db_history_multiple(void** state); +void message_db_history_contact_isolation(void** state); +void message_db_history_special_chars(void** state); +void message_db_history_outgoing(void** state); +void message_db_history_dialog(void** state); +void message_db_history_empty(void** state); +void message_db_history_long_message(void** state); +void message_db_history_newline(void** state); +void message_db_history_service_chars(void** state); +void message_db_history_verify(void** state); +void message_db_history_lmc(void** state);