LCOV - code coverage report
Current view: top level - tests/pty - test_pty_send_local.c (source / functions) Coverage Total Hit
Test: coverage-functional.info Lines: 57.3 % 260 149
Test Date: 2026-05-07 15:53:08 Functions: 85.7 % 21 18

            Line data    Source code
       1              : /**
       2              :  * @file test_pty_send_local.c
       3              :  * @brief PTY tests for local-first send behaviour (US-SL-01 to US-SL-04).
       4              :  *
       5              :  * US-SL-01: Successful SMTP send → message saved to local Sent folder,
       6              :  *           queued in pending_appends.tsv, TUI shows "Saved locally".
       7              :  * US-SL-02: Failed SMTP send → message saved to local Drafts folder,
       8              :  *           queued in pending_appends.tsv, TUI shows "Saved to Drafts".
       9              :  * US-SL-03: email-sync uploads pending messages and clears the queue.
      10              :  * US-SL-04: pending_appends.tsv survives between runs (persistent queue).
      11              :  *
      12              :  * Usage: test-pty-send-local <email-tui> <email-sync>
      13              :  *                             <mock-imap-server> <mock-smtp-server>
      14              :  */
      15              : 
      16              : #define _DEFAULT_SOURCE
      17              : #define _XOPEN_SOURCE 600
      18              : 
      19              : #include "ptytest.h"
      20              : #include "pty_assert.h"
      21              : 
      22              : #include <dirent.h>
      23              : #include <fcntl.h>
      24              : #include <netinet/in.h>
      25              : #include <signal.h>
      26              : #include <stdio.h>
      27              : #include <stdlib.h>
      28              : #include <string.h>
      29              : #include <sys/socket.h>
      30              : #include <sys/stat.h>
      31              : #include <sys/wait.h>
      32              : #include <unistd.h>
      33              : 
      34              : /* ── Test globals ────────────────────────────────────────────────────── */
      35              : 
      36              : int g_tests_run    = 0;
      37              : int g_tests_failed = 0;
      38              : 
      39              : static char g_tui_bin[512];
      40              : static char g_sync_bin[512];
      41              : static char g_imap_bin[512];
      42              : static char g_smtp_bin[512];
      43              : 
      44              : static char g_test_home[512];
      45              : static char g_old_home[512];
      46              : static char g_editor_script[600];
      47              : 
      48              : static pid_t g_imap_pid = -1;
      49              : static pid_t g_smtp_pid = -1;
      50              : 
      51              : #define WAIT_MS    8000
      52              : #define SETTLE_MS   400
      53              : #define ROWS 24
      54              : #define COLS 120
      55              : 
      56              : #define RUN_TEST(fn) do { printf("  %s...\n", #fn); fflush(stdout); fn(); } while(0)
      57              : 
      58              : /* Account directory under test HOME (username-based path) */
      59              : #define ACCOUNT_DIR  "/.local/share/email-cli/accounts/testuser@example.com"
      60              : 
      61              : /* ── Fake editor ─────────────────────────────────────────────────────── */
      62              : 
      63           19 : static void write_editor_script(void) {
      64           19 :     snprintf(g_editor_script, sizeof(g_editor_script),
      65              :              "%s/.fake_editor.sh", g_test_home);
      66           19 :     FILE *f = fopen(g_editor_script, "w");
      67           19 :     if (!f) return;
      68           19 :     fprintf(f, "#!/bin/sh\necho 'Test body' >> \"$1\"\n");
      69           19 :     fclose(f);
      70           19 :     chmod(g_editor_script, 0755);
      71           19 :     setenv("EDITOR", g_editor_script, 1);
      72              : }
      73              : 
      74              : /* ── Directory setup ──────────────────────────────────────────────────── */
      75              : 
      76           24 : static void mkdirs(void) {
      77              :     char d[700];
      78           24 :     snprintf(d, sizeof(d), "%s/.config",                              g_test_home); mkdir(d, 0700);
      79           24 :     snprintf(d, sizeof(d), "%s/.config/email-cli",                    g_test_home); mkdir(d, 0700);
      80           24 :     snprintf(d, sizeof(d), "%s/.config/email-cli/accounts",           g_test_home); mkdir(d, 0700);
      81           24 :     snprintf(d, sizeof(d), "%s/.config/email-cli/accounts/testuser",  g_test_home); mkdir(d, 0700);
      82           24 :     snprintf(d, sizeof(d), "%s/.local",                               g_test_home); mkdir(d, 0700);
      83           24 :     snprintf(d, sizeof(d), "%s/.local/share",                         g_test_home); mkdir(d, 0700);
      84           24 :     snprintf(d, sizeof(d), "%s/.local/share/email-cli",               g_test_home); mkdir(d, 0700);
      85           24 :     snprintf(d, sizeof(d), "%s/.local/share/email-cli/accounts",      g_test_home); mkdir(d, 0700);
      86           24 :     snprintf(d, sizeof(d), "%s%s",                                    g_test_home, ACCOUNT_DIR); mkdir(d, 0700);
      87           24 :     snprintf(d, sizeof(d), "%s%s/manifests",                          g_test_home, ACCOUNT_DIR); mkdir(d, 0700);
      88           24 : }
      89              : 
      90           19 : static void write_config(void) {
      91           19 :     mkdirs();
      92              :     char path[800];
      93           19 :     snprintf(path, sizeof(path),
      94              :              "%s/.config/email-cli/accounts/testuser/config.ini", g_test_home);
      95           19 :     FILE *fp = fopen(path, "w");
      96           19 :     if (!fp) return;
      97           19 :     fprintf(fp,
      98              :         "EMAIL_HOST=imaps://localhost:9993\n"
      99              :         "EMAIL_USER=testuser@example.com\n"
     100              :         "EMAIL_PASS=testpass\n"
     101              :         "EMAIL_FOLDER=INBOX\n"
     102              :         "SMTP_HOST=smtps://localhost:9025\n"
     103              :         "SMTP_PORT=9025\n"
     104              :         "SMTP_USER=testuser@example.com\n"
     105              :         "SMTP_PASS=testpass\n"
     106              :         "SSL_NO_VERIFY=1\n");
     107           19 :     fclose(fp);
     108           19 :     chmod(path, 0600);
     109              : }
     110              : 
     111              : /* ── Server helpers ───────────────────────────────────────────────────── */
     112              : 
     113           44 : static int probe_port(int port) {
     114           44 :     int fd = socket(AF_INET, SOCK_STREAM, 0);
     115           44 :     if (fd < 0) return -1;
     116           44 :     struct sockaddr_in a = {0};
     117           44 :     a.sin_family = AF_INET;
     118           44 :     a.sin_port   = htons((uint16_t)port);
     119           44 :     a.sin_addr.s_addr = htonl(0x7f000001);
     120           44 :     int r = connect(fd, (struct sockaddr *)&a, sizeof(a));
     121           44 :     close(fd);
     122           44 :     return r;
     123              : }
     124              : 
     125           44 : static void start_server(const char *bin, pid_t *pid_out) {
     126           44 :     *pid_out = fork();
     127           57 :     if (*pid_out < 0) return;
     128           57 :     if (*pid_out == 0) {
     129           13 :         int devnull = open("/dev/null", O_WRONLY);
     130           13 :         if (devnull >= 0) { dup2(devnull, 1); dup2(devnull, 2); close(devnull); }
     131           13 :         execl(bin, bin, (char *)NULL);
     132           13 :         _exit(127);
     133              :     }
     134           44 :     usleep(800000);
     135              : }
     136              : 
     137           50 : static void stop_server(pid_t *pid_out) {
     138           50 :     if (*pid_out > 0) {
     139           37 :         kill(*pid_out, SIGKILL);
     140           37 :         waitpid(*pid_out, NULL, 0);
     141           37 :         *pid_out = -1;
     142              :     }
     143           50 : }
     144              : 
     145              : /* Kill any process still listening on the given TCP port (cleanup of
     146              :  * lingering instances from previous test runs). */
     147            4 : static void kill_listeners_on_port(int port) {
     148              :     char cmd[80];
     149            4 :     snprintf(cmd, sizeof(cmd), "fuser -k -KILL %d/tcp >/dev/null 2>&1", port);
     150            4 :     int _unused = system(cmd); (void)_unused;
     151            4 :     usleep(200000);
     152            4 : }
     153              : 
     154           24 : static void restart_imap(void) {
     155           24 :     stop_server(&g_imap_pid);
     156           24 :     usleep(200000);
     157           24 :     start_server(g_imap_bin, &g_imap_pid);
     158           24 :     for (int i = 0; i < 30 && probe_port(9993) != 0; i++) usleep(100000);
     159           24 : }
     160              : 
     161           20 : static void restart_smtp(void) {
     162           20 :     stop_server(&g_smtp_pid);
     163           20 :     usleep(200000);
     164           20 :     start_server(g_smtp_bin, &g_smtp_pid);
     165           20 :     for (int i = 0; i < 30 && probe_port(9025) != 0; i++) usleep(100000);
     166           20 : }
     167              : 
     168              : /* ── TUI / sync runners ───────────────────────────────────────────────── */
     169              : 
     170           14 : static PtySession *tui_run(void) {
     171           14 :     const char *args[4] = { g_tui_bin, NULL };
     172           14 :     PtySession *s = pty_open(COLS, ROWS);
     173           14 :     if (!s) return NULL;
     174           14 :     if (pty_run(s, args) != 0) { pty_close(s); return NULL; }
     175           10 :     return s;
     176              : }
     177              : 
     178            0 : static PtySession *sync_run(const char **extra_args) {
     179              :     const char *argv[16];
     180            0 :     int n = 0;
     181            0 :     argv[n++] = g_sync_bin;
     182            0 :     if (extra_args)
     183            0 :         for (int i = 0; extra_args[i] && n < 15; i++)
     184            0 :             argv[n++] = extra_args[i];
     185            0 :     argv[n] = NULL;
     186            0 :     PtySession *s = pty_open(COLS, ROWS);
     187            0 :     if (!s) return NULL;
     188            0 :     if (pty_run(s, argv) != 0) { pty_close(s); return NULL; }
     189            0 :     return s;
     190              : }
     191              : 
     192              : /*
     193              :  * Navigate TUI to the folder browser for the test account.
     194              :  * Returns a running PtySession ready at the folder browser screen,
     195              :  * or NULL on failure.
     196              :  */
     197           14 : static PtySession *tui_open_to_folders(void) {
     198           14 :     write_config();
     199           14 :     PtySession *s = tui_run();
     200           10 :     if (!s) return NULL;
     201           10 :     if (pty_wait_for(s, "testuser", WAIT_MS) != 0) { pty_close(s); return NULL; }
     202            0 :     pty_settle(s, SETTLE_MS);
     203            0 :     pty_send_key(s, PTY_KEY_ENTER);
     204            0 :     if (pty_wait_for(s, "Folders", WAIT_MS) != 0) { pty_close(s); return NULL; }
     205            0 :     pty_settle(s, SETTLE_MS);
     206            0 :     return s;
     207              : }
     208              : 
     209              : /*
     210              :  * Navigate TUI to the INBOX message list.
     211              :  */
     212           14 : static PtySession *tui_open_to_inbox(void) {
     213           14 :     PtySession *s = tui_open_to_folders();
     214           10 :     if (!s) return NULL;
     215            0 :     pty_send_key(s, PTY_KEY_HOME);
     216            0 :     for (int i = 0; i < 6; i++) { pty_send_key(s, PTY_KEY_DOWN); pty_settle(s, 50); }
     217            0 :     if (pty_wait_for(s, "INBOX", WAIT_MS) != 0) { pty_close(s); return NULL; }
     218            0 :     pty_settle(s, SETTLE_MS);
     219            0 :     pty_send_key(s, PTY_KEY_ENTER);
     220            0 :     if (pty_wait_for(s, "message(s) in", WAIT_MS) != 0) { pty_close(s); return NULL; }
     221            0 :     pty_settle(s, SETTLE_MS);
     222            0 :     return s;
     223              : }
     224              : 
     225              : /* ── File-system helpers ──────────────────────────────────────────────── */
     226              : 
     227              : /* Return 1 if the pending_appends.tsv file contains a line starting with folder. */
     228            0 : static int pending_has_folder(const char *folder) {
     229              :     char path[800];
     230            0 :     snprintf(path, sizeof(path), "%s%s/pending_appends.tsv", g_test_home, ACCOUNT_DIR);
     231            0 :     FILE *fp = fopen(path, "r");
     232            0 :     if (!fp) return 0;
     233              :     char line[512];
     234            0 :     while (fgets(line, sizeof(line), fp)) {
     235            0 :         if (strncmp(line, folder, strlen(folder)) == 0 && line[strlen(folder)] == '\t') {
     236            0 :             fclose(fp);
     237            0 :             return 1;
     238              :         }
     239              :     }
     240            0 :     fclose(fp);
     241            0 :     return 0;
     242              : }
     243              : 
     244              : /* Return 1 if the pending_appends.tsv file is empty or does not exist. */
     245            0 : static int pending_is_empty(void) {
     246              :     char path[800];
     247            0 :     snprintf(path, sizeof(path), "%s%s/pending_appends.tsv", g_test_home, ACCOUNT_DIR);
     248            0 :     FILE *fp = fopen(path, "r");
     249            0 :     if (!fp) return 1; /* does not exist → empty */
     250            0 :     int c = fgetc(fp);
     251            0 :     fclose(fp);
     252            0 :     return (c == EOF);
     253              : }
     254              : 
     255              : /* Delete pending_appends.tsv to reset state between tests. */
     256           14 : static void pending_reset(void) {
     257              :     char path[800];
     258           14 :     snprintf(path, sizeof(path), "%s%s/pending_appends.tsv", g_test_home, ACCOUNT_DIR);
     259           14 :     unlink(path);
     260           14 : }
     261              : 
     262              : /* ══════════════════════════════════════════════════════════════════════
     263              :  * TC-SL-01 (US-SL-01): Successful SMTP send → local Sent + pending queue
     264              :  * ══════════════════════════════════════════════════════════════════════ */
     265              : 
     266            5 : static void test_successful_send_saves_locally(void) {
     267            5 :     pending_reset();
     268            5 :     restart_imap(); restart_smtp();
     269            5 :     write_editor_script();
     270            5 :     PtySession *s = tui_open_to_inbox();
     271            4 :     ASSERT(s != NULL, "TC-SL-01: reached inbox");
     272              : 
     273              :     /* Press 'c' to open compose dialog */
     274            0 :     pty_send_str(s, "c");
     275            0 :     ASSERT_WAIT_FOR(s, "New Message", WAIT_MS);
     276            0 :     pty_settle(s, SETTLE_MS);
     277              : 
     278              :     /* Fill To: field and Tab to Subject */
     279            0 :     pty_send_str(s, "recipient@example.com");
     280            0 :     pty_send_key(s, PTY_KEY_TAB); /* To → Cc */
     281            0 :     pty_send_key(s, PTY_KEY_TAB); /* Cc → Bcc */
     282            0 :     pty_send_key(s, PTY_KEY_TAB); /* Bcc → Subject */
     283            0 :     pty_send_str(s, "TC-SL-01 Test Subject");
     284            0 :     pty_send_key(s, PTY_KEY_ENTER); /* open editor */
     285              : 
     286              :     /* Wait for send confirmation prompt, confirm, then check result */
     287            0 :     ASSERT_WAIT_FOR(s, "Send?", WAIT_MS * 2);
     288            0 :     pty_send_str(s, "y");
     289            0 :     ASSERT_WAIT_FOR(s, "Sending", WAIT_MS);
     290            0 :     ASSERT_WAIT_FOR(s, "Message sent.", WAIT_MS);
     291            0 :     ASSERT_WAIT_FOR(s, "Saved locally", WAIT_MS);
     292              : 
     293            0 :     pty_close(s);
     294              : 
     295              :     /* Verify pending_appends.tsv has a Sent entry */
     296            0 :     ASSERT(pending_has_folder("Sent"), "TC-SL-01: pending_appends.tsv has Sent entry");
     297              : }
     298              : 
     299              : /* ══════════════════════════════════════════════════════════════════════
     300              :  * TC-SL-02 (US-SL-02): Failed SMTP send → local Drafts + pending queue
     301              :  * ══════════════════════════════════════════════════════════════════════ */
     302              : 
     303            4 : static void test_failed_send_saves_to_drafts(void) {
     304            4 :     pending_reset();
     305            4 :     restart_imap();
     306            4 :     stop_server(&g_smtp_pid);       /* kill the server we started */
     307            4 :     kill_listeners_on_port(9025);   /* kill any lingering instance */
     308            4 :     write_editor_script();
     309            4 :     PtySession *s = tui_open_to_inbox();
     310            3 :     ASSERT(s != NULL, "TC-SL-02: reached inbox");
     311              : 
     312            0 :     pty_send_str(s, "c");
     313            0 :     ASSERT_WAIT_FOR(s, "New Message", WAIT_MS);
     314            0 :     pty_settle(s, SETTLE_MS);
     315              : 
     316            0 :     pty_send_str(s, "recipient@example.com");
     317            0 :     pty_send_key(s, PTY_KEY_TAB);
     318            0 :     pty_send_key(s, PTY_KEY_TAB);
     319            0 :     pty_send_key(s, PTY_KEY_TAB);
     320            0 :     pty_send_str(s, "TC-SL-02 Test Draft");
     321            0 :     pty_send_key(s, PTY_KEY_ENTER);
     322              : 
     323              :     /* Wait for send confirmation, confirm, then check failure path */
     324            0 :     ASSERT_WAIT_FOR(s, "Send?", WAIT_MS * 2);
     325            0 :     pty_send_str(s, "y");
     326            0 :     ASSERT_WAIT_FOR(s, "Sending", WAIT_MS);
     327            0 :     ASSERT_WAIT_FOR(s, "Saved to Drafts", WAIT_MS);
     328              : 
     329            0 :     pty_close(s);
     330              : 
     331              :     /* Verify pending_appends.tsv has a Drafts entry */
     332            0 :     ASSERT(pending_has_folder("Drafts"), "TC-SL-02: pending_appends.tsv has Drafts entry");
     333              : }
     334              : 
     335              : /* ══════════════════════════════════════════════════════════════════════
     336              :  * TC-SL-03 (US-SL-03): email-sync uploads pending messages, clears queue
     337              :  * ══════════════════════════════════════════════════════════════════════ */
     338              : 
     339            3 : static void test_sync_uploads_pending_and_clears_queue(void) {
     340              :     /* Seed pending_appends.tsv via a successful send first */
     341            3 :     pending_reset();
     342            3 :     restart_imap(); restart_smtp();
     343            3 :     write_editor_script();
     344            3 :     PtySession *s = tui_open_to_inbox();
     345            2 :     ASSERT(s != NULL, "TC-SL-03 setup: reached inbox");
     346              : 
     347            0 :     pty_send_str(s, "c");
     348            0 :     ASSERT_WAIT_FOR(s, "New Message", WAIT_MS);
     349            0 :     pty_settle(s, SETTLE_MS);
     350            0 :     pty_send_str(s, "recipient@example.com");
     351            0 :     pty_send_key(s, PTY_KEY_TAB);
     352            0 :     pty_send_key(s, PTY_KEY_TAB);
     353            0 :     pty_send_key(s, PTY_KEY_TAB);
     354            0 :     pty_send_str(s, "TC-SL-03 Sync Test");
     355            0 :     pty_send_key(s, PTY_KEY_ENTER);
     356            0 :     ASSERT_WAIT_FOR(s, "Send?", WAIT_MS * 2);
     357            0 :     pty_send_str(s, "y");
     358            0 :     ASSERT_WAIT_FOR(s, "Saved locally", WAIT_MS);
     359            0 :     pty_close(s);
     360              : 
     361            0 :     ASSERT(pending_has_folder("Sent"), "TC-SL-03 setup: Sent entry queued before sync");
     362              : 
     363              :     /* Run email-sync to upload the pending message */
     364            0 :     PtySession *ss = sync_run(NULL);
     365            0 :     ASSERT(ss != NULL, "TC-SL-03: email-sync started");
     366            0 :     ASSERT_WAIT_FOR(ss, "uploaded", WAIT_MS);
     367            0 :     pty_close(ss);
     368              : 
     369              :     /* Queue should now be empty */
     370            0 :     ASSERT(pending_is_empty(), "TC-SL-03: pending_appends.tsv empty after sync");
     371              : }
     372              : 
     373              : /* ══════════════════════════════════════════════════════════════════════
     374              :  * TC-SL-04 (US-SL-04): pending queue survives process restart
     375              :  * ══════════════════════════════════════════════════════════════════════ */
     376              : 
     377            2 : static void test_pending_queue_survives_restart(void) {
     378              :     /* Seed via a successful send */
     379            2 :     pending_reset();
     380            2 :     restart_imap(); restart_smtp();
     381            2 :     write_editor_script();
     382            2 :     PtySession *s = tui_open_to_inbox();
     383            1 :     ASSERT(s != NULL, "TC-SL-04 setup: reached inbox");
     384              : 
     385            0 :     pty_send_str(s, "c");
     386            0 :     ASSERT_WAIT_FOR(s, "New Message", WAIT_MS);
     387            0 :     pty_settle(s, SETTLE_MS);
     388            0 :     pty_send_str(s, "recipient@example.com");
     389            0 :     pty_send_key(s, PTY_KEY_TAB);
     390            0 :     pty_send_key(s, PTY_KEY_TAB);
     391            0 :     pty_send_key(s, PTY_KEY_TAB);
     392            0 :     pty_send_str(s, "TC-SL-04 Persist Test");
     393            0 :     pty_send_key(s, PTY_KEY_ENTER);
     394            0 :     ASSERT_WAIT_FOR(s, "Send?", WAIT_MS * 2);
     395            0 :     pty_send_str(s, "y");
     396            0 :     ASSERT_WAIT_FOR(s, "Saved locally", WAIT_MS);
     397            0 :     pty_close(s);
     398              : 
     399            0 :     ASSERT(pending_has_folder("Sent"), "TC-SL-04: Sent entry in queue after send");
     400              : 
     401              :     /* Stop all servers; restart — queue must still be there */
     402            0 :     stop_server(&g_smtp_pid);
     403              : 
     404            0 :     ASSERT(pending_has_folder("Sent"), "TC-SL-04: Sent entry persists after process restart");
     405              : }
     406              : 
     407              : /* ── main ─────────────────────────────────────────────────────────────── */
     408              : 
     409            5 : int main(int argc, char **argv) {
     410            5 :     printf("--- Local-first send PTY Tests (US-SL-01 … US-SL-04) ---\n\n");
     411              : 
     412            5 :     if (argc < 5) {
     413            0 :         fprintf(stderr,
     414              :                 "Usage: %s <email-tui> <email-sync> "
     415              :                 "<mock-imap-server> <mock-smtp-server>\n",
     416              :                 argv[0]);
     417            0 :         return 1;
     418              :     }
     419              : 
     420            5 :     snprintf(g_tui_bin,  sizeof(g_tui_bin),  "%s", argv[1]);
     421            5 :     snprintf(g_sync_bin, sizeof(g_sync_bin), "%s", argv[2]);
     422            5 :     snprintf(g_imap_bin, sizeof(g_imap_bin), "%s", argv[3]);
     423            5 :     snprintf(g_smtp_bin, sizeof(g_smtp_bin), "%s", argv[4]);
     424              : 
     425            5 :     snprintf(g_test_home, sizeof(g_test_home), "/tmp/test-send-local-XXXXXX");
     426            5 :     if (!mkdtemp(g_test_home)) {
     427            0 :         perror("mkdtemp");
     428            0 :         return 1;
     429              :     }
     430            5 :     if (getenv("HOME"))
     431            5 :         snprintf(g_old_home, sizeof(g_old_home), "%s", getenv("HOME"));
     432            5 :     setenv("HOME", g_test_home, 1);
     433              : 
     434            5 :     mkdirs();
     435            5 :     write_config();
     436            5 :     write_editor_script();
     437              : 
     438            5 :     restart_imap();
     439            5 :     restart_smtp();
     440              : 
     441            5 :     printf("--- US-SL-01: Successful send saves locally ---\n");
     442            5 :     RUN_TEST(test_successful_send_saves_locally);
     443              : 
     444            4 :     printf("\n--- US-SL-02: Failed send saves to Drafts ---\n");
     445            4 :     RUN_TEST(test_failed_send_saves_to_drafts);
     446              : 
     447            3 :     printf("\n--- US-SL-03: Sync uploads pending messages ---\n");
     448            3 :     restart_imap(); restart_smtp();
     449            3 :     RUN_TEST(test_sync_uploads_pending_and_clears_queue);
     450              : 
     451            2 :     printf("\n--- US-SL-04: Pending queue survives restart ---\n");
     452            2 :     restart_imap(); restart_smtp();
     453            2 :     RUN_TEST(test_pending_queue_survives_restart);
     454              : 
     455            1 :     stop_server(&g_imap_pid);
     456            1 :     stop_server(&g_smtp_pid);
     457              : 
     458            1 :     if (g_old_home[0]) setenv("HOME", g_old_home, 1);
     459              : 
     460            1 :     printf("\n--- Test Results ---\n");
     461            1 :     printf("Tests Run:    %d\n", g_tests_run);
     462            1 :     printf("Tests Passed: %d\n", g_tests_run - g_tests_failed);
     463            1 :     printf("Tests Failed: %d\n", g_tests_failed);
     464              : 
     465            1 :     return g_tests_failed > 0 ? 1 : 0;
     466              : }
        

Generated by: LCOV version 2.0-1