#include #include #include #include #include #include #include #include #include #define STATUS_FIFO "/tmp/looper_status" #define CMD_FIFO "/tmp/looper_cmd" static pid_t start_looper(void) { pid_t pid = fork(); if (pid < 0) { perror("fork"); return -1; } if (pid == 0) { close(2); open("/dev/null", O_WRONLY); execl("./looper", "looper", NULL); perror("execl"); _exit(1); } return pid; } /* Drain any stale data from the status FIFO */ static void drain_fifo(void) { int fd = open(STATUS_FIFO, O_RDONLY | O_NONBLOCK); if (fd < 0) return; char buf[4096]; while (read(fd, buf, sizeof(buf)) > 0); close(fd); } /* Read the first status line with a timeout (milliseconds). * Returns 0 on success, -1 on timeout/error. */ static int read_status_line_timeout(char *buf, size_t bufsize, int timeout_ms) { int fd = open(STATUS_FIFO, O_RDONLY | O_NONBLOCK); if (fd < 0) return -1; fd_set set; struct timeval tv; FD_ZERO(&set); FD_SET(fd, &set); tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; int ret = select(fd + 1, &set, NULL, NULL, &tv); if (ret <= 0) { close(fd); return -1; } int n = read(fd, buf, bufsize - 1); close(fd); if (n <= 0) return -1; buf[n] = '\0'; /* keep only the first line */ char *nl = strchr(buf, '\n'); if (nl) *nl = '\0'; return 0; } static int test_status_after_record(void) { printf("Test: status FIFO reports RECORD state after record command\n"); pid_t pid = start_looper(); if (pid < 0) return 1; /* Give looper time to start main loop and begin writing status */ usleep(1500000); drain_fifo(); /* Send record 0 command via FIFO */ int fd_cmd = open(CMD_FIFO, O_WRONLY); if (fd_cmd < 0) { fprintf(stderr, " FAIL: cannot open command FIFO\n"); kill(pid, SIGTERM); waitpid(pid, NULL, 0); return 1; } write(fd_cmd, "record 0\n", 9); close(fd_cmd); /* Keep reading status lines until we see RECORD or timeout (5 seconds) */ int found = 0; int ch, sc; char state[32]; char line[256]; for (int tries = 0; tries < 50; tries++) { if (read_status_line_timeout(line, sizeof(line), 100) != 0) { usleep(100000); continue; } if (sscanf(line, "CH=%d SC=%d STATE=%31s", &ch, &sc, state) != 3) continue; if (ch == 0 && sc == 0 && strcmp(state, "RECORD") == 0) { found = 1; break; } } if (!found) { fprintf(stderr, " FAIL: did not see STATE=RECORD for CH=0 SC=0 within 5 seconds\n"); kill(pid, SIGTERM); waitpid(pid, NULL, 0); return 1; } printf(" PASS\n"); kill(pid, SIGTERM); waitpid(pid, NULL, 0); return 0; } int main(void) { int fail = 0; fail += test_status_after_record(); return fail; }