|
10 | 10 | #include "cpu_io.h" |
11 | 11 | #include "singleton.hpp" |
12 | 12 | #include "sk_stdio.h" |
| 13 | +#include "sk_string.h" |
13 | 14 | #include "spinlock.hpp" |
14 | 15 | #include "syscall.hpp" |
15 | 16 | #include "system_test.h" |
16 | 17 | #include "task_manager.hpp" |
17 | | - |
18 | | -namespace { |
19 | | - |
20 | | -// 测试用的共享变量 |
21 | | -static std::atomic<int> shared_counter{0}; |
22 | | -static std::atomic<int> finished_tasks{0}; |
23 | | -static Mutex* test_mutex = nullptr; |
24 | | - |
25 | | -/** |
26 | | - * @brief 测试基本的 Lock/UnLock 功能 |
27 | | - */ |
28 | | -auto test_basic_lock() -> bool { |
29 | | - sk_printf("Running test_basic_lock...\n"); |
30 | | - |
31 | | - Mutex mutex("basic_test"); |
32 | | - EXPECT_TRUE(mutex.Lock(), "Basic lock failed"); |
33 | | - EXPECT_TRUE(mutex.IsLockedByCurrentTask(), |
34 | | - "IsLockedByCurrentTask failed after lock"); |
35 | | - EXPECT_TRUE(mutex.UnLock(), "Basic unlock failed"); |
36 | | - EXPECT_TRUE(!mutex.IsLockedByCurrentTask(), |
37 | | - "IsLockedByCurrentTask failed after unlock"); |
38 | | - |
39 | | - sk_printf("test_basic_lock passed\n"); |
40 | | - return true; |
41 | | -} |
42 | | - |
43 | | -/** |
44 | | - * @brief 测试递归加锁检测 |
45 | | - */ |
46 | | -auto test_recursive_lock() -> bool { |
47 | | - sk_printf("Running test_recursive_lock...\n"); |
48 | | - |
49 | | - Mutex mutex("recursive_test"); |
50 | | - EXPECT_TRUE(mutex.Lock(), "Lock failed in recursive test"); |
51 | | - |
52 | | - // 尝试递归获取锁应该失败 |
53 | | - if (mutex.Lock()) { |
54 | | - sk_printf("FAIL: Recursive lock should return false\n"); |
55 | | - mutex.UnLock(); // 尝试恢复 |
56 | | - mutex.UnLock(); |
57 | | - return false; |
58 | | - } |
59 | | - |
60 | | - EXPECT_TRUE(mutex.UnLock(), "Unlock failed in recursive test"); |
61 | | - |
62 | | - // 再次解锁应该失败(未持有锁) |
63 | | - if (mutex.UnLock()) { |
64 | | - sk_printf("FAIL: Double unlock should return false\n"); |
65 | | - return false; |
66 | | - } |
67 | | - |
68 | | - sk_printf("test_recursive_lock passed\n"); |
69 | | - return true; |
70 | | -} |
71 | | - |
72 | | -/** |
73 | | - * @brief 测试 TryLock 功能 |
74 | | - */ |
75 | | -auto test_trylock() -> bool { |
76 | | - sk_printf("Running test_trylock...\n"); |
77 | | - |
78 | | - Mutex mutex("trylock_test"); |
79 | | - |
80 | | - // 第一次 TryLock 应该成功 |
81 | | - EXPECT_TRUE(mutex.TryLock(), "First TryLock failed"); |
82 | | - EXPECT_TRUE(mutex.IsLockedByCurrentTask(), "TryLock didn't acquire lock"); |
83 | | - |
84 | | - // 再次 TryLock 应该失败(递归) |
85 | | - if (mutex.TryLock()) { |
86 | | - sk_printf("FAIL: Recursive TryLock should return false\n"); |
87 | | - mutex.UnLock(); |
88 | | - return false; |
89 | | - } |
90 | | - |
91 | | - EXPECT_TRUE(mutex.UnLock(), "UnLock after TryLock failed"); |
92 | | - |
93 | | - sk_printf("test_trylock passed\n"); |
94 | | - return true; |
95 | | -} |
96 | | - |
97 | | -/** |
98 | | - * @brief 测试 LockGuard<Mutex> RAII |
99 | | - */ |
100 | | -auto test_mutex_guard() -> bool { |
101 | | - sk_printf("Running test_mutex_guard...\n"); |
102 | | - |
103 | | - Mutex mutex("guard_test"); |
104 | | - |
105 | | - { |
106 | | - LockGuard<Mutex> guard(mutex); |
107 | | - EXPECT_TRUE(mutex.IsLockedByCurrentTask(), "LockGuard failed to lock"); |
108 | | - } |
109 | | - // 作用域结束后应该自动解锁 |
110 | | - EXPECT_TRUE(!mutex.IsLockedByCurrentTask(), "LockGuard failed to unlock"); |
111 | | - |
112 | | - sk_printf("test_mutex_guard passed\n"); |
113 | | - return true; |
114 | | -} |
115 | | - |
116 | | -/** |
117 | | - * @brief 测试多任务竞争互斥锁 |
118 | | - */ |
119 | | -void mutex_contention_task(void* arg) { |
120 | | - int task_id = *reinterpret_cast<int*>(arg); |
121 | | - sk_printf("Task %d: started\n", task_id); |
122 | | - |
123 | | - for (int i = 0; i < 100; ++i) { |
124 | | - // 获取互斥锁 |
125 | | - test_mutex->Lock(); |
126 | | - |
127 | | - // 临界区:增加共享计数器 |
128 | | - int old_value = shared_counter.load(); |
129 | | - // 模拟一些计算 |
130 | | - for (volatile int j = 0; j < 10; ++j) { |
131 | | - ; |
132 | | - } |
133 | | - shared_counter.store(old_value + 1); |
134 | | - |
135 | | - // 释放互斥锁 |
136 | | - test_mutex->UnLock(); |
137 | | - } |
138 | | - |
139 | | - sk_printf("Task %d: finished\n", task_id); |
140 | | - finished_tasks.fetch_add(1); |
141 | | -} |
142 | | - |
143 | | -/** |
144 | | - * @brief 测试多任务竞争场景 |
145 | | - */ |
146 | | -auto test_mutex_contention() -> bool { |
147 | | - sk_printf("Running test_mutex_contention...\n"); |
148 | | - |
149 | | - // 重置测试变量 |
150 | | - shared_counter = 0; |
151 | | - finished_tasks = 0; |
152 | | - |
153 | | - // 创建测试用的互斥锁 |
154 | | - static Mutex mutex("contention_test"); |
155 | | - test_mutex = &mutex; |
156 | | - |
157 | | - // 创建多个任务竞争同一个锁 |
158 | | - constexpr int kNumTasks = 4; |
159 | | - constexpr int kIterations = 100; |
160 | | - static int task_ids[kNumTasks]; |
161 | | - |
162 | | - auto& task_manager = Singleton<TaskManager>::GetInstance(); |
163 | | - |
164 | | - for (int i = 0; i < kNumTasks; ++i) { |
165 | | - task_ids[i] = i; |
166 | | - auto* task = new TaskControlBlock("mutex_test_task", 10, |
167 | | - mutex_contention_task, &task_ids[i]); |
168 | | - task_manager.AddTask(task); |
169 | | - } |
170 | | - |
171 | | - // 等待所有任务完成 |
172 | | - sk_printf("Waiting for tasks to complete...\n"); |
173 | | - while (finished_tasks.load() < kNumTasks) { |
174 | | - // 让出 CPU,让其他任务运行 |
175 | | - sys_yield(); |
176 | | - } |
177 | | - |
178 | | - // 验证计数器值 |
179 | | - int expected = kNumTasks * kIterations; |
180 | | - int actual = shared_counter.load(); |
181 | | - |
182 | | - if (actual != expected) { |
183 | | - sk_printf("FAIL: Expected counter=%d, got %d\n", expected, actual); |
184 | | - return false; |
185 | | - } |
186 | | - |
187 | | - sk_printf("test_mutex_contention passed (counter=%d)\n", actual); |
188 | | - return true; |
189 | | -} |
190 | | - |
191 | | -/** |
192 | | - * @brief 测试 LockGuard<Mutex> 在多任务场景下的使用 |
193 | | - */ |
194 | | -void mutex_guard_task(void* arg) { |
195 | | - int task_id = *reinterpret_cast<int*>(arg); |
196 | | - sk_printf("Task %d: started (with guard)\n", task_id); |
197 | | - |
198 | | - for (int i = 0; i < 100; ++i) { |
199 | | - // 使用 RAII 风格的 LockGuard<Mutex> |
200 | | - LockGuard<Mutex> guard(*test_mutex); |
201 | | - |
202 | | - // 临界区 |
203 | | - int old_value = shared_counter.load(); |
204 | | - for (volatile int j = 0; j < 10; ++j) { |
205 | | - ; |
206 | | - } |
207 | | - shared_counter.store(old_value + 1); |
208 | | - // guard 在作用域结束时自动释放锁 |
209 | | - } |
210 | | - |
211 | | - sk_printf("Task %d: finished (with guard)\n", task_id); |
212 | | - finished_tasks.fetch_add(1); |
213 | | -} |
214 | | - |
215 | | -/** |
216 | | - * @brief 测试 LockGuard<Mutex> 在多任务竞争场景 |
217 | | - */ |
218 | | -auto test_mutex_guard_contention() -> bool { |
219 | | - sk_printf("Running test_mutex_guard_contention...\n"); |
220 | | - |
221 | | - // 重置测试变量 |
222 | | - shared_counter = 0; |
223 | | - finished_tasks = 0; |
224 | | - |
225 | | - static Mutex mutex("guard_contention_test"); |
226 | | - test_mutex = &mutex; |
227 | | - |
228 | | - constexpr int kNumTasks = 4; |
229 | | - constexpr int kIterations = 100; |
230 | | - static int task_ids[kNumTasks]; |
231 | | - |
232 | | - auto& task_manager = Singleton<TaskManager>::GetInstance(); |
233 | | - |
234 | | - for (int i = 0; i < kNumTasks; ++i) { |
235 | | - task_ids[i] = i; |
236 | | - auto* task = new TaskControlBlock("mutex_guard_test_task", 10, |
237 | | - mutex_guard_task, &task_ids[i]); |
238 | | - task_manager.AddTask(task); |
239 | | - } |
240 | | - |
241 | | - // 等待所有任务完成 |
242 | | - sk_printf("Waiting for guard tasks to complete...\n"); |
243 | | - while (finished_tasks.load() < kNumTasks) { |
244 | | - sys_yield(); |
245 | | - } |
246 | | - |
247 | | - // 验证计数器值 |
248 | | - int expected = kNumTasks * kIterations; |
249 | | - int actual = shared_counter.load(); |
250 | | - |
251 | | - if (actual != expected) { |
252 | | - sk_printf("FAIL: Expected counter=%d, got %d\n", expected, actual); |
253 | | - return false; |
254 | | - } |
255 | | - |
256 | | - sk_printf("test_mutex_guard_contention passed (counter=%d)\n", actual); |
257 | | - return true; |
258 | | -} |
259 | | - |
260 | | -} // namespace |
261 | | - |
262 | | -namespace MutexTest { |
263 | | - |
264 | | -void RunTest() { |
265 | | - sk_printf("\n========== Mutex System Tests ==========\n"); |
266 | | - |
267 | | - bool all_passed = true; |
268 | | - |
269 | | - all_passed &= test_basic_lock(); |
270 | | - all_passed &= test_recursive_lock(); |
271 | | - all_passed &= test_trylock(); |
272 | | - all_passed &= test_mutex_guard(); |
273 | | - all_passed &= test_mutex_contention(); |
274 | | - all_passed &= test_mutex_guard_contention(); |
275 | | - |
276 | | - if (all_passed) { |
277 | | - sk_printf("\n[PASS] All Mutex tests passed!\n"); |
278 | | - } else { |
279 | | - sk_printf("\n[FAIL] Some Mutex tests failed!\n"); |
280 | | - } |
281 | | - |
282 | | - sk_printf("========== Mutex Tests Complete ==========\n\n"); |
283 | | -} |
284 | | - |
285 | | -} // namespace MutexTest |
0 commit comments