Bläddra i källkod

feat(test_fifo_write): 重构FIFO写入测试,使其输出更加可读

xiaolin2004 4 månader sedan
förälder
incheckning
85a7c38694
1 ändrade filer med 155 tillägg och 97 borttagningar
  1. 155 97
      user/apps/test_fifo_write/main.c

+ 155 - 97
user/apps/test_fifo_write/main.c

@@ -1,137 +1,195 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <unistd.h>
+
+#define TEST_ASSERT(left, right, success_msg, fail_msg)                        \
+  do {                                                                         \
+    if ((left) == (right)) {                                                   \
+      printf("[PASS] %s\n", success_msg);                                      \
+    } else {                                                                   \
+      printf("[FAIL] %s: Expected %d, but got %d\n", fail_msg, (right),        \
+             (left));                                                          \
+    }                                                                          \
+  } while (0)
 
 #define FIFO_PATH "/bin/test_fifo" // 使用 /tmp 目录避免权限问题
 
+typedef struct {
+  int fd;
+  int error_code;
+} FifoWriteResult;
+
 // 信号处理函数
 void sigpipe_handler(int signo) {
-    if (signo == SIGPIPE) {
-        printf("Received SIGPIPE signal. Write operation failed.\n");
-    }
+  if (signo == SIGPIPE) {
+    printf("Received SIGPIPE signal. Write operation failed.\n");
+  }
 }
 
