1 
2 #pragma GCC push_options
3 #pragma GCC optimize("O1")
4 #include "ktest.h"
5 #include "ktest_utils.h"
6 #include <common/idr.h>
7 
8 /**
9  * @brief 测试idr的构建,预获取空间是否成功
10  *
11  * 以下函数将被测试:
12  * 1. idr_preload
13  * 2. DECLARE_IDR
14  * 3. idr_init
15  * 4. idr_destroy
16  *
17  * 同时还会(间接)测试一些内部函数:
18  * 1. move_to_free_list
19  *
20  * @param arg0
21  * @param arg1
22  */
ktest_idr_case0(uint64_t arg0,uint64_t arg1)23 static long ktest_idr_case0(uint64_t arg0, uint64_t arg1)
24 {
25     unsigned long bitmap = -1;
26     assert((int)(bitmap == IDR_FULL));
27 
28     DECLARE_IDR(k_idr);
29     assert(k_idr.top == NULL);      // 刚被创建,必须是NULL
30     assert(k_idr.id_free_cnt == 0); // 必须是0
31     assert(k_idr.free_list == NULL);
32 
33     k_idr.id_free_cnt = arg1;
34     idr_init(&k_idr);
35     assert(k_idr.id_free_cnt == 0);
36 
37     assert(idr_preload(&k_idr, 0) == 0);
38     assert(k_idr.id_free_cnt == IDR_FREE_MAX);
39 
40     for (uint64_t i = 1; i < 64; i++)
41     {
42         int id = __lowbit_id(i), chk_id = -1;
43         for (int j = 0; j < 64; j++)
44             if ((i >> j) & 1)
45             {
46                 chk_id = j;
47                 break;
48             }
49         assert(id == chk_id);
50     }
51 
52     // 销毁
53     idr_destroy(&k_idr);
54     assert(k_idr.id_free_cnt == 0);
55     assert(k_idr.free_list == NULL);
56     assert(k_idr.top == NULL);
57 
58     return 0;
59 }
60 
61 /**
62  * @brief 测试id的获取,id的删除,id的全体删除, idr的find函数
63  *
64  * @param arg0
65  * @param arg1
66  */
ktest_idr_case1(uint64_t arg0,uint64_t arg1)67 static long ktest_idr_case1(uint64_t arg0, uint64_t arg1)
68 {
69     DECLARE_IDR(k_idr);
70     int a[128];
71 
72     // 获取128个id
73     for (int i = 0; i < 128; i++)
74     {
75         assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
76         assert(a[i] == i);
77     }
78 
79     // 查询128个ptr
80     for (int i = 0; i < 128; i++)
81     {
82         int *ptr = idr_find(&k_idr, a[i]);
83         assert(ptr == &a[i]);
84         assert(ptr != NULL);
85         assert(*ptr == a[i]);
86     }
87 
88     // 倒序:删除64个id
89     for (int i = 127; i >= 64; i--)
90     {
91         int *id = idr_remove(&k_idr, a[i]);
92         assert(id != NULL);
93         assert(*id == i);
94         assert(idr_find(&k_idr, a[i]) == NULL);
95     }
96 
97     // 正序:删除64个id
98     for (int i = 0; i <= 63; i++)
99     {
100         int *id = idr_remove(&k_idr, a[i]);
101         assert(id != NULL);
102         assert(*id == i);
103         assert(idr_find(&k_idr, a[i]) == NULL);
104     }
105 
106     for (int i = 0; i < 128; i++)
107     {
108         assert(idr_count(&k_idr, i) == 0);
109     }
110 
111     // 重新申请128个id, 值域范围应该仍然是[0,127]
112     for (int i = 0; i < 128; i++)
113     {
114         assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
115         assert(a[i] == i);
116     }
117 
118     for (int i = 0; i < 128; i++)
119     {
120         assert(idr_count(&k_idr, i));
121     }
122 
123     // 正序:删除32个id
124     for (int i = 0; i <= 31; i++)
125     {
126         int *id = idr_remove(&k_idr, a[i]);
127         assert(id != NULL);
128         assert(*id == i);
129         assert(idr_find(&k_idr, a[i]) == NULL);
130     }
131 
132     // 倒序:删除32个id
133     for (int i = 127; i >= 96; i--)
134     {
135         int *id = idr_remove(&k_idr, a[i]);
136         assert(id != NULL);
137         assert(*id == i);
138         assert(idr_find(&k_idr, a[i]) == NULL);
139     }
140 
141     // 整体删除
142     idr_remove_all(&k_idr);
143     assert(k_idr.top == NULL);
144 
145     // 获取128个id
146     for (int i = 0; i < 128; i++)
147     {
148         assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
149         assert(a[i] == i);
150     }
151 
152     // 查询128个ptr
153     for (int i = 0; i < 128; i++)
154     {
155         int *ptr = idr_find(&k_idr, a[i]);
156         assert(ptr == &a[i]);
157         assert(*ptr == a[i]);
158     }
159 
160     // 正序:删除64个id
161     for (int i = 0; i <= 63; i++)
162     {
163         idr_remove(&k_idr, a[i]);
164         assert(idr_find(&k_idr, a[i]) == NULL);
165     }
166 
167     // 倒序:删除64个id
168     for (int i = 127; i >= 64; i--)
169     {
170         idr_remove(&k_idr, a[i]);
171         assert(idr_find(&k_idr, a[i]) == NULL);
172     }
173 
174     // 销毁
175     idr_destroy(&k_idr);
176     assert(k_idr.id_free_cnt == 0);
177     assert(k_idr.free_list == NULL);
178 
179     return 0;
180 }
181 
182 /**
183  * @brief case1 的大数据测试
184  *
185  * @param arg0
186  * @param arg1
187  */
ktest_idr_case2(uint64_t arg0,uint64_t arg1)188 static long ktest_idr_case2(uint64_t arg0, uint64_t arg1)
189 {
190     DECLARE_IDR(k_idr);
191 
192     // 获取 1000‘000 个ID
193     const int N = 1e6;
194     // const int N = 1048576;
195     const int M = 2e5;
196 
197     int tmp = 0;
198     for (int i = 0; i < N; i++)
199     {
200         barrier();
201         assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
202         barrier();
203         assert(tmp == i);
204 
205         barrier();
206         int *ptr = idr_find(&k_idr, i);
207         barrier();
208         assert(ptr != NULL);
209         assert(*ptr == i);
210 
211         barrier();
212         // if (i >= 7255) kdebug("1e6 !!!!!!! : %d", i);
213         assert(idr_count(&k_idr, i));
214         barrier();
215     }
216     // kdebug("111111");
217     // 正向: M 个ID
218     for (int i = 0; i < M; i++)
219     {
220         int *ptr = idr_find(&k_idr, i);
221         assert(ptr != NULL);
222         assert(*ptr == N - 1);
223         idr_remove(&k_idr, i);
224         assert(idr_find(&k_idr, i) == NULL);
225     }
226     // kdebug("22222");
227 
228     // 倒序: N-M 个ID
229     for (int i = (N)-1; i >= M; i--)
230     {
231         int *ptr = idr_find(&k_idr, i);
232         assert(*ptr == N - 1);
233         idr_remove(&k_idr, i);
234         assert(idr_find(&k_idr, i) == NULL);
235     }
236     // kdebug("3333333");
237     // 重新插入数据
238     for (int i = 0; i < N; i++)
239     {
240         assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
241         assert(tmp == i);
242         assert(k_idr.top != NULL);
243 
244         int *ptr = idr_find(&k_idr, i);
245         assert(ptr != NULL);
246         assert(*ptr == i);
247     }
248     // kdebug("4444444444");
249     assert(k_idr.top != NULL);
250 
251     for (int i = 0; i < M; i++)
252     {
253         assert(idr_replace(&k_idr, NULL, i) == 0);
254     }
255     // kdebug("555555555555555555");
256     // 销毁
257     idr_destroy(&k_idr);
258     assert(k_idr.id_free_cnt == 0);
259     assert(k_idr.free_list == NULL);
260     // kdebug("666666666666");
261     return 0;
262 }
263 
264 /**
265  * @brief case1 的大数据测试
266  *
267  * @param arg0
268  * @param arg1
269  */
ktest_idr_case3(uint64_t arg0,uint64_t arg1)270 static long ktest_idr_case3(uint64_t arg0, uint64_t arg1)
271 {
272     DECLARE_IDR(k_idr);
273 
274     const int N = 1949;
275     int tmp;
276 
277     // 获取ID
278     for (int i = 0; i < N; i++)
279     {
280         assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
281         assert(tmp == i);
282 
283         int *ptr = idr_find(&k_idr, i);
284         assert(ptr != NULL);
285         assert(*ptr == i);
286     }
287 
288     // 查询 nextid
289     for (int i = 1; i <= N; i++)
290     {
291         int nextid;
292         int *ptr = idr_find_next_getid(&k_idr, i - 1, &nextid);
293         if (likely(i < N))
294         {
295             assert(ptr != NULL);
296             assert(*ptr == N - 1);
297             assert(nextid == i);
298         }
299         else
300         {
301             assert(ptr == NULL);
302             assert(nextid == -1);
303         }
304     }
305 
306     int sz = N;
307     // 删掉某一段
308     for (int i = N / 3, j = 2 * (N / 3), k = 0; i <= j; k++, i++)
309     {
310         int *ptr = idr_find(&k_idr, i);
311         assert(ptr != NULL);
312         assert(*ptr == N - 1);
313         idr_remove(&k_idr, i);
314 
315         assert(idr_find(&k_idr, i) == NULL);
316         sz--;
317         assert(k_idr.top != NULL);
318     }
319 
320     // 查询 nextid
321     for (int i = 1; i <= N; i++)
322     {
323         int nextid;
324         int *ptr = idr_find_next_getid(&k_idr, i - 1, &nextid);
325         if (likely(i < N))
326         {
327             int target = i < N / 3 ? i : max(i, 2 * (N / 3) + 1);
328             assert(ptr != NULL);
329             assert(*ptr == N - 1);
330             assert(nextid == target);
331         }
332         else
333         {
334             assert(ptr == NULL);
335             assert(nextid == -1);
336         }
337     }
338 
339     // 销毁
340     idr_destroy(&k_idr);
341     assert(k_idr.id_free_cnt == 0);
342     assert(k_idr.free_list == NULL);
343 
344     return 0;
345 }
346 
347 /**
348  * @brief 更加全面覆盖所有函数 - 小数据测试
349  *
350  * @param arg0
351  * @param arg1
352  */
ktest_idr_case4(uint64_t arg0,uint64_t arg1)353 static long ktest_idr_case4(uint64_t arg0, uint64_t arg1)
354 {
355     DECLARE_IDR(k_idr);
356     idr_init(&k_idr);
357 
358     const int N = 91173;
359     static uint32_t tmp;
360 
361     for (int i = 1; i <= 20; i++)
362     {
363         int M = N / i, T = M / 3, b = 2 * T;
364         for (int j = 0; j < M; j++)
365         {
366             assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
367             assert(tmp == j);
368         }
369 
370         for (int j = b; j >= T; j--)
371         {
372             int *ptr = idr_find(&k_idr, j);
373             assert(ptr != NULL);
374             assert(*ptr == M - 1);
375             idr_remove(&k_idr, j);
376         }
377 
378         for (int j = b + 1; j < M; j++)
379         {
380             int *ptr = idr_find(&k_idr, j);
381             assert(ptr != NULL);
382             assert(*ptr == M - 1);
383             idr_remove(&k_idr, j);
384         }
385 
386         for (int j = T - 1; j >= 0; j--)
387         {
388             int *ptr = idr_find(&k_idr, j);
389             assert(ptr != NULL);
390             assert(*ptr == M - 1);
391             idr_remove(&k_idr, j);
392         }
393 
394         assert(k_idr.top == NULL);
395         assert(idr_empty(&k_idr));
396     }
397 
398     // 销毁
399     idr_destroy(&k_idr);
400     assert(k_idr.id_free_cnt == 0);
401     assert(k_idr.free_list == NULL);
402     assert(idr_empty(&k_idr));
403 
404     return 0;
405 }
406 
407 /**
408  * @brief 测试id的获取,id的删除,id的全体删除, idr的find函数
409  *
410  * @param arg0
411  * @param arg1
412  */
ktest_idr_case5(uint64_t arg0,uint64_t arg1)413 static long ktest_idr_case5(uint64_t arg0, uint64_t arg1)
414 {
415     DECLARE_IDR(k_idr);
416     const int N = 128;
417     int a[N];
418 
419     // 获取128个id
420     for (int i = 0; i < N; i++)
421     {
422         assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
423         assert(a[i] == i);
424     }
425 
426     // 把id指向的指针向后移动一个单位
427     for (int i = 0; i < N; i++)
428     {
429         int *ptr;
430         int flags = idr_replace_get_old(&k_idr, &a[(i + 1) % N], i, (void *)&ptr);
431         assert(flags == 0); // 0 是成功
432         assert(ptr != NULL);
433         assert(*ptr == i);
434 
435         // 测试是否替换成功
436         ptr = idr_find(&k_idr, i);
437         assert(ptr != NULL);
438         assert(*ptr == (i + 1) % N);
439     }
440 
441     // 销毁
442     idr_destroy(&k_idr);
443     assert(k_idr.id_free_cnt == 0);
444     assert(k_idr.free_list == NULL);
445 
446     // destroy之后,再获取128个id
447     for (int i = 0; i < N; i++)
448     {
449         assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0);
450         assert(a[i] == i);
451     }
452 
453     // 销毁
454     idr_destroy(&k_idr);
455     assert(idr_empty(&k_idr));
456     assert(k_idr.id_free_cnt == 0);
457     assert(k_idr.free_list == NULL);
458 
459     return 0;
460 }
461 
462 /**
463  * @brief 测试ida的插入/删除
464  *
465  * @param arg0
466  * @param arg1
467  * @return long
468  */
ktest_idr_case6(uint64_t arg0,uint64_t arg1)469 static long ktest_idr_case6(uint64_t arg0, uint64_t arg1)
470 {
471     assert(IDA_BITMAP_LONGS != 0);
472     assert(IDA_BMP_SIZE != 0);
473     assert(IDA_FULL != 0);
474     assert(IDA_BITMAP_BITS != 0);
475 
476     DECLARE_IDA(k_ida);
477     ida_init(&k_ida);
478     io_sfence();
479 
480     const int N = IDA_FULL * IDR_SIZE + 1;
481 
482     for (int i = 0; i < N; i++)
483     {
484         int p_id;
485         io_sfence();
486         assert(ida_alloc(&k_ida, &p_id) == 0);
487         io_sfence();
488         assert(p_id == i);
489         io_sfence();
490     }
491 
492     for (int i = 0; i < N; i++)
493     {
494         assert(ida_count(&k_ida, i) == 1);
495         io_sfence();
496     }
497 
498     for (int i = N - 1; i >= 0; i--)
499     {
500         ida_remove(&k_ida, i);
501         io_sfence();
502         assert(ida_count(&k_ida, i) == 0);
503         io_sfence();
504     }
505 
506     assert(k_ida.idr.top == NULL);
507 
508     for (int i = 0; i < N; i++)
509     {
510         int p_id;
511         io_sfence();
512         assert(ida_alloc(&k_ida, &p_id) == 0);
513         io_sfence();
514         assert(p_id == i);
515         io_sfence();
516     }
517 
518     assert(k_ida.idr.top != NULL);
519     io_sfence();
520     ida_destroy(&k_ida);
521     io_sfence();
522     assert(k_ida.idr.top == NULL);
523     io_sfence();
524     assert(k_ida.free_list == NULL);
525     io_sfence();
526     assert(ida_empty(&k_ida));
527     io_sfence();
528 
529     // 测试destroy之后能否重新获取ID
530     for (int i = 0; i < N; i++)
531     {
532         int p_id;
533         io_sfence();
534         assert(ida_alloc(&k_ida, &p_id) == 0);
535         io_sfence();
536         assert(p_id == i);
537         io_sfence();
538     }
539 
540     for (int i = 0; i < N / 3; i++)
541     {
542         ida_remove(&k_ida, i);
543         io_sfence();
544         assert(ida_count(&k_ida, i) == 0);
545         io_sfence();
546     }
547 
548     for (int i = 2 * N / 3; i < N; i++)
549     {
550         ida_remove(&k_ida, i);
551         io_sfence();
552         assert(ida_count(&k_ida, i) == 0);
553         io_sfence();
554     }
555 
556     assert(k_ida.idr.top != NULL);
557     io_sfence();
558     ida_destroy(&k_ida);
559     io_sfence();
560     assert(k_ida.idr.top == NULL);
561     io_sfence();
562     assert(k_ida.free_list == NULL);
563     io_sfence();
564     assert(ida_empty(&k_ida));
565     io_sfence();
566 
567     return 0;
568 }
569 
570 static ktest_case_table kt_idr_func_table[] = {
571     ktest_idr_case0,
572     ktest_idr_case1,
573     // ktest_idr_case2, // 为了加快启动速度, 暂时注释掉这个测试
574     ktest_idr_case3,
575     ktest_idr_case4,
576     ktest_idr_case5,
577     ktest_idr_case6,
578 };
579 
ktest_test_idr(void * arg)580 int ktest_test_idr(void *arg)
581 {
582     kTEST("Testing idr...");
583     unsigned int sz = sizeof(kt_idr_func_table) / sizeof(ktest_case_table);
584     for (int i = 0; i < sz; ++i)
585     {
586         kTEST("Testing case %d", i);
587         kt_idr_func_table[i](i, i + 1);
588     }
589     kTEST("idr Test done.");
590     return 0;
591 }
592 
593 #pragma GCC pop_options