/
matv3ys
/
QueueDriver
Обзор
Документация
Войти
/
matv3ys
/
QueueDriver
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
test/test.c
248 строк
7 KB
matv3ys
Done
14 дек 2025, 19:14
14 дек 2025, 19:14
d53eb16
Код
Авторство
О чём код?
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <poll.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include "../q_share.h" #define DEV_NAME_FMT "/dev/queue_drv%d" #define SYSFS_PATH_FMT "/sys/class/queue_drv/queue_drv%d/lost_count" #define NUM_DEVICES 4 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) /* Вспомогательные функции для Sysfs */ int read_lost_count(int dev_id) { char path[64]; char buf[16]; int fd; int val; snprintf(path, sizeof(path), SYSFS_PATH_FMT, dev_id); fd = open(path, O_RDONLY); if (fd < 0) errExit("Failed to open sysfs file"); if (read(fd, buf, sizeof(buf)) < 0) { close(fd); errExit("Failed to read sysfs"); } close(fd); val = atoi(buf); return val; } void reset_lost_count(int dev_id) { char path[64]; int fd; snprintf(path, sizeof(path), SYSFS_PATH_FMT, dev_id); fd = open(path, O_WRONLY); if (fd < 0) errExit("Failed to open sysfs file for writing"); if (write(fd, "0", 1) < 0) { close(fd); errExit("Failed to write to sysfs"); } close(fd); } /* ТЕСТ 1: Проверка Single Open */ void test_single_open(void) { char path[32]; int fd1, fd2; printf("=== TEST 1: Single Open Guarantee ===\n"); snprintf(path, sizeof(path), DEV_NAME_FMT, 0); printf("Opening %s (1st time)...\n", path); fd1 = open(path, O_RDWR | O_NONBLOCK); if (fd1 < 0) errExit("First open failed"); printf("Opening %s (2nd time) - Expecting failure...\n", path); fd2 = open(path, O_RDWR | O_NONBLOCK); if (fd2 < 0) { if (errno == EBUSY) { printf("[PASS] Second open failed with EBUSY as expected.\n"); } else { close(fd1); printf("[FAIL] Second open failed but with wrong error: %s\n", strerror(errno)); exit(EXIT_FAILURE); } } else { printf("[FAIL] Second open succeeded! (fd=%d)\n", fd2); close(fd1); close(fd2); exit(EXIT_FAILURE); } close(fd1); printf("Closed 1st fd.\n\n"); } /* ТЕСТ 2: Переполнение и Sysfs */ void test_overwrite_and_sysfs(void) { char path[32]; int fd; int i; int lost; struct queue_msg msg; int write_count = FIFO_ELEM_NUM + 5; // Пишем больше, чем влезает (16 + 5 = 21) printf("=== TEST 2: Overwrite Logic & Sysfs ===\n"); snprintf(path, sizeof(path), DEV_NAME_FMT, 1); // Используем устройство 1 /* 1. Сброс счетчика */ reset_lost_count(1); printf("Sysfs counter reset to 0.\n"); fd = open(path, O_RDWR | O_NONBLOCK); if (fd < 0) errExit("Open failed"); /* 2. Запись с переполнением */ printf("Queue capacity: %d. Writing %d messages...\n", FIFO_ELEM_NUM, write_count); for (i = 0; i < write_count; i++) { msg.a = i; // ID сообщения 0..20 msg.b = i * 100; if (write(fd, &msg, sizeof(msg)) < 0) { close(fd); errExit("Write failed"); } } /* 3. Проверка Sysfs */ lost = read_lost_count(1); printf("Messages written: %d. Expected lost: %d. Sysfs lost_count: %d\n", write_count, write_count - FIFO_ELEM_NUM, lost); if (lost != (write_count - FIFO_ELEM_NUM)) { close(fd); printf("[FAIL] Sysfs counter mismatch!\n"); exit(EXIT_FAILURE); } else { printf("[PASS] Sysfs counter correct.\n"); } /* 4. Проверка данных (должны остаться только последние 16) */ // Ожидаем, что старые (0, 1, 2, 3, 4) удалены. // Первое прочитанное должно быть 5. printf("Reading back queue...\n"); for (i = 0; i < FIFO_ELEM_NUM; i++) { if (read(fd, &msg, sizeof(msg)) < 0) { close(fd); errExit("Read failed"); } //printf("First message read: ID=%d (Expected %d)\n", msg.a, write_count - FIFO_ELEM_NUM); if (msg.a != (write_count - FIFO_ELEM_NUM + i)) { close(fd); printf("[FAIL] Logic error: read old data or wrong data.\n"); exit(EXIT_FAILURE); } } printf("[PASS] Oldest data was overwritten correctly.\n"); close(fd); printf("\n"); } /* ------------------------------------------------------------------ * ТЕСТ 3: Poll на 4 устройствах * ------------------------------------------------------------------ */ void test3_cleanup(struct pollfd *pfds, int count) { for (int i = 0; i < count; i++) { close(pfds[i].fd); } } void test_poll_all(void) { struct pollfd pfds[NUM_DEVICES]; char path[32]; int i; int active_fds = NUM_DEVICES; printf("=== TEST 3: Poll on 4 devices ===\n"); /* 1. Открываем все 4 устройства */ for (i = 0; i < NUM_DEVICES; i++) { snprintf(path, sizeof(path), DEV_NAME_FMT, i); pfds[i].fd = open(path, O_RDWR | O_NONBLOCK); if (pfds[i].fd < 0) { test3_cleanup(pfds, i + 1); errExit("Open failed"); } pfds[i].events = POLLIN; // Слушаем на чтение printf("Opened %s on fd %d\n", path, pfds[i].fd); /* 2. Записываем разное количество данных */ // dev0: 0 сообщений (пусто) // dev1: 1 сообщение // dev2: 2 сообщения // dev3: 3 сообщения for (int k = 0; k < i; k++) { struct queue_msg m = { .a = i, .b = k }; write(pfds[i].fd, &m, sizeof(m)); } } printf("Data populated. Starting poll loop...\n"); /* 3. Poll Loop */ while (active_fds > 0) { int ret = poll(pfds, NUM_DEVICES, 2000); // 2 sec timeout if (ret < 0) { test3_cleanup(pfds, NUM_DEVICES); errExit("poll"); } if (ret == 0) { printf("Poll timeout (Test finished)\n"); break; } for (i = 0; i < NUM_DEVICES; i++) { if (pfds[i].revents & POLLIN) { struct queue_msg m; ssize_t s = read(pfds[i].fd, &m, sizeof(m)); if (s > 0) { printf(" [Dev %d] Read msg: {%d, %d}\n", i, m.a, m.b); } else { test3_cleanup(pfds, NUM_DEVICES); errExit("read"); } } } } /* Cleanup */ test3_cleanup(pfds, NUM_DEVICES); printf("[PASS] Poll test completed.\n\n"); } int main(void) { printf("Starting QUEUE DRIVER Tests...\n\n"); test_single_open(); test_overwrite_and_sysfs(); test_poll_all(); printf("ALL TESTS PASSED SUCCESSFULLY.\n"); return 0; }