From e7a5676a6414cffd1c1a3a6a6b2d19099f7d6cc3 Mon Sep 17 00:00:00 2001 From: kenzok8 Date: Thu, 11 Sep 2025 16:29:28 +0800 Subject: [PATCH] update 2025-09-11 16:29:28 --- UA2F/CMakeLists.txt | 22 +++++++++++++++++++++- UA2F/scripts/test.py | 39 ++++++++++++++++++++++++++++++++++----- UA2F/src/ua2f.c | 15 +++++++++++++-- 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/UA2F/CMakeLists.txt b/UA2F/CMakeLists.txt index df6f891b6..2cfa3b633 100644 --- a/UA2F/CMakeLists.txt +++ b/UA2F/CMakeLists.txt @@ -231,6 +231,18 @@ if (UA2F_BUILD_TESTS) DEPENDS ua2f_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) + + # Add lcov target for preprocessed coverage data + add_custom_target(coverage-lcov + COMMAND echo "Running unit tests and generating lcov report" + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/ua2f_test + COMMAND lcov --capture --directory . --output-file coverage.info --ignore-errors mismatch --branch-coverage + COMMAND lcov --remove coverage.info '*/test/*' '*/build*/_deps/*' '/usr/*' '*/googletest/*' '*_deps/*' --output-file coverage.info --ignore-errors unused --branch-coverage + COMMAND lcov --list coverage.info --branch-coverage + COMMENT "Generating lcov coverage report" + DEPENDS ua2f_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) endif() include(GoogleTest) @@ -241,12 +253,20 @@ endif () # Coverage targets for integration testing (independent of unit tests) if (UA2F_ENABLE_COVERAGE) - add_custom_target(coverage-integration + add_custom_target(coverage-integration-reset COMMAND find . -name "*.gcda" -delete COMMENT "Reset coverage counters for integration tests" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) + add_custom_target(coverage-integration-process + COMMAND lcov --capture --directory . --output-file coverage-integration.info --ignore-errors mismatch --branch-coverage + COMMAND lcov --remove coverage-integration.info '*/test/*' '*/build*/_deps/*' '/usr/*' '*/googletest/*' '*_deps/*' --output-file coverage-integration.info --ignore-errors unused --branch-coverage + COMMAND lcov --list coverage-integration.info --branch-coverage + COMMENT "Process integration test coverage data with lcov" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + add_custom_target(coverage-clean COMMAND find . -name "*.gcda" -delete WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} diff --git a/UA2F/scripts/test.py b/UA2F/scripts/test.py index d5b7b1d58..f0d3c7858 100644 --- a/UA2F/scripts/test.py +++ b/UA2F/scripts/test.py @@ -48,8 +48,29 @@ def start_server(): t6.start() def start_ua2f(u: str): - p = subprocess.Popen([u]) - atexit.register(lambda: p.kill()) + env = os.environ.copy() + + ua2f_abs_path = os.path.abspath(u) + build_dir = os.path.dirname(ua2f_abs_path) + + print(f"Starting UA2F from build directory: {build_dir}") + original_cwd = os.getcwd() + os.chdir(build_dir) + + binary_name = os.path.basename(ua2f_abs_path) + p = subprocess.Popen([f'./{binary_name}'], env=env, cwd=build_dir) + + os.chdir(original_cwd) + + def graceful_shutdown(): + try: + p.terminate() + p.wait(timeout=5) + except subprocess.TimeoutExpired: + p.kill() + + atexit.register(graceful_shutdown) + return p def setup_iptables(): @@ -75,9 +96,7 @@ if __name__ == "__main__": start_server() - ua2f_thread = threading.Thread(target=start_ua2f, args=(ua2f,)) - ua2f_thread.daemon = True - ua2f_thread.start() + ua2f_process = start_ua2f(ua2f) print(f"Starting UA2F: {ua2f}") @@ -99,5 +118,15 @@ if __name__ == "__main__": assert response.ok assert response.text == str(len(nxt)) + print("Tests completed, shutting down UA2F gracefully...") + + try: + ua2f_process.terminate() + ua2f_process.wait(timeout=5) + print("UA2F terminated gracefully") + except subprocess.TimeoutExpired: + print("UA2F didn't respond to SIGTERM, force killing...") + ua2f_process.kill() + # clean cleanup_iptables() diff --git a/UA2F/src/ua2f.c b/UA2F/src/ua2f.c index 047714b21..cbc66c616 100644 --- a/UA2F/src/ua2f.c +++ b/UA2F/src/ua2f.c @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -20,6 +19,11 @@ volatile int should_exit = false; +void signal_handler(int sig) { + syslog(LOG_INFO, "Received signal %d, preparing to exit...", sig); + should_exit = true; +} + int parse_packet(const struct nf_queue *queue, struct nf_buffer *buf) { struct nf_packet packet[1] = {0}; @@ -36,7 +40,8 @@ int parse_packet(const struct nf_queue *queue, struct nf_buffer *buf) { } int read_buffer(struct nf_queue *queue, struct nf_buffer *buf) { - const __auto_type buf_status = nfqueue_receive(queue, buf, 0); + // Use timeout to allow periodic checking of should_exit flag during signal handling + const __auto_type buf_status = nfqueue_receive(queue, buf, 1000); if (buf_status == IO_READY) { return parse_packet(queue, buf); } @@ -79,6 +84,10 @@ void main_loop(struct nf_queue *queue) { int main(const int argc, char *argv[]) { openlog("UA2F", LOG_PID, LOG_SYSLOG); + // Register signal handlers for graceful shutdown + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + #ifdef UA2F_ENABLE_UCI load_config(); #else @@ -108,6 +117,8 @@ int main(const int argc, char *argv[]) { nfqueue_close(queue); + syslog(LOG_INFO, "UA2F exiting gracefully"); + return EXIT_SUCCESS; }