From 547266ed1b067523b837cb08e647f9c301a5789c Mon Sep 17 00:00:00 2001 From: veqcc Date: Thu, 27 Feb 2025 18:10:06 +0900 Subject: [PATCH] feat(kmod): unit test for AGNOCAST_NEW_SHM_CMD Signed-off-by: veqcc --- kmod/agnocast.c | 36 +++++++- kmod/agnocast.h | 6 ++ kmod/agnocast_kunit/agnocast_kunit_new_shm.c | 90 ++++++++++++++++++-- kmod/agnocast_kunit/agnocast_kunit_new_shm.h | 11 ++- 4 files changed, 130 insertions(+), 13 deletions(-) diff --git a/kmod/agnocast.c b/kmod/agnocast.c index 19e0550d..b795b062 100644 --- a/kmod/agnocast.c +++ b/kmod/agnocast.c @@ -1590,6 +1590,39 @@ static long agnocast_ioctl(struct file * file, unsigned int cmd, unsigned long a return -EFAULT; } +// ========================================= +// helper functions for KUnit test + +#ifdef KUNIT_BUILD +int get_proc_info_htable_size(void) +{ + int count = 0; + struct process_info * proc_info; + int bkt_proc_info; + hash_for_each(proc_info_htable, bkt_proc_info, proc_info, node) + { + count++; + } + return count; +} + +bool is_in_proc_info_htable(const pid_t pid) +{ + struct process_info * proc_info; + int bkt_proc_info; + hash_for_each(proc_info_htable, bkt_proc_info, proc_info, node) + { + if (proc_info->pid == pid) { + return true; + } + } + return false; +} +#endif + +// ========================================= +// Initialize and cleanup + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0) static char * agnocast_devnode(const struct device * dev, umode_t * mode) #else @@ -1692,9 +1725,6 @@ static void pre_handler_publisher_exit(struct topic_wrapper * wrapper, const pid } } -// ========================================= -// Cleanup resources related to exited processes - // Ring buffer to hold exited pids #define EXIT_QUEUE_SIZE_BITS 10 // arbitrary size #define EXIT_QUEUE_SIZE (1U << EXIT_QUEUE_SIZE_BITS) diff --git a/kmod/agnocast.h b/kmod/agnocast.h index a4d9c743..d952a4c4 100644 --- a/kmod/agnocast.h +++ b/kmod/agnocast.h @@ -201,3 +201,9 @@ int get_subscriber_num(char * topic_name, union ioctl_get_subscriber_num_args * int get_topic_list(union ioctl_topic_list_args * topic_list_args); void process_exit_cleanup(const pid_t pid); + +// ================================================ +// helper functions for KUnit test + +int get_proc_info_htable_size(void); +bool is_in_proc_info_htable(const pid_t pid); diff --git a/kmod/agnocast_kunit/agnocast_kunit_new_shm.c b/kmod/agnocast_kunit/agnocast_kunit_new_shm.c index 640b9a55..7f556966 100644 --- a/kmod/agnocast_kunit/agnocast_kunit_new_shm.c +++ b/kmod/agnocast_kunit/agnocast_kunit_new_shm.c @@ -4,14 +4,92 @@ #include -// Feel free to delete this test case -void test_case_new_shm_sample0(struct kunit * test) +static pid_t pid = 1000; + +static uint64_t get_previously_allocated_shm_addr(struct kunit * test) +{ + uint64_t local_pid = pid++; + union ioctl_new_shm_args new_shm_args; + int ret = new_shm_addr(local_pid, PAGE_SIZE, &new_shm_args); + KUNIT_ASSERT_EQ(test, ret, 0); + process_exit_cleanup(local_pid); + return new_shm_args.ret_addr; +} + +void test_case_new_shm_normal(struct kunit * test) { - KUNIT_EXPECT_EQ(test, 1 + 1, 2); + uint64_t previously_allocated_shm_addr = get_previously_allocated_shm_addr(test); + KUNIT_ASSERT_EQ(test, get_proc_info_htable_size(), 0); + + uint64_t local_pid = pid++; + union ioctl_new_shm_args args; + int ret = new_shm_addr(local_pid, PAGE_SIZE, &args); + + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, args.ret_addr, previously_allocated_shm_addr + PAGE_SIZE); + KUNIT_EXPECT_TRUE(test, is_in_proc_info_htable(local_pid)); + KUNIT_EXPECT_EQ(test, get_proc_info_htable_size(), 1); + + process_exit_cleanup(local_pid); } -// Feel free to delete this test case -void test_case_new_shm_sample1(struct kunit * test) +void test_case_new_shm_many(struct kunit * test) { - KUNIT_EXPECT_EQ(test, 1 * 1, 1); + const int process_num = 1000; + uint64_t previously_allocated_shm_addr = get_previously_allocated_shm_addr(test); + KUNIT_ASSERT_EQ(test, get_proc_info_htable_size(), 0); + + // ================================================ + // Act + + pid_t local_pid_start = pid; + for (int i = 0; i < process_num - 1; i++) { + uint64_t local_pid = pid++; + union ioctl_new_shm_args args; + new_shm_addr(local_pid, PAGE_SIZE, &args); + } + + uint64_t local_pid = pid++; + union ioctl_new_shm_args args; + int ret = new_shm_addr(local_pid, PAGE_SIZE, &args); + + // ================================================ + // Assert + + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, args.ret_addr, previously_allocated_shm_addr + PAGE_SIZE * process_num); + KUNIT_EXPECT_EQ(test, get_proc_info_htable_size(), process_num); + for (int i = 0; i < process_num; i++) { + KUNIT_EXPECT_TRUE(test, is_in_proc_info_htable(local_pid_start + i)); + } + + for (int i = 0; i < process_num; i++) { + process_exit_cleanup(local_pid_start + i); + } +} + +void test_case_new_shm_not_aligned(struct kunit * test) +{ + uint64_t local_pid = pid++; + union ioctl_new_shm_args args; + int ret = new_shm_addr(local_pid, PAGE_SIZE + 1, &args); + + KUNIT_EXPECT_EQ(test, ret, -EINVAL); +} + +void test_case_new_shm_twice(struct kunit * test) +{ + KUNIT_ASSERT_EQ(test, get_proc_info_htable_size(), 0); + + pid_t local_pid = pid++; + union ioctl_new_shm_args args; + int ret1 = new_shm_addr(local_pid, PAGE_SIZE, &args); + int ret2 = new_shm_addr(local_pid, PAGE_SIZE, &args); + + KUNIT_EXPECT_EQ(test, ret1, 0); + KUNIT_EXPECT_EQ(test, ret2, -EINVAL); + KUNIT_EXPECT_EQ(test, is_in_proc_info_htable(local_pid), true); + KUNIT_EXPECT_EQ(test, get_proc_info_htable_size(), 1); + + process_exit_cleanup(local_pid); } diff --git a/kmod/agnocast_kunit/agnocast_kunit_new_shm.h b/kmod/agnocast_kunit/agnocast_kunit_new_shm.h index f75b65fc..c604569d 100644 --- a/kmod/agnocast_kunit/agnocast_kunit_new_shm.h +++ b/kmod/agnocast_kunit/agnocast_kunit_new_shm.h @@ -1,8 +1,11 @@ #pragma once #include -#define TEST_CASES_NEW_SHM \ - KUNIT_CASE(test_case_new_shm_sample0), KUNIT_CASE(test_case_new_shm_sample1) +#define TEST_CASES_NEW_SHM \ + KUNIT_CASE(test_case_new_shm_normal), KUNIT_CASE(test_case_new_shm_many), \ + KUNIT_CASE(test_case_new_shm_not_aligned), KUNIT_CASE(test_case_new_shm_twice) -void test_case_new_shm_sample0(struct kunit * test); -void test_case_new_shm_sample1(struct kunit * test); +void test_case_new_shm_normal(struct kunit * test); +void test_case_new_shm_many(struct kunit * test); +void test_case_new_shm_not_aligned(struct kunit * test); +void test_case_new_shm_twice(struct kunit * test);