|
4 | 4 | #include <stdlib.h> |
5 | 5 | #include <string.h> |
6 | 6 |
|
7 | | -void setUp(void) {} |
8 | | -void tearDown(void) {} |
| 7 | +// Memory tracking for hook tests |
| 8 | +static size_t custom_malloc_count = 0; |
| 9 | +static size_t custom_free_count = 0; |
| 10 | +static size_t custom_strdup_count = 0; |
| 11 | + |
| 12 | +// Custom memory functions for testing hooks |
| 13 | +static void* test_malloc(size_t size) |
| 14 | +{ |
| 15 | + custom_malloc_count++; |
| 16 | + return malloc(size); |
| 17 | +} |
| 18 | + |
| 19 | +static void test_free(void* ptr) |
| 20 | +{ |
| 21 | + if (ptr != NULL) { |
| 22 | + custom_free_count++; |
| 23 | + } |
| 24 | + free(ptr); |
| 25 | +} |
| 26 | + |
| 27 | +static char* test_strdup(const char* str) |
| 28 | +{ |
| 29 | + if (str == NULL) { |
| 30 | + return NULL; |
| 31 | + } |
| 32 | + custom_strdup_count++; |
| 33 | + size_t len = strlen(str) + 1; |
| 34 | + char* dup = test_malloc(len); |
| 35 | + if (dup != NULL) { |
| 36 | + memcpy(dup, str, len); |
| 37 | + } |
| 38 | + return dup; |
| 39 | +} |
| 40 | + |
| 41 | +void setUp(void) { |
| 42 | + // Reset memory counters before each test |
| 43 | + custom_malloc_count = 0; |
| 44 | + custom_free_count = 0; |
| 45 | + custom_strdup_count = 0; |
| 46 | + // Reset to default memory functions |
| 47 | + mjrpc_set_memory_hooks(NULL, NULL, NULL); |
| 48 | +} |
| 49 | + |
| 50 | +void tearDown(void) { |
| 51 | + // Ensure we reset to default memory functions after each test |
| 52 | + mjrpc_set_memory_hooks(NULL, NULL, NULL); |
| 53 | +} |
9 | 54 |
|
10 | 55 | // 用于测试自动扩容的空方法 |
11 | 56 | static cJSON* dummy_func(mjrpc_func_ctx_t* ctx, cJSON* params, cJSON* id) |
12 | 57 | { |
13 | 58 | return cJSON_CreateString("ok"); |
14 | 59 | } |
15 | 60 |
|
| 61 | +// 用于测试内存hooks的方法 |
| 62 | +static cJSON* memory_test_func(mjrpc_func_ctx_t* ctx, cJSON* params, cJSON* id) |
| 63 | +{ |
| 64 | + (void)ctx; |
| 65 | + (void)id; |
| 66 | + |
| 67 | + // 创建一个包含字符串的响应,这会触发内存分配 |
| 68 | + cJSON* result = cJSON_CreateObject(); |
| 69 | + cJSON_AddStringToObject(result, "message", "memory test successful"); |
| 70 | + cJSON_AddNumberToObject(result, "malloc_count", custom_malloc_count); |
| 71 | + cJSON_AddNumberToObject(result, "free_count", custom_free_count); |
| 72 | + cJSON_AddNumberToObject(result, "strdup_count", custom_strdup_count); |
| 73 | + |
| 74 | + return result; |
| 75 | +} |
| 76 | + |
16 | 77 | void test_auto_resize(void) |
17 | 78 | { |
18 | 79 | size_t initial_capacity = 4; |
@@ -43,9 +104,141 @@ void test_auto_resize(void) |
43 | 104 | mjrpc_destroy_handle(h); |
44 | 105 | } |
45 | 106 |
|
| 107 | +void test_memory_hooks_set_and_reset(void) |
| 108 | +{ |
| 109 | + // 测试设置自定义内存hooks |
| 110 | + int ret = mjrpc_set_memory_hooks(test_malloc, test_free, test_strdup); |
| 111 | + TEST_ASSERT_EQUAL_INT(MJRPC_RET_OK, ret); |
| 112 | + |
| 113 | + // 测试重置为默认内存函数 |
| 114 | + ret = mjrpc_set_memory_hooks(NULL, NULL, NULL); |
| 115 | + TEST_ASSERT_EQUAL_INT(MJRPC_RET_OK, ret); |
| 116 | +} |
| 117 | + |
| 118 | +void test_memory_hooks_invalid_params(void) |
| 119 | +{ |
| 120 | + // 测试无效参数组合 - 只设置部分函数应该失败 |
| 121 | + int ret = mjrpc_set_memory_hooks(test_malloc, NULL, NULL); |
| 122 | + TEST_ASSERT_NOT_EQUAL(MJRPC_RET_OK, ret); |
| 123 | + |
| 124 | + ret = mjrpc_set_memory_hooks(NULL, test_free, NULL); |
| 125 | + TEST_ASSERT_NOT_EQUAL(MJRPC_RET_OK, ret); |
| 126 | + |
| 127 | + ret = mjrpc_set_memory_hooks(NULL, NULL, test_strdup); |
| 128 | + TEST_ASSERT_NOT_EQUAL(MJRPC_RET_OK, ret); |
| 129 | + |
| 130 | + ret = mjrpc_set_memory_hooks(test_malloc, test_free, NULL); |
| 131 | + TEST_ASSERT_NOT_EQUAL(MJRPC_RET_OK, ret); |
| 132 | +} |
| 133 | + |
| 134 | +void test_memory_hooks_functionality(void) |
| 135 | +{ |
| 136 | + // 设置自定义内存hooks |
| 137 | + int ret = mjrpc_set_memory_hooks(test_malloc, test_free, test_strdup); |
| 138 | + TEST_ASSERT_EQUAL_INT(MJRPC_RET_OK, ret); |
| 139 | + |
| 140 | + // 创建handle - 这应该会触发内存分配 |
| 141 | + size_t malloc_before = custom_malloc_count; |
| 142 | + size_t strdup_before = custom_strdup_count; |
| 143 | + |
| 144 | + mjrpc_handle_t* h = mjrpc_create_handle(4); |
| 145 | + TEST_ASSERT_NOT_NULL(h); |
| 146 | + |
| 147 | + // 验证创建handle时使用了自定义内存函数 |
| 148 | + TEST_ASSERT_GREATER_THAN(malloc_before, custom_malloc_count); |
| 149 | + |
| 150 | + // 添加方法 - 这应该会触发strdup |
| 151 | + ret = mjrpc_add_method(h, memory_test_func, "memory_test", NULL); |
| 152 | + TEST_ASSERT_EQUAL_INT(MJRPC_RET_OK, ret); |
| 153 | + TEST_ASSERT_GREATER_THAN(strdup_before, custom_strdup_count); |
| 154 | + |
| 155 | + // 处理请求 - 验证hooks正常工作 |
| 156 | + cJSON* id = cJSON_CreateNumber(1); |
| 157 | + cJSON* req = mjrpc_request_cjson("memory_test", NULL, id); |
| 158 | + TEST_ASSERT_NOT_NULL(req); |
| 159 | + |
| 160 | + int code = -1; |
| 161 | + cJSON* resp = mjrpc_process_cjson(h, req, &code); |
| 162 | + TEST_ASSERT_NOT_NULL(resp); |
| 163 | + TEST_ASSERT_EQUAL_INT(MJRPC_RET_OK, code); |
| 164 | + |
| 165 | + // 验证响应内容 |
| 166 | + cJSON* result = cJSON_GetObjectItem(resp, "result"); |
| 167 | + TEST_ASSERT_NOT_NULL(result); |
| 168 | + TEST_ASSERT_TRUE(cJSON_IsObject(result)); |
| 169 | + |
| 170 | + cJSON* message = cJSON_GetObjectItem(result, "message"); |
| 171 | + TEST_ASSERT_TRUE(cJSON_IsString(message)); |
| 172 | + TEST_ASSERT_EQUAL_STRING("memory test successful", message->valuestring); |
| 173 | + |
| 174 | + cJSON_Delete(resp); |
| 175 | + |
| 176 | + // 记录销毁前的free计数 |
| 177 | + size_t free_before = custom_free_count; |
| 178 | + |
| 179 | + // 销毁handle - 这应该会触发内存释放 |
| 180 | + mjrpc_destroy_handle(h); |
| 181 | + |
| 182 | + // 验证销毁时使用了自定义free函数 |
| 183 | + TEST_ASSERT_GREATER_THAN(free_before, custom_free_count); |
| 184 | +} |
| 185 | + |
| 186 | +void test_memory_hooks_multiple_operations(void) |
| 187 | +{ |
| 188 | + // 设置自定义内存hooks |
| 189 | + int ret = mjrpc_set_memory_hooks(test_malloc, test_free, test_strdup); |
| 190 | + TEST_ASSERT_EQUAL_INT(MJRPC_RET_OK, ret); |
| 191 | + |
| 192 | + // 重置计数器 |
| 193 | + custom_malloc_count = 0; |
| 194 | + custom_free_count = 0; |
| 195 | + custom_strdup_count = 0; |
| 196 | + |
| 197 | + mjrpc_handle_t* h = mjrpc_create_handle(2); |
| 198 | + TEST_ASSERT_NOT_NULL(h); |
| 199 | + |
| 200 | + // 记录添加方法前的strdup计数 |
| 201 | + size_t strdup_before = custom_strdup_count; |
| 202 | + |
| 203 | + // 添加多个方法来测试strdup的使用 |
| 204 | + char method_names[3][20] = {"test1", "test2", "test3"}; |
| 205 | + for (int i = 0; i < 3; i++) { |
| 206 | + ret = mjrpc_add_method(h, dummy_func, method_names[i], NULL); |
| 207 | + TEST_ASSERT_EQUAL_INT(MJRPC_RET_OK, ret); |
| 208 | + } |
| 209 | + |
| 210 | + // 验证至少有3次strdup调用(可能因为内部实现有额外的strdup调用) |
| 211 | + TEST_ASSERT_GREATER_OR_EQUAL_size_t(3, custom_strdup_count - strdup_before); |
| 212 | + |
| 213 | + // 处理多个请求 |
| 214 | + for (int i = 0; i < 3; i++) { |
| 215 | + cJSON* id = cJSON_CreateNumber(i); |
| 216 | + cJSON* req = mjrpc_request_cjson(method_names[i], NULL, id); |
| 217 | + |
| 218 | + int code = -1; |
| 219 | + cJSON* resp = mjrpc_process_cjson(h, req, &code); |
| 220 | + TEST_ASSERT_NOT_NULL(resp); |
| 221 | + TEST_ASSERT_EQUAL_INT(MJRPC_RET_OK, code); |
| 222 | + |
| 223 | + cJSON_Delete(resp); |
| 224 | + } |
| 225 | + |
| 226 | + // 验证malloc和free被调用 |
| 227 | + TEST_ASSERT_GREATER_THAN_size_t(0, custom_malloc_count); |
| 228 | + |
| 229 | + mjrpc_destroy_handle(h); |
| 230 | + |
| 231 | + // 验证free被调用用于清理 |
| 232 | + TEST_ASSERT_GREATER_THAN_size_t(0, custom_free_count); |
| 233 | +} |
| 234 | + |
46 | 235 | int main(void) |
47 | 236 | { |
48 | 237 | UNITY_BEGIN(); |
49 | 238 | RUN_TEST(test_auto_resize); |
| 239 | + RUN_TEST(test_memory_hooks_set_and_reset); |
| 240 | + RUN_TEST(test_memory_hooks_invalid_params); |
| 241 | + RUN_TEST(test_memory_hooks_functionality); |
| 242 | + RUN_TEST(test_memory_hooks_multiple_operations); |
50 | 243 | return UNITY_END(); |
51 | 244 | } |
0 commit comments