diff --git a/Makefile b/Makefile index 3566a30..d1a6990 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ HOOK_NAME = hook_write.so BUILD_DIR = build SRC_DIR = src +TESTS_DIR = tests SRC = $(wildcard $(SRC_DIR)/*.c) SRC := $(filter-out $(SRC_DIR)/hook_write.c, $(SRC)) # 排除 hook_write.c @@ -19,6 +20,11 @@ HOOK_SRC = $(SRC_DIR)/hook_write.c HOOK_OBJ = $(BUILD_DIR)/hook_write.o HOOK_TARGET = $(BUILD_DIR)/$(HOOK_NAME) +# 测试客户端 +TEST_CLIENT = $(BUILD_DIR)/test_client +TEST_CLIENT_SRC = $(TESTS_DIR)/test_client.c +TEST_CLIENT_DEPS = $(BUILD_DIR)/client.o $(BUILD_DIR)/debug.o + # 如果需要开启 debug,只需执行 make DEBUG=1 ifeq ($(DEBUG),1) CFLAGS += -DDEBUG -g @@ -34,10 +40,12 @@ ifeq ($(NO_CONFIG_CHECK),1) CFLAGS += -DNO_CONFIG_CHECK endif -.PHONY: all clean debug hook rebuild pre_build +.PHONY: all clean debug hook rebuild pre_build test_client all: pre_build $(TARGET) $(HOOK_TARGET) +test_client: pre_build $(TEST_CLIENT) + pre_build: ifeq ($(DEBUG),1) @echo "Building with debug flags..." @@ -65,6 +73,10 @@ $(HOOK_OBJ): $(HOOK_SRC) @mkdir -p $(BUILD_DIR) $(CC) $(CFLAGS) -Wno-error=unused-result -c $< -o $@ +$(TEST_CLIENT): $(TEST_CLIENT_SRC) $(TEST_CLIENT_DEPS) + @mkdir -p $(BUILD_DIR) + $(CC) -Wall -Wextra -o $@ $(TEST_CLIENT_SRC) $(TEST_CLIENT_DEPS) + clean: rm -rf $(BUILD_DIR) diff --git a/src/client.h b/src/client.h index 61c7e9a..be6cab8 100644 --- a/src/client.h +++ b/src/client.h @@ -12,7 +12,7 @@ #include // for PATH_MAX #include -#define SOCKET_PATH "/etc/exec_hook/exec.sock" +#define SOCKET_PATH "/var/run/bash-smart.sock" #define MAX_BUF_SIZE 4096 // 函数声明 diff --git a/test_log.stderr.log b/test_log.stderr.log new file mode 100644 index 0000000..8c1f6a2 --- /dev/null +++ b/test_log.stderr.log @@ -0,0 +1,6 @@ +pip is not installed. Please install pip to proceed. +Installing required Python packages... +Successfully installed click-8.1.3 +Finished installing Python packages. + +This is a test error log file for testing the client functionality. \ No newline at end of file diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..d3604ac --- /dev/null +++ b/tests/README.md @@ -0,0 +1,43 @@ +# 客户端测试程序 + +## 编译 + +```bash +make test_client +``` + +## 运行测试 + +确保 Go 服务端正在运行,然后执行: + +```bash +./build/test_client /tmp/test_error.log +``` + +## 测试说明 + +测试程序会: +1. 连接到 Unix socket (`/etc/exec_hook/exec.sock`) +2. 发送模拟的执行参数(命令、参数、环境变量、日志路径) +3. 接收并显示服务端返回的所有消息 +4. 等待 socket 关闭后退出 + +## 创建测试日志文件 + +如果需要自定义测试日志内容: + +```bash +cat > /tmp/test_error.log << 'EOF' +This is a test error log file. + +Error: command not found +Usage: test_script.py [OPTIONS] + +Exit code: 127 +EOF +``` + +## 预期行为 + +- 成功情况: 显示服务端返回的所有消息,最后输出 "✓ 测试成功" +- 失败情况: 输出错误信息,返回非零退出码 diff --git a/tests/a.out b/tests/a.out deleted file mode 100755 index 487d2ab..0000000 Binary files a/tests/a.out and /dev/null differ diff --git a/tests/forkpty b/tests/forkpty deleted file mode 100755 index 59c504b..0000000 Binary files a/tests/forkpty and /dev/null differ diff --git a/tests/makefault b/tests/makefault deleted file mode 100755 index 72d0e26..0000000 Binary files a/tests/makefault and /dev/null differ diff --git a/tests/socket-client/Makefile b/tests/socket-client/Makefile deleted file mode 100644 index 23a52d0..0000000 --- a/tests/socket-client/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -CC = gcc -CFLAGS = -Wall -g - -all: client-tests - -client-tests: client-tests.o client.o - $(CC) $(CFLAGS) -o client-tests client-tests.o client.o - -client-tests.o: client-tests.c client.h - $(CC) $(CFLAGS) -c client-tests.c - -client.o: client.c client.h - $(CC) $(CFLAGS) -c client.c - -clean: - rm -f client-tests *.o - -.PHONY: all clean diff --git a/tests/socket-client/client-tests b/tests/socket-client/client-tests deleted file mode 100755 index ad07782..0000000 Binary files a/tests/socket-client/client-tests and /dev/null differ diff --git a/tests/socket-client/client-tests.c b/tests/socket-client/client-tests.c deleted file mode 100644 index 808c800..0000000 --- a/tests/socket-client/client-tests.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "client.h" - -int main() { - // 测试参数 - const char *filename = "/usr/bin/ls"; - char *const argv[] = { - "ls", - "-l", - "/home", - NULL - }; - - char *const envp[] = { - "PATH=/usr/local/bin:/usr/bin:/bin", - "HOME=/home/user", - "LANG=en_US.UTF-8", - NULL - }; - - // 调用socket发送函数 - int result = send_exec_params(filename, argv, envp, "./test.log"); - - if(result == 0) { - printf("Parameters sent successfully\n"); - } else { - printf("Failed to send parameters\n"); - } - - return 0; -} \ No newline at end of file diff --git a/tests/socket-client/client-tests.o b/tests/socket-client/client-tests.o deleted file mode 100644 index 479ec47..0000000 Binary files a/tests/socket-client/client-tests.o and /dev/null differ diff --git a/tests/socket-client/client.c b/tests/socket-client/client.c deleted file mode 100644 index 179cd7b..0000000 --- a/tests/socket-client/client.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "client.h" -#include -#include -#include -#include -#include -#include -#include - -#define BUFFER_SIZE 4096 - -// 读取完整消息 -ssize_t readMessage(int sock, char *buffer, size_t maxSize) { - uint32_t messageLen; - // 先读取消息长度 - if (read(sock, &messageLen, sizeof(messageLen)) != sizeof(messageLen)) { - return -1; - } - - // 检查buffer大小是否足够 - if (messageLen >= maxSize) { - return -1; - } - - // 读取完整消息 - size_t totalRead = 0; - while (totalRead < messageLen) { - ssize_t n = read(sock, buffer + totalRead, messageLen - totalRead); - if (n <= 0) return -1; - totalRead += n; - } - buffer[messageLen] = '\0'; - return messageLen; -} - -int send_exec_params(const char *filename, char *const argv[], - char *const envp[], const char *logPath) { - char abs_path[PATH_MAX]; - char pwd[PATH_MAX]; - - // 获取当前工作目录 - if (getcwd(pwd, sizeof(pwd)) == NULL) { - perror("getcwd"); - return -1; - } - - if (logPath[0] != '/') { // 相对路径 - size_t pwd_len = strlen(pwd); - size_t log_len = strlen(logPath); - if (pwd_len + log_len + 2 > PATH_MAX) { - errno = ENAMETOOLONG; - perror("path too long"); - return -1; - } - - strncpy(abs_path, pwd, PATH_MAX - 1); - abs_path[PATH_MAX - 1] = '\0'; - strncat(abs_path, "/", PATH_MAX - strlen(abs_path) - 1); - strncat(abs_path, logPath, PATH_MAX - strlen(abs_path) - 1); - - char real_path[PATH_MAX]; - if (realpath(abs_path, real_path) == NULL) { - perror("realpath"); - return -1; - } - strncpy(abs_path, real_path, PATH_MAX - 1); - abs_path[PATH_MAX - 1] = '\0'; - } else { - strncpy(abs_path, logPath, PATH_MAX - 1); - abs_path[PATH_MAX - 1] = '\0'; - } - - size_t path_len = strlen(abs_path); - - int sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock == -1) { - perror("socket"); - return -1; - } - - // 设置TCP_NODELAY - // int flag = 1; - // setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)); - - struct sockaddr_un addr; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1); - addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; - - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - perror("connect"); - close(sock); - return -1; - } - - // 发送文件名 - size_t filename_len = strlen(filename); - write(sock, &filename_len, sizeof(size_t)); - write(sock, filename, filename_len); - - // 发送当前工作目录 - size_t pwd_len = strlen(pwd); - write(sock, &pwd_len, sizeof(size_t)); - write(sock, pwd, pwd_len); - - // 发送argv - int argc = 0; - while (argv[argc] != NULL) argc++; - write(sock, &argc, sizeof(int)); - - for (int i = 0; i < argc; i++) { - size_t arg_len = strlen(argv[i]); - write(sock, &arg_len, sizeof(size_t)); - write(sock, argv[i], arg_len); - } - - // 发送envp - int envc = 0; - while (envp[envc] != NULL) envc++; - write(sock, &envc, sizeof(int)); - - for (int i = 0; i < envc; i++) { - size_t env_len = strlen(envp[i]); - write(sock, &env_len, sizeof(size_t)); - write(sock, envp[i], env_len); - } - - // 发送logPath - write(sock, &path_len, sizeof(size_t)); - write(sock, abs_path, path_len); - - // 接收服务器响应 - char buffer[BUFFER_SIZE]; - char display_buffer[BUFFER_SIZE]; - ssize_t bytes_read; - int started = 0; - - // 等待接收[sthttp]标记 - while (!started) { - bytes_read = readMessage(sock, buffer, BUFFER_SIZE); - if (bytes_read <= 0) { - perror("Failed to read start marker"); - close(sock); - return -1; - } - - if (strstr(buffer, "[sthttp]")) { - started = 1; - } - } - - // 持续读取消息直到收到[end] - while (1) { - bytes_read = readMessage(sock, buffer, BUFFER_SIZE); - if (bytes_read <= 0) { - break; - } - - if (strstr(buffer, "[end]")) { - break; - } - - // 处理[res]...[wait]消息 - char *res_start = strstr(buffer, "[res]"); - char *wait_end = strstr(buffer, "[wait]"); - - if (res_start && wait_end) { - size_t content_len = wait_end - (res_start + strlen("[res]")); - if (content_len < BUFFER_SIZE) { - strncpy(display_buffer, res_start + strlen("[res]"), content_len); - display_buffer[content_len] = '\0'; - printf("%s\n", display_buffer); - fflush(stdout); - } - } - } - - close(sock); - return 0; -} diff --git a/tests/socket-client/client.h b/tests/socket-client/client.h deleted file mode 100644 index 61c7e9a..0000000 --- a/tests/socket-client/client.h +++ /dev/null @@ -1,21 +0,0 @@ -// exec_socket.h - -#ifndef EXEC_SOCKET_H -#define EXEC_SOCKET_H - -#include -#include -#include -#include -#include -#include -#include // for PATH_MAX -#include - -#define SOCKET_PATH "/etc/exec_hook/exec.sock" -#define MAX_BUF_SIZE 4096 - -// 函数声明 -int send_exec_params(const char *filename, char *const argv[], char *const envp[], const char *logPath); - -#endif // EXEC_SOCKET_H diff --git a/tests/socket-client/client.o b/tests/socket-client/client.o deleted file mode 100644 index da99897..0000000 Binary files a/tests/socket-client/client.o and /dev/null differ diff --git a/tests/socket-client/test.log b/tests/socket-client/test.log deleted file mode 100644 index 803d89e..0000000 --- a/tests/socket-client/test.log +++ /dev/null @@ -1 +0,0 @@ -我是一段标准错误输出 \ No newline at end of file diff --git a/tests/test_client.c b/tests/test_client.c new file mode 100644 index 0000000..a0cc64e --- /dev/null +++ b/tests/test_client.c @@ -0,0 +1,69 @@ +#include "../src/client.h" +#include +#include +#include + +/** + * 测试客户端 - 用于测试 send_exec_params 函数 + * + * 用法: + * ./test_client + * + * 示例: + * ./test_client /tmp/test_error.log + */ + +int main(int argc, char *argv[]) { + if (argc < 2) { + fprintf(stderr, "用法: %s \n", argv[0]); + fprintf(stderr, "示例: %s /tmp/test_error.log\n", argv[0]); + return 1; + } + + const char *log_path = argv[1]; + + // 模拟要执行的命令 + const char *filename = "/usr/bin/python3"; + + // 模拟命令行参数 + char *test_argv[] = { + "python3", + "test_script.py", + "--arg1", + "value1", + NULL + }; + + // 模拟环境变量 + char *test_envp[] = { + "PATH=/usr/bin:/bin", + "HOME=/home/test", + "USER=test", + "SHELL=/bin/bash", + NULL + }; + + printf("===== 客户端测试开始 =====\n"); + printf("socket地址:%s\n", SOCKET_PATH); + printf("文件名: %s\n", filename); + printf("日志路径: %s\n", log_path); + printf("参数:\n"); + for (int i = 0; test_argv[i] != NULL; i++) { + printf(" argv[%d]: %s\n", i, test_argv[i]); + } + printf("\n正在发送请求到服务端...\n\n"); + printf("--- 服务端响应 ---\n"); + + // 调用客户端函数 + int result = send_exec_params(filename, test_argv, test_envp, log_path); + + printf("\n--- 响应结束 ---\n"); + + if (result == 0) { + printf("\n✓ 测试成功\n"); + return 0; + } else { + fprintf(stderr, "\n✗ 测试失败: send_exec_params 返回 %d\n", result); + return 1; + } +}