LCOV - code coverage report
Current view: top level - tests/functional/pty - terminal_coverage_harness.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 77.5 % 142 110
Test Date: 2026-04-20 19:54:22 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /* SPDX-License-Identifier: GPL-3.0-or-later */
       2              : /* Copyright 2026 Peter Csaszar */
       3              : 
       4              : /**
       5              :  * @file terminal_coverage_harness.c
       6              :  * @brief Harness binary that exercises terminal.c paths for coverage.
       7              :  *
       8              :  * Each mode exercises a specific area of src/platform/posix/terminal.c.
       9              :  * The test runner (test_terminal_coverage.c) drives this binary through
      10              :  * a PTY or via piped stdin to reach all uncovered lines.
      11              :  *
      12              :  * Modes:
      13              :  *   cols_rows        - call terminal_cols() / terminal_rows() and print results
      14              :  *   raw_enter_exit   - enter/exit raw mode, print result
      15              :  *   read_key         - raw mode: read one key, print name, exit
      16              :  *   wait_key         - call terminal_wait_key(500), print READY/TIMEOUT
      17              :  *   install_handlers - enter raw mode, install cleanup handlers, then exit 0
      18              :  *   resize_notify    - enable resize notifications, loop until resize or 'q'
      19              :  *   passwd_nontty    - call terminal_read_password when stdin is a pipe (non-TTY)
      20              :  */
      21              : 
      22              : #include "platform/terminal.h"
      23              : 
      24              : #include <stdio.h>
      25              : #include <string.h>
      26              : #include <stdlib.h>
      27              : #include <unistd.h>
      28              : #include <signal.h>
      29              : 
      30              : /* ---- cols_rows --------------------------------------------------------- */
      31              : 
      32            1 : static int mode_cols_rows(void) {
      33            1 :     int c = terminal_cols();
      34            1 :     int r = terminal_rows();
      35              :     /* On a real PTY both should be > 0; on non-TTY fallback values apply. */
      36            1 :     printf("COLS:%d\n", c);
      37            1 :     printf("ROWS:%d\n", r);
      38            1 :     fflush(stdout);
      39            1 :     return 0;
      40              : }
      41              : 
      42              : /* ---- raw_enter_exit ---------------------------------------------------- */
      43              : 
      44            1 : static int mode_raw_enter_exit(void) {
      45            1 :     TermRawState *st = terminal_raw_enter();
      46            1 :     if (!st) {
      47            0 :         printf("RAW_ENTER:FAIL\n");
      48            0 :         fflush(stdout);
      49            0 :         return 1;
      50              :     }
      51            1 :     printf("RAW_ENTER:OK\n");
      52            1 :     fflush(stdout);
      53            1 :     terminal_raw_exit(&st);
      54            1 :     if (st != NULL) {
      55            0 :         printf("RAW_EXIT:FAIL\n");
      56            0 :         fflush(stdout);
      57            0 :         return 1;
      58              :     }
      59            1 :     printf("RAW_EXIT:OK\n");
      60            1 :     fflush(stdout);
      61            1 :     return 0;
      62              : }
      63              : 
      64              : /* ---- read_key ---------------------------------------------------------- */
      65              : 
      66              : /**
      67              :  * Enter raw mode, print "READY", then read keys until 'q' or a count limit.
      68              :  * For each key print its name so the test can assert receipt.
      69              :  */
      70            3 : static int mode_read_key(void) {
      71            3 :     TermRawState *st = terminal_raw_enter();
      72            3 :     if (!st) {
      73            0 :         printf("RAW:FAIL\n");
      74            0 :         fflush(stdout);
      75            0 :         return 1;
      76              :     }
      77            3 :     printf("READY\n");
      78            3 :     fflush(stdout);
      79              : 
      80              :     /* Read up to 32 keystrokes, exit on 'q' (printable) or TERM_KEY_QUIT */
      81           28 :     for (int i = 0; i < 32; i++) {
      82              :         /* Use terminal_wait_key so that path is also hit. */
      83           28 :         int avail = terminal_wait_key(3000);
      84           28 :         if (avail <= 0) {
      85            0 :             printf("TIMEOUT\n");
      86            0 :             fflush(stdout);
      87            0 :             break;
      88              :         }
      89           28 :         TermKey k = terminal_read_key();
      90           28 :         int lp = terminal_last_printable();
      91           28 :         switch (k) {
      92            1 :         case TERM_KEY_QUIT:      printf("KEY:QUIT\n");      fflush(stdout); goto done;
      93            1 :         case TERM_KEY_ENTER:     printf("KEY:ENTER\n");     fflush(stdout); break;
      94            1 :         case TERM_KEY_ESC:       printf("KEY:ESC\n");       fflush(stdout); break;
      95            1 :         case TERM_KEY_BACK:      printf("KEY:BACK\n");      fflush(stdout); break;
      96            1 :         case TERM_KEY_LEFT:      printf("KEY:LEFT\n");      fflush(stdout); break;
      97            1 :         case TERM_KEY_RIGHT:     printf("KEY:RIGHT\n");     fflush(stdout); break;
      98            1 :         case TERM_KEY_PREV_LINE: printf("KEY:UP\n");        fflush(stdout); break;
      99            1 :         case TERM_KEY_NEXT_LINE: printf("KEY:DOWN\n");      fflush(stdout); break;
     100            4 :         case TERM_KEY_HOME:      printf("KEY:HOME\n");      fflush(stdout); break;
     101            4 :         case TERM_KEY_END:       printf("KEY:END\n");       fflush(stdout); break;
     102            1 :         case TERM_KEY_DELETE:    printf("KEY:DELETE\n");    fflush(stdout); break;
     103            1 :         case TERM_KEY_PREV_PAGE: printf("KEY:PGUP\n");      fflush(stdout); break;
     104            1 :         case TERM_KEY_NEXT_PAGE: printf("KEY:PGDN\n");      fflush(stdout); break;
     105            1 :         case TERM_KEY_CTRL_A:    printf("KEY:CTRL_A\n");    fflush(stdout); break;
     106            1 :         case TERM_KEY_CTRL_E:    printf("KEY:CTRL_E\n");    fflush(stdout); break;
     107            1 :         case TERM_KEY_CTRL_K:    printf("KEY:CTRL_K\n");    fflush(stdout); break;
     108            1 :         case TERM_KEY_CTRL_W:    printf("KEY:CTRL_W\n");    fflush(stdout); break;
     109            1 :         case TERM_KEY_CTRL_D:    printf("KEY:CTRL_D\n");    fflush(stdout); goto done;
     110            4 :         case TERM_KEY_IGNORE:
     111            4 :             if (lp) {
     112            2 :                 if (lp == 'q') {
     113            1 :                     printf("KEY:q\n");
     114            1 :                     fflush(stdout);
     115            1 :                     goto done;
     116              :                 }
     117            1 :                 printf("KEY:CHAR:%c\n", (char)lp);
     118            1 :                 fflush(stdout);
     119              :             } else {
     120            2 :                 printf("KEY:IGNORE\n");
     121            2 :                 fflush(stdout);
     122              :             }
     123            3 :             break;
     124              :         }
     125              :     }
     126            0 : done:
     127            3 :     terminal_raw_exit(&st);
     128            3 :     return 0;
     129              : }
     130              : 
     131              : /* ---- wait_key ---------------------------------------------------------- */
     132              : 
     133            1 : static int mode_wait_key(void) {
     134              :     /* Signal readiness so the test can send a byte after seeing READY. */
     135            1 :     printf("READY\n");
     136            1 :     fflush(stdout);
     137            1 :     int rc = terminal_wait_key(3000);
     138            1 :     if (rc > 0)
     139            1 :         printf("WAIT_KEY:READY\n");
     140            0 :     else if (rc == 0)
     141            0 :         printf("WAIT_KEY:TIMEOUT\n");
     142              :     else
     143            0 :         printf("WAIT_KEY:INTR\n");
     144            1 :     fflush(stdout);
     145            1 :     return 0;
     146              : }
     147              : 
     148              : /* ---- install_handlers -------------------------------------------------- */
     149              : 
     150            1 : static int mode_install_handlers(void) {
     151            1 :     TermRawState *st = terminal_raw_enter();
     152            1 :     if (!st) {
     153            0 :         printf("HANDLERS:FAIL\n");
     154            0 :         fflush(stdout);
     155            0 :         return 1;
     156              :     }
     157              :     /* Install the handlers — this exercises terminal_install_cleanup_handlers
     158              :      * and exposes g_saved_termios. */
     159            1 :     terminal_install_cleanup_handlers(st);
     160            1 :     printf("HANDLERS:OK\n");
     161            1 :     fflush(stdout);
     162              :     /* Clean exit: restore terminal before exiting so the PTY isn't stuck. */
     163            1 :     terminal_raw_exit(&st);
     164            1 :     return 0;
     165              : }
     166              : 
     167              : /* ---- resize_notify ----------------------------------------------------- */
     168              : 
     169            1 : static int mode_resize_notify(void) {
     170            1 :     terminal_enable_resize_notifications();
     171              :     /* Call a second time to cover the "already installed" guard. */
     172            1 :     terminal_enable_resize_notifications();
     173              : 
     174            1 :     printf("RESIZE_READY\n");
     175            1 :     fflush(stdout);
     176              : 
     177              :     /* Poll for a resize event or 'q' for up to 3 s. */
     178            1 :     TermRawState *st = terminal_raw_enter();
     179            1 :     if (!st) {
     180            0 :         printf("RAW:FAIL\n");
     181            0 :         fflush(stdout);
     182            0 :         return 1;
     183              :     }
     184            2 :     for (int i = 0; i < 30; i++) {
     185            2 :         if (terminal_consume_resize()) {
     186            1 :             printf("RESIZE_DETECTED\n");
     187            1 :             fflush(stdout);
     188            1 :             break;
     189              :         }
     190            1 :         int avail = terminal_wait_key(100);
     191            1 :         if (avail > 0) {
     192            0 :             TermKey k = terminal_read_key();
     193            0 :             int lp = terminal_last_printable();
     194            0 :             if (k == TERM_KEY_QUIT || (k == TERM_KEY_IGNORE && lp == 'q')) {
     195            0 :                 printf("QUIT\n");
     196            0 :                 fflush(stdout);
     197            0 :                 break;
     198              :             }
     199              :         }
     200              :     }
     201            1 :     terminal_raw_exit(&st);
     202            1 :     return 0;
     203              : }
     204              : 
     205              : /* ---- passwd_nontty ----------------------------------------------------- */
     206              : 
     207              : /**
     208              :  * Call terminal_read_password when stdin is NOT a TTY (piped).
     209              :  * This exercises the else-branch in terminal_read_password (lines 328-346).
     210              :  */
     211            2 : static int mode_passwd_nontty(void) {
     212              :     char buf[64];
     213            2 :     int rc = terminal_read_password("TestPrompt", buf, sizeof(buf));
     214            2 :     if (rc < 0) {
     215            1 :         printf("PASSWD:ERROR\n");
     216            1 :         fflush(stdout);
     217            1 :         return 1;
     218              :     }
     219            1 :     printf("PASSWD:%s\n", buf);
     220            1 :     printf("PASSWD_LEN:%d\n", rc);
     221            1 :     fflush(stdout);
     222            1 :     return 0;
     223              : }
     224              : 
     225              : /* ---- main -------------------------------------------------------------- */
     226              : 
     227           10 : int main(int argc, char **argv) {
     228           10 :     if (argc < 2) {
     229            0 :         fprintf(stderr, "usage: terminal_coverage_harness <mode>\n");
     230            0 :         return 2;
     231              :     }
     232              : 
     233           10 :     if (strcmp(argv[1], "cols_rows")        == 0) return mode_cols_rows();
     234            9 :     if (strcmp(argv[1], "raw_enter_exit")   == 0) return mode_raw_enter_exit();
     235            8 :     if (strcmp(argv[1], "read_key")         == 0) return mode_read_key();
     236            5 :     if (strcmp(argv[1], "wait_key")         == 0) return mode_wait_key();
     237            4 :     if (strcmp(argv[1], "install_handlers") == 0) return mode_install_handlers();
     238            3 :     if (strcmp(argv[1], "resize_notify")    == 0) return mode_resize_notify();
     239            2 :     if (strcmp(argv[1], "passwd_nontty")    == 0) return mode_passwd_nontty();
     240              : 
     241            0 :     fprintf(stderr, "unknown mode: %s\n", argv[1]);
     242            0 :     return 2;
     243              : }
        

Generated by: LCOV version 2.0-1