1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2018-08-31     armink       the first version
9  */
10 
11 #include <string.h>
12 #include <rtthread.h>
13 #include <rtdevice.h>
14 #include <stdlib.h>
15 
16 static rt_bool_t put_finish = RT_FALSE;
17 
put_thread(void * param)18 static void put_thread(void *param)
19 {
20     rt_rbb_t rbb = (rt_rbb_t)param;
21     rt_rbb_blk_t block;
22     rt_uint8_t put_count = 0;
23 
24     put_finish = RT_FALSE;
25 
26     while (put_count < 255)
27     {
28         if (put_count == 10)
29         {
30             put_count = 10;
31         }
32         block = rt_rbb_blk_alloc(rbb, rand() % 10 + 1);
33         if (block)
34         {
35             block->buf[0] = put_count++;
36             rt_rbb_blk_put(block);
37         }
38         rt_thread_mdelay(rand() % 10);
39     }
40     rt_kprintf("Put block data finish.\n");
41 
42     put_finish = RT_TRUE;
43 }
44 
get_thread(void * param)45 static void get_thread(void *param)
46 {
47     rt_rbb_t rbb = (rt_rbb_t)param;
48     rt_rbb_blk_t block;
49     rt_uint8_t get_count = 0;
50 
51     while (get_count < 255)
52     {
53         if (get_count == 10)
54         {
55             get_count = 10;
56         }
57         block = rt_rbb_blk_get(rbb);
58         if (block)
59         {
60             if (block->buf[0] != get_count++)
61             {
62                 rt_kprintf("Error: get data (times %d) has an error!\n", get_count);
63             }
64             rt_rbb_blk_free(rbb, block);
65         }
66         else if (put_finish)
67         {
68             break;
69         }
70         rt_thread_mdelay(rand() % 10);
71     }
72     rt_kprintf("Get block data finish.\n");
73     rt_kprintf("\n====================== rbb dynamic test finish =====================\n");
74 }
75 
rbb_test(void)76 void rbb_test(void)
77 {
78     rt_rbb_t rbb;
79     rt_rbb_blk_t blk1, blk2, blk3, blk4, blk5, blk6, _blk1, _blk2;
80     rt_size_t i, j, k, req_size, size;
81     struct rt_rbb_blk_queue blk_queue1;
82     rt_thread_t thread;
83 
84     /* create ring block buffer */
85     rt_kprintf("\n====================== rbb create test =====================\n");
86     rbb = rt_rbb_create(52, 6);
87     if (rbb)
88     {
89         rt_kprintf("6 blocks in 52 bytes ring block buffer object create success.\n");
90     }
91     else
92     {
93         rt_kprintf("Test error: 6 blocks in 52 bytes ring block buffer object create failed.\n");
94     }
95     /* allocate block */
96     rt_kprintf("\n====================== rbb alloc test =====================\n");
97     blk1 = rt_rbb_blk_alloc(rbb, 2);
98     if (blk1 && blk1->size == 2)
99     {
100         memset(blk1->buf, 1, blk1->size);
101         rt_kprintf("Block1 (2 bytes) allocate success.\n");
102     }
103     else
104     {
105         rt_kprintf("Test error: block1 (2 bytes) allocate failed.\n");
106         goto __exit;
107     }
108     blk2 = rt_rbb_blk_alloc(rbb, 4);
109     if (blk2 && blk2->size == 4)
110     {
111         memset(blk2->buf, 2, blk2->size);
112         rt_kprintf("Block2 (4 bytes) allocate success.\n");
113     }
114     else
115     {
116         rt_kprintf("Test error: block2 (4 bytes) allocate failed.\n");
117         goto __exit;
118     }
119     blk3 = rt_rbb_blk_alloc(rbb, 8);
120     if (blk3 && blk3->size == 8)
121     {
122         memset(blk3->buf, 3, blk3->size);
123         rt_kprintf("Block3 (8 bytes) allocate success.\n");
124     }
125     else
126     {
127         rt_kprintf("Test error: block3 (8 bytes) allocate failed.\n");
128         goto __exit;
129     }
130     blk4 = rt_rbb_blk_alloc(rbb, 16);
131     if (blk4 && blk4->size == 16)
132     {
133         memset(blk4->buf, 4, blk4->size);
134         rt_kprintf("Block4 (16 bytes) allocate success.\n");
135     }
136     else
137     {
138         rt_kprintf("Test error: block4 (16 bytes) allocate failed.\n");
139         goto __exit;
140     }
141     blk5 = rt_rbb_blk_alloc(rbb, 32);
142     if (blk5 && blk5->size == 32)
143     {
144         memset(blk5->buf, 5, blk5->size);
145         rt_kprintf("Block5 (32 bytes) allocate success.\n");
146     }
147     else
148     {
149         rt_kprintf("Block5 (32 bytes) allocate failed.\n");
150     }
151     blk5 = rt_rbb_blk_alloc(rbb, 18);
152     if (blk5 && blk5->size == 18)
153     {
154         memset(blk5->buf, 5, blk5->size);
155         rt_kprintf("Block5 (18 bytes) allocate success.\n");
156     }
157     else
158     {
159         rt_kprintf("Test error: block5 (18 bytes) allocate failed.\n");
160         goto __exit;
161     }
162     rt_kprintf("Ring block buffer current status:\n");
163     rt_kprintf("next block queue length: %d\n", rt_rbb_next_blk_queue_len(rbb));
164     rt_kprintf("block list length: %d\n", rt_slist_len(&rbb->blk_list));
165     rt_kprintf("|<- 2 -->|<-- 4 -->|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|\n");
166     rt_kprintf("+--------+---------+--------------+---------------------+------------------+-------------+\n");
167     rt_kprintf("| blcok1 | block2  |    block3    |       block4        |       block5     |    empty    |\n");
168     rt_kprintf("+--------+---------+--------------+---------------------+------------------+-------------+\n");
169     rt_kprintf("| inited | inited  |    inited    |       inited        |       inited     |             |\n");
170 
171     /* put block */
172     rt_kprintf("\n====================== rbb put test =====================\n");
173     rt_rbb_blk_put(blk1);
174     rt_rbb_blk_put(blk2);
175     rt_rbb_blk_put(blk3);
176     rt_rbb_blk_put(blk4);
177     rt_rbb_blk_put(blk5);
178     rt_kprintf("Block1 to block5 put success.\n");
179     rt_kprintf("Ring block buffer current status:\n");
180     rt_kprintf("next block queue length: %d\n", rt_rbb_next_blk_queue_len(rbb));
181     rt_kprintf("block list length: %d\n", rt_slist_len(&rbb->blk_list));
182     rt_kprintf("|<- 2 -->|<-- 4 -->|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|\n");
183     rt_kprintf("+--------+---------+--------------+---------------------+------------------+-------------+\n");
184     rt_kprintf("| blcok1 | block2  |    block3    |       block4        |       block5     |    empty    |\n");
185     rt_kprintf("+--------+---------+--------------+---------------------+------------------+-------------+\n");
186     rt_kprintf("|  put   |  put    |     put      |        put          |        put       |             |\n");
187 
188     /* get block */
189     rt_kprintf("\n====================== rbb get test =====================\n");
190     _blk1 = rt_rbb_blk_get(rbb);
191     _blk2 = rt_rbb_blk_get(rbb);
192     for (i = 0; i < _blk1->size; i++)
193     {
194         if (_blk1->buf[i] != 1) break;
195     }
196     for (j = 0; j < _blk2->size; j++)
197     {
198         if (_blk2->buf[j] != 2) break;
199     }
200     if (blk1 == _blk1 && blk2 == _blk2 && i == _blk1->size && j == _blk2->size)
201     {
202         rt_kprintf("Block1 and block2 get success.\n");
203     }
204     else
205     {
206         rt_kprintf("Test error: block1 and block2 get failed.\n");
207         goto __exit;
208     }
209     rt_kprintf("Ring block buffer current status:\n");
210     rt_kprintf("next block queue length: %d\n", rt_rbb_next_blk_queue_len(rbb));
211     rt_kprintf("block list length: %d\n", rt_slist_len(&rbb->blk_list));
212     rt_kprintf("|<- 2 -->|<-- 4 -->|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|\n");
213     rt_kprintf("+--------+---------+--------------+---------------------+------------------+-------------+\n");
214     rt_kprintf("| blcok1 | block2  |    block3    |       block4        |       block5     |    empty    |\n");
215     rt_kprintf("+--------+---------+--------------+---------------------+------------------+-------------+\n");
216     rt_kprintf("|  get   |   get   |     put      |        put          |        put       |             |\n");
217 
218     /* free block */
219     rt_kprintf("\n====================== rbb free test =====================\n");
220     rt_rbb_blk_free(rbb, blk2);
221     rt_kprintf("Block2 free success.\n");
222     rt_rbb_blk_free(rbb, blk1);
223     rt_kprintf("Block1 free success.\n");
224     rt_kprintf("Ring block buffer current status:\n");
225     rt_kprintf("next block queue length: %d\n", rt_rbb_next_blk_queue_len(rbb));
226     rt_kprintf("block list length: %d\n", rt_slist_len(&rbb->blk_list));
227     rt_kprintf("|<------- 6 ------>|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|\n");
228     rt_kprintf("+------------------+--------------+---------------------+------------------+-------------+\n");
229     rt_kprintf("|      empty2      |    block3    |       block4        |       block5     |    empty1   |\n");
230     rt_kprintf("+------------------+--------------+---------------------+------------------+-------------+\n");
231     rt_kprintf("|                  |     put      |        put          |        put       |             |\n");
232 
233     blk6 = rt_rbb_blk_alloc(rbb, 5);
234     if (blk6)
235     {
236         rt_kprintf("Block6 (5 bytes) allocate success.\n");
237     }
238     else
239     {
240         rt_kprintf("Test error: block6 (5 bytes) allocate failed.\n");
241         goto __exit;
242     }
243 
244     rt_rbb_blk_put(blk6);
245     rt_kprintf("Block6 put success.\n");
246     rt_kprintf("Ring block buffer current status:\n");
247     rt_kprintf("next block queue length: %d\n", rt_rbb_next_blk_queue_len(rbb));
248     rt_kprintf("block list length: %d\n", rt_slist_len(&rbb->blk_list));
249     rt_kprintf("|<--- 5 ---->|< 1 >|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|\n");
250     rt_kprintf("+------------+-----+--------------+---------------------+------------------+-------------+\n");
251     rt_kprintf("|   block6   |empty|    block3    |       block4        |       block5     |   fragment  |\n");
252     rt_kprintf("+------------+-----+--------------+---------------------+------------------+-------------+\n");
253     rt_kprintf("|     put    |     |     put      |        put          |        put       |             |\n");
254 
255     /* get block queue */
256     rt_kprintf("\n====================== rbb block queue get test =====================\n");
257     req_size = rt_rbb_next_blk_queue_len(rbb) + 5;
258     size = rt_rbb_blk_queue_get(rbb, req_size, &blk_queue1);
259     i = j = k = 0;
260     for (; i < blk3->size; i++)
261     {
262         if (rt_rbb_blk_queue_buf(&blk_queue1)[i] != 3) break;
263     }
264     for (; j < blk4->size; j++)
265     {
266         if (rt_rbb_blk_queue_buf(&blk_queue1)[i + j] != 4) break;
267     }
268     for (; k < blk5->size; k++)
269     {
270         if (rt_rbb_blk_queue_buf(&blk_queue1)[i + j + k] != 5) break;
271     }
272     if (size && size == 42 && rt_rbb_blk_queue_len(&blk_queue1) == 42 && k == blk5->size)
273     {
274         rt_kprintf("Block queue (request %d bytes, actual %d) get success.\n", req_size, size);
275     }
276     else
277     {
278         rt_kprintf("Test error: Block queue (request %d bytes, actual %d) get failed.\n", req_size, size);
279         goto __exit;
280     }
281     rt_kprintf("Ring block buffer current status:\n");
282     rt_kprintf("next block queue length: %d\n", rt_rbb_next_blk_queue_len(rbb));
283     rt_kprintf("block list length: %d\n", rt_slist_len(&rbb->blk_list));
284     rt_kprintf("|            |     |<----- block queue1 (42 bytes continuous buffer) ----->|             |\n");
285     rt_kprintf("|<--- 5 ---->|< 1 >|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|\n");
286     rt_kprintf("+------------+-----+--------------+---------------------+------------------+-------------+\n");
287     rt_kprintf("|   block6   |empty|    block3    |       block4        |       block5     |   fragment  |\n");
288     rt_kprintf("+------------+-----+--------------+---------------------+------------------+-------------+\n");
289     rt_kprintf("|     put    |     |     get      |        get          |        get       |             |\n");
290 
291     /* free block queue */
292     rt_kprintf("\n====================== rbb block queue free test =====================\n");
293     rt_rbb_blk_queue_free(rbb, &blk_queue1);
294     rt_kprintf("Block queue1 free success.\n");
295     rt_kprintf("Ring block buffer current status:\n");
296     rt_kprintf("next block queue length: %d\n", rt_rbb_next_blk_queue_len(rbb));
297     rt_kprintf("block list length: %d\n", rt_slist_len(&rbb->blk_list));
298     rt_kprintf("|<--- 5 ---->|<--------------------------------- 47 ------------------------------------>|\n");
299     rt_kprintf("+------------+---------------------------------------------------------------------------+\n");
300     rt_kprintf("|   block6   |                                 empty                                     |\n");
301     rt_kprintf("+------------+---------------------------------------------------------------------------+\n");
302     rt_kprintf("|     put    |                                                                           |\n");
303     rt_rbb_blk_free(rbb, blk6);
304 
305     rt_kprintf("\n====================== rbb static test SUCCESS =====================\n");
306 
307     rt_kprintf("\n====================== rbb dynamic test =====================\n");
308 
309     thread = rt_thread_create("rbb_put", put_thread, rbb, 1024, 10, 25);
310     if (thread)
311     {
312         rt_thread_startup(thread);
313     }
314 
315     thread = rt_thread_create("rbb_get", get_thread, rbb, 1024, 10, 25);
316     if (thread)
317     {
318         rt_thread_startup(thread);
319     }
320 
321 __exit :
322 
323     rt_rbb_destroy(rbb);
324 }
325 
326 MSH_CMD_EXPORT(rbb_test, run ring block buffer testcase)
327 
328