-void test_fifo_write(const char *scenario_desc, int nonblocking) {
-    int fd;
-    char *data = "Hello, FIFO!";
-    printf("\n--- Testing: %s (nonblocking=%d) ---\n", scenario_desc, nonblocking);
-
-    // 设置写模式和非阻塞模式标志
-    int flags = O_WRONLY;
-    if (nonblocking) {
-        flags |= O_NONBLOCK;
+const char *scenarios[] = {"No readers (FIFO never had readers)",
+                           "Reader exists but disconnects",
+                           "Active reader exists"};
+
+FifoWriteResult test_fifo_write(int scenario_index, int nonblocking) {
+  FifoWriteResult result = {.fd = -1, .error_code = 0};
+  int fd;
+  const char *data = "Hello, FIFO!";
+
+  // Set write mode and non-blocking flag
+  int flags = O_WRONLY;
+  if (nonblocking) {
+    flags |= O_NONBLOCK;
+  }
+
+  // Open the FIFO write end
+  fd = open(FIFO_PATH, flags);
+  if (fd == -1) {
+    result.fd = fd;
+    result.error_code = errno;
+
+    if (errno == ENXIO) {
+      printf("Result: Failed to open FIFO for writing (ENXIO: No readers).\n");
+    } else {
+      perror("Failed to open FIFO for writing");
     }
+    return result; // Return early with error details
+  }
 
-    // 打开 FIFO 写端
-    fd = open(FIFO_PATH, flags);
-    if (fd == -1) {
-        if (errno == ENXIO) {
-            printf("Result: Failed to open FIFO for writing (ENXIO: No readers).\n");
-        } else {
-            perror("Failed to open FIFO for writing");
-        }
-        return;
-    }
+  // Write data
+  ssize_t bytes_written = write(fd, data, strlen(data));
+  if (bytes_written == -1) {
+    result.error_code = errno;
 
-    // 写入数据
-    ssize_t bytes_written = write(fd, data, sizeof(data));
     if (bytes_written == -1) {
-        if (errno == EPIPE) {
-            printf("Result: Write failed with EPIPE (no readers available).\n");
-        } else if (errno == ENXIO) {
-            printf("Result: Write failed with ENXIO (FIFO never had readers).\n");
-        } else if (errno == EAGAIN) {
-            printf("Result: Write failed with EAGAIN (nonblocking write, pipe full or no readers).\n");
-        } else {
-            perror("Write failed with an unexpected error");
-        }
+      if (errno == EPIPE) {
+        printf("Result: Write failed with EPIPE (no readers available).\n");
+      } else if (errno == ENXIO) {
+        printf("Result: Write failed with ENXIO (FIFO never had readers).\n");
+      } else if (errno == EAGAIN) {
+        printf("Result: Write failed with EAGAIN (nonblocking write, pipe full "
+               "or no readers).\n");
+      } else {
+        perror("Write failed with an unexpected error");
+      }
     } else {
-        printf("Result: Write succeeded. Bytes written: %zd\n", bytes_written);
+      printf("Result: Write succeeded. Bytes written: %zd\n", bytes_written);
     }
 
-    // 关闭 FIFO 写端
+    result.fd = fd;
     close(fd);
+    return result; // Return with fd and error_code
+  }
 }
 
 void test_case1(int nonblocking) {
-    // Case 1: No readers (FIFO never had readers)
-    test_fifo_write("No readers (FIFO never had readers)", nonblocking);
+  // Case 1: No readers (FIFO never had readers)
+  FifoWriteResult result = test_fifo_write(0, nonblocking);
+
+  char buffer[100];
+  sprintf(buffer,"Fail with unexpected error %d",result.error_code);
+  TEST_ASSERT(result.error_code, ENXIO,
+              "write(2) fails with the error ENXIO",
+              buffer);
 }
 
 void test_case2(int nonblocking) {
-    pid_t reader_pid;
-
-    // Case 2: Reader exists but disconnects
-    reader_pid = fork();
-    if (reader_pid == 0) {
-        // 子进程充当读端
-        int reader_fd = open(FIFO_PATH, O_RDONLY);
-        if (reader_fd == -1) {
-            perror("Reader failed to open FIFO");
-            exit(EXIT_FAILURE);
-        }
-        sleep(1); // 模拟读端短暂存在
-        close(reader_fd);
-        exit(EXIT_SUCCESS);
+  pid_t reader_pid;
+
+  // Case 2: Reader exists but disconnects
+  reader_pid = fork();
+  if (reader_pid == 0) {
+    // Child process acts as a reader
+    int reader_fd = open(FIFO_PATH, O_RDONLY);
+    if (reader_fd == -1) {
+      perror("Reader failed to open FIFO");
+      exit(EXIT_FAILURE);
     }
-
-    sleep(5); // 确保读端已打开
-    test_fifo_write("Reader exists but disconnects", nonblocking);
-    waitpid(reader_pid, NULL, 0); // 等待读端子进程退出
+    sleep(1); // Simulate a brief existence of the reader
+    close(reader_fd);
+    exit(EXIT_SUCCESS);
+  }
+
+  sleep(5); // Ensure the reader has opened the FIFO
+  FifoWriteResult result = test_fifo_write(1, nonblocking);
+  waitpid(reader_pid, NULL, 0); // Wait for the reader process to exit
+
+  if (nonblocking) {
+    TEST_ASSERT(result.fd != -1 && result.error_code == EPIPE, 1, "Non-Blocking Write failed with EPIPE", "Non-Blocking Write failed with wrong error type");
+  } else {
+    TEST_ASSERT(result.fd != -1 && result.error_code == EPIPE, 1, "Blocking Write failed with EPIPE", "Blocking Write failed with wrong error type");
+  }
 }
 
 void test_case3(int nonblocking) {
-    pid_t reader_pid;
-
-    // Case 3: Active reader exists
-    reader_pid = fork();
-    if (reader_pid == 0) {
-        // 子进程充当读端
-        int reader_fd = open(FIFO_PATH, O_RDONLY);
-        if (reader_fd == -1) {
-            perror("Reader failed to open FIFO");
-            exit(EXIT_FAILURE);
-        }
-        sleep(5); // 保持读端存在
-        close(reader_fd);
-        exit(EXIT_SUCCESS);
+  pid_t reader_pid;
+
+  // Case 3: Active reader exists
+  reader_pid = fork();
+  if (reader_pid == 0) {
+    // Child process acts as a reader
+    int reader_fd = open(FIFO_PATH, O_RDONLY);
+    if (reader_fd == -1) {
+      perror("Reader failed to open FIFO");
+      exit(EXIT_FAILURE);
     }
+    sleep(5); // Keep the reader active
+    close(reader_fd);
+    exit(EXIT_SUCCESS);
+  }
+
+  sleep(1); // Ensure the reader has opened the FIFO
+  FifoWriteResult result = test_fifo_write(2, nonblocking);
 
-    sleep(1); // 确保读端已打开
-    test_fifo_write("Active reader exists", nonblocking);
-    waitpid(reader_pid, NULL, 0); // 等待读端子进程退出
+  waitpid(reader_pid, NULL, 0); // Wait for the reader process to exit
+
+  TEST_ASSERT(result.error_code, 0, "write succeed", "write failed");
+}
+
+void run_tests(int nonblocking) {
+  for (int i = 0; i < 3; i++) {
+    printf("\n--- Testing: %s (nonblocking=%d) ---\n", scenarios[i],
+           nonblocking);
+    switch (i) {
+    case 0:
+      test_case1(nonblocking);
+      break;
+    case 1:
+      test_case2(nonblocking);
+      break;
+    case 2:
+      test_case3(nonblocking);
+      break;
+    }
+  }
 }
 
 int main() {
-    // 设置 SIGPIPE 信号处理
-    signal(SIGPIPE, sigpipe_handler);
+  // 设置 SIGPIPE 信号处理
+  signal(SIGPIPE, sigpipe_handler);
 
-    // 创建 FIFO
-    if (mkfifo(FIFO_PATH, 0666) == -1 && errno != EEXIST) {
-        perror("mkfifo failed");
-        exit(EXIT_FAILURE);
-    }
+  // 创建 FIFO
+  if (mkfifo(FIFO_PATH, 0666) == -1 && errno != EEXIST) {
+    perror("mkfifo failed");
+    exit(EXIT_FAILURE);
+  }
 
-    // 测试阻塞模式下的三种情况
-    // printf("========== Testing Blocking Mode ==========\n");
-    // test_case1(0); // 阻塞模式下没有读端
-    // test_case2(0); // 阻塞模式下读端断开
-    // test_case3(0); // 阻塞模式下读端存在
+  // 测试阻塞模式下的三种情况
+//   printf("========== Testing Blocking Mode ==========\n");
+//   run_tests(0); // 阻塞模式
 
-    // 测试非阻塞模式下的三种情况
-    printf("\n========== Testing Nonblocking Mode ==========\n");
-    test_case1(1); // 非阻塞模式下没有读端
-    test_case2(1); // 非阻塞模式下读端断开
-    test_case3(1); // 非阻塞模式下读端存在
+  // 测试非阻塞模式下的三种情况
+  printf("\n========== Testing Nonblocking Mode ==========\n");
+  run_tests(1); // 非阻塞模式
 
-    // 删除 FIFO
-    unlink(FIFO_PATH);
+  // 删除 FIFO
+  unlink(FIFO_PATH);
 
-    printf("\nAll tests completed.\n");
-    return 0;
+  printf("\nAll tests completed.\n");
+  return 0;
 }