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