1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <zephyr/ztest.h>
18 #include <zephyr/irq_offload.h>
19 #include <zephyr/sys/ring_buffer.h>
20
21 #include <zephyr/logging/log.h>
22 LOG_MODULE_REGISTER(test);
23
24 /**
25 * @defgroup lib_ringbuffer_tests Ringbuffer
26 * @ingroup all_tests
27 * @{
28 * @}
29 */
30
31 RING_BUF_ITEM_DECLARE_POW2(ring_buf1, 8);
32
33 #define TYPE 1
34 #define VALUE 2
35 #define INITIAL_SIZE 2
36
37
38 #define RINGBUFFER_SIZE 5
39 #define DATA_MAX_SIZE 3
40 #define POW 2
41 extern void test_ringbuffer_concurrent(void);
42 extern void test_ringbuffer_zerocpy_stress(void);
43 extern void test_ringbuffer_cpy_stress(void);
44 extern void test_ringbuffer_item_stress(void);
45 /**
46 * @brief Test APIs of ring buffer
47 *
48 * @details
49 * Test Objective:
50 * - Define and initialize a ring buffer and
51 * the ring buffer copy data out of the array by
52 * ring_buf_item_put(), and then ring buffer data
53 * is copied into the array by ring_buf_item_get()
54 * return error when full/empty.
55 *
56 * Testing techniques:
57 * - Interface testing
58 * - Dynamic analysis and testing
59 * - Equivalence classes and input partition testing
60 * - Structural test coverage(entry points,statements,branches)
61 *
62 * Prerequisite Conditions:
63 * - Define and initialize a ringbuffer by using macro
64 * RING_BUF_ITEM_DECLARE_POW2
65 *
66 * Input Specifications:
67 * - N/A
68 *
69 * Test Procedure:
70 * -# Defined an array with some data items that ready for being
71 * put.
72 * -# Put data items with "while loop".
73 * -# Check if an error will be seen when the ringbuffer is full.
74 * -# Get data items from the ringbuffer.
75 * -# Check if the data put are equal to the data got.
76 * -# Going on getting data from the ringbuffer.
77 * -# Check if an error will be seen when the ringbuffer is empty.
78 *
79 * Expected Test Result:
80 * - Data items pushed shall be equal to what are gotten. And
81 * An error shall be shown up when an item is put into a full ringbuffer or
82 * get some items from an empty ringbuffer.
83 *
84 * Pass/Fail Criteria:
85 * - Success if test result of step 3.5,7 is passed. Otherwise, failure.
86 *
87 * Assumptions and Constraints:
88 * - N/A
89 *
90 * @ingroup lib_ringbuffer_tests
91 *
92 * @see ring_buf_item_put, ring_buf_item_get
93 */
ZTEST(ringbuffer_api,test_ring_buffer_main)94 ZTEST(ringbuffer_api, test_ring_buffer_main)
95 {
96 int ret, put_count, i;
97 uint32_t getdata[6];
98 uint8_t getsize, getval;
99 uint16_t gettype;
100 int dsize = INITIAL_SIZE;
101
102 __aligned(sizeof(uint32_t)) char rb_data[] = "ABCDEFGHIJKLMNOPQRSTUVWX";
103 put_count = 0;
104
105 while (1) {
106 ret = ring_buf_item_put(&ring_buf1, TYPE, VALUE,
107 (uint32_t *)rb_data, dsize);
108 if (ret == -EMSGSIZE) {
109 LOG_DBG("ring buffer is full");
110 break;
111 }
112 LOG_DBG("inserted %d chunks, %d remaining", dsize,
113 ring_buf_space_get(&ring_buf1));
114 dsize = (dsize + 1) % RING_BUF_ITEM_SIZEOF(rb_data);
115 put_count++;
116 }
117
118 getsize = INITIAL_SIZE - 1;
119 ret = ring_buf_item_get(&ring_buf1, &gettype, &getval,
120 getdata, &getsize);
121 if (ret != -EMSGSIZE) {
122 LOG_DBG("Allowed retrieval with insufficient "
123 "destination buffer space");
124 zassert_true((getsize == INITIAL_SIZE),
125 "Correct size wasn't reported back to the caller");
126 }
127
128 for (i = 0; i < put_count; i++) {
129 getsize = RING_BUF_ITEM_SIZEOF(getdata);
130 ret = ring_buf_item_get(&ring_buf1, &gettype, &getval, getdata,
131 &getsize);
132 zassert_true((ret == 0), "Couldn't retrieve a stored value");
133 LOG_DBG("got %u chunks of type %u and val %u, %u remaining",
134 getsize, gettype, getval,
135 ring_buf_item_space_get(&ring_buf1));
136
137 zassert_true((memcmp((char *)getdata, rb_data,
138 getsize * sizeof(uint32_t)) == 0), "data corrupted");
139 zassert_true((gettype == TYPE), "type information corrupted");
140 zassert_true((getval == VALUE), "value information corrupted");
141 }
142
143 getsize = RING_BUF_ITEM_SIZEOF(getdata);
144 ret = ring_buf_item_get(&ring_buf1, &gettype, &getval, getdata,
145 &getsize);
146 zassert_true((ret == -EAGAIN), "Got data out of an empty buffer");
147 }
148
149 /**TESTPOINT: init via RING_BUF_ITEM_DECLARE_POW2*/
150 RING_BUF_ITEM_DECLARE_POW2(ringbuf_pow2, POW);
151
152 /**TESTPOINT: init via RING_BUF_ITEM_DECLARE*/
153 /**
154 * @brief define a ring buffer with arbitrary size
155 *
156 * @see RING_BUF_ITEM_DECLARE(), RING_BUF_DECLARE()
157 */
158 RING_BUF_ITEM_DECLARE(ringbuf_size, RINGBUFFER_SIZE);
159
160 RING_BUF_DECLARE(ringbuf_raw, RINGBUFFER_SIZE);
161
162 static struct ring_buf ringbuf, *pbuf;
163
164 static uint32_t buffer[RINGBUFFER_SIZE];
165
166 static struct {
167 uint8_t length;
168 uint8_t value;
169 uint16_t type;
170 uint32_t buffer[DATA_MAX_SIZE];
171 } static_data[] = {
172 { 0, 32, 1, {} },
173 { 1, 76, 54, { 0x89ab } },
174 { 3, 0xff, 0xffff, { 0x0f0f, 0xf0f0, 0xff00 } }
175 };
176
177 /*entry of contexts*/
tringbuf_put(const void * p)178 static void tringbuf_put(const void *p)
179 {
180 int index = POINTER_TO_INT(p);
181 /**TESTPOINT: ring buffer put*/
182 int ret = ring_buf_item_put(pbuf, static_data[index].type, static_data[index].value,
183 static_data[index].buffer, static_data[index].length);
184
185 zassert_equal(ret, 0);
186 }
187
tringbuf_get(const void * p)188 static void tringbuf_get(const void *p)
189 {
190 uint16_t type;
191 uint8_t value, size32 = DATA_MAX_SIZE;
192 uint32_t rx_data[DATA_MAX_SIZE];
193 int ret, index = POINTER_TO_INT(p);
194
195 /**TESTPOINT: ring buffer get*/
196 ret = ring_buf_item_get(pbuf, &type, &value, rx_data, &size32);
197 zassert_equal(ret, 0);
198 zassert_equal(type, static_data[index].type);
199 zassert_equal(value, static_data[index].value);
200 zassert_equal(size32, static_data[index].length);
201 zassert_equal(memcmp(rx_data, static_data[index].buffer, size32), 0);
202 }
203
tringbuf_get_discard(const void * p)204 static void tringbuf_get_discard(const void *p)
205 {
206 uint16_t type;
207 uint8_t value, size32;
208 int ret, index = POINTER_TO_INT(p);
209
210 /**TESTPOINT: ring buffer get*/
211 ret = ring_buf_item_get(pbuf, &type, &value, NULL, &size32);
212 zassert_equal(ret, 0);
213 zassert_equal(type, static_data[index].type);
214 zassert_equal(value, static_data[index].value);
215 zassert_equal(size32, static_data[index].length);
216 }
217
218 /*test cases*/
ZTEST(ringbuffer_api,test_ringbuffer_init)219 ZTEST(ringbuffer_api, test_ringbuffer_init)
220 {
221 /**TESTPOINT: init via ring_buf_item_init*/
222 ring_buf_item_init(&ringbuf, RINGBUFFER_SIZE, buffer);
223 zassert_true(ring_buf_is_empty(&ringbuf));
224 zassert_equal(ring_buf_item_space_get(&ringbuf), RINGBUFFER_SIZE);
225 }
226
ZTEST(ringbuffer_api,test_ringbuffer_declare_pow2)227 ZTEST(ringbuffer_api, test_ringbuffer_declare_pow2)
228 {
229 zassert_true(ring_buf_is_empty(&ringbuf_pow2));
230 zassert_equal(ring_buf_item_space_get(&ringbuf_pow2), (1 << POW));
231 }
232
ZTEST(ringbuffer_api,test_ringbuffer_declare_size)233 ZTEST(ringbuffer_api, test_ringbuffer_declare_size)
234 {
235 zassert_true(ring_buf_is_empty(&ringbuf_size));
236 zassert_equal(ring_buf_item_space_get(&ringbuf_size), RINGBUFFER_SIZE,
237 NULL);
238 }
239
240 /**
241 * @brief verify that ringbuffer can be placed in any user-controlled memory
242 *
243 * @details
244 * Test Objective:
245 * - define and initialize a ring buffer by struct ring_buf,
246 * then passing data by thread to verify the ringbuffer
247 * if it works to be placed in any user-controlled memory.
248 *
249 * Testing techniques:
250 * - Interface testing
251 * - Dynamic analysis and testing
252 * - Structural test coverage(entry points,statements,branches)
253 *
254 * Prerequisite Conditions:
255 * - Define and initialize a ringbuffer by using struct ring_buf
256 * - Define a pointer of ring buffer type.
257 *
258 * Input Specifications:
259 * - N/A
260 *
261 * Test Procedure:
262 * -# Put data items into a ringbuffer
263 * -# Get data items from a ringbuffer
264 * -# Check if data items pushed are equal to what are gotten.
265 * -# Repeat 1,2,3 to verify the ringbuffer is working normally.
266 *
267 * Expected Test Result:
268 * - data items pushed shall be equal to what are gotten.
269 *
270 * Pass/Fail Criteria:
271 * - Success if test result of step 3,4 is passed. Otherwise, failure.
272 *
273 * Assumptions and Constraints:
274 * - N/A
275 *
276 * @ingroup lib_ringbuffer_tests
277 *
278 * @see ring_buf_item_put, ring_buf_item_get
279 */
ZTEST(ringbuffer_api,test_ringbuffer_put_get_thread)280 ZTEST(ringbuffer_api, test_ringbuffer_put_get_thread)
281 {
282 pbuf = &ringbuf;
283 for (int i = 0; i < 1000; i++) {
284 tringbuf_put((const void *)0);
285 tringbuf_put((const void *)1);
286 tringbuf_get((const void *)0);
287 tringbuf_get((const void *)1);
288 tringbuf_put((const void *)2);
289 zassert_false(ring_buf_is_empty(pbuf));
290 tringbuf_get((const void *)2);
291 zassert_true(ring_buf_is_empty(pbuf));
292 }
293 }
294
ZTEST(ringbuffer_api,test_ringbuffer_put_get_isr)295 ZTEST(ringbuffer_api, test_ringbuffer_put_get_isr)
296 {
297 pbuf = &ringbuf;
298 irq_offload(tringbuf_put, (const void *)0);
299 irq_offload(tringbuf_put, (const void *)1);
300 irq_offload(tringbuf_get, (const void *)0);
301 irq_offload(tringbuf_get, (const void *)1);
302 irq_offload(tringbuf_put, (const void *)2);
303 zassert_false(ring_buf_is_empty(pbuf));
304 irq_offload(tringbuf_get, (const void *)2);
305 zassert_true(ring_buf_is_empty(pbuf));
306 }
307
ZTEST(ringbuffer_api,test_ringbuffer_put_get_thread_isr)308 ZTEST(ringbuffer_api, test_ringbuffer_put_get_thread_isr)
309 {
310 pbuf = &ringbuf;
311 tringbuf_put((const void *)0);
312 irq_offload(tringbuf_put, (const void *)1);
313 tringbuf_get((const void *)0);
314 irq_offload(tringbuf_get, (const void *)1);
315 tringbuf_put((const void *)2);
316 irq_offload(tringbuf_get, (const void *)2);
317 }
318
ZTEST(ringbuffer_api,test_ringbuffer_put_get_discard)319 ZTEST(ringbuffer_api, test_ringbuffer_put_get_discard)
320 {
321 pbuf = &ringbuf;
322 tringbuf_put((const void *)0);
323 tringbuf_put((const void *)1);
324 zassert_false(ring_buf_is_empty(pbuf));
325 tringbuf_get_discard((const void *)0);
326 tringbuf_get_discard((const void *)1);
327 zassert_true(ring_buf_is_empty(pbuf));
328 }
329
330 /**
331 * @brief verify that ringbuffer can be placed in any user-controlled memory
332 *
333 * @details
334 * Test Objective:
335 * - define and initialize a ring buffer by macro RING_BUF_ITEM_DECLARE_POW2,
336 * then passing data by thread and isr to verify the ringbuffer
337 * if it works to be placed in any user-controlled memory.
338 *
339 * Testing techniques:
340 * - Interface testing
341 * - Dynamic analysis and testing
342 * - Structural test coverage(entry points,statements,branches)
343 *
344 * Prerequisite Conditions:
345 * - Define and initialize a ringbuffer by RING_BUF_ITEM_DECLARE_POW2
346 * - Define a pointer of ring_buffer type.
347 *
348 * Input Specifications:
349 * - N/A
350 *
351 * Test Procedure:
352 * -# Put data items into the ringbuffer by a thread
353 * -# Put data items into the ringbuffer by a ISR
354 * -# Get data items from the ringbuffer by the thread
355 * -# Check if data items pushed are equal to what are gotten.
356 * -# Get data items from the ringbuffer by the ISR
357 * -# Check if data items pushed are equal to what are gotten.
358 * -# Put data items into the ringbuffer by the thread
359 * -# Get data items from the ringbuffer by the ISR
360 * -# Check if data items pushed are equal to what are gotten.
361 *
362 * Expected Test Result:
363 * - data items pushed shall be equal to what are gotten.
364 *
365 * Pass/Fail Criteria:
366 * - Success if test result of step 4,6,9 is passed. Otherwise, failure.
367 *
368 * Assumptions and Constraints:
369 * - N/A
370 *
371 * @ingroup lib_ringbuffer_tests
372 *
373 * @see ring_buf_item_put, ring_buf_item_get
374 */
ZTEST(ringbuffer_api,test_ringbuffer_pow2_put_get_thread_isr)375 ZTEST(ringbuffer_api, test_ringbuffer_pow2_put_get_thread_isr)
376 {
377 pbuf = &ringbuf_pow2;
378 tringbuf_put((const void *)0);
379 irq_offload(tringbuf_put, (const void *)1);
380 tringbuf_get((const void *)0);
381 irq_offload(tringbuf_get, (const void *)1);
382 tringbuf_put((const void *)1);
383 irq_offload(tringbuf_get, (const void *)1);
384 }
385
386 /**
387 * @brief verify that ringbuffer can be placed in any user-controlled memory
388 *
389 * @details
390 * Test Objective:
391 * - define and initialize a ring buffer by macro RING_BUF_ITEM_DECLARE,
392 * then passing data by thread and isr to verify the ringbuffer
393 * if it works to be placed in any user-controlled memory.
394 *
395 * Testing techniques:
396 * - Interface testing
397 * - Dynamic analysis and testing
398 * - Structural test coverage(entry points,statements,branches)
399 *
400 * Prerequisite Conditions:
401 * - Define and initialize a ringbuffer by RING_BUF_ITEM_DECLARE
402 * - Define a pointer of ring buffer type.
403 *
404 * Input Specifications:
405 * - N/A
406 *
407 * Test Procedure:
408 * -# Put data items into the ringbuffer by a thread
409 * -# Put data items into the ringbuffer by a ISR
410 * -# Get data items from the ringbuffer by the thread
411 * -# Check if data items pushed are equal to what are gotten.
412 * -# Get data items from the ringbuffer by the ISR
413 * -# Check if data items pushed are equal to what are gotten.
414 * -# Put data items into the ringbuffer by the thread
415 * -# Get data items from the ringbuffer by the ISR
416 * -# Check if data items pushed are equal to what are gotten.
417 *
418 * Expected Test Result:
419 * - data items pushed shall be equal to what are gotten.
420 *
421 * Pass/Fail Criteria:
422 * - Success if test result of step 4,6,9 is passed. Otherwise, failure.
423 *
424 * Assumptions and Constraints:
425 * - N/A
426 *
427 * @ingroup lib_ringbuffer_tests
428 *
429 * @see ring_buf_item_put, ring_buf_item_get
430 */
ZTEST(ringbuffer_api,test_ringbuffer_size_put_get_thread_isr)431 ZTEST(ringbuffer_api, test_ringbuffer_size_put_get_thread_isr)
432 {
433 pbuf = &ringbuf_size;
434 tringbuf_put((const void *)0);
435 irq_offload(tringbuf_put, (const void *)1);
436 tringbuf_get((const void *)0);
437 irq_offload(tringbuf_get, (const void *)1);
438 tringbuf_put((const void *)2);
439 irq_offload(tringbuf_get, (const void *)2);
440 }
441
442 /**
443 * @brief verify that ringbuffer can be placed in any user-controlled memory
444 *
445 * @details
446 * Test Objective:
447 * - define and initialize a ring buffer by macro RING_BUF_DECLARE,
448 * then verify data is passed between ring buffer and array
449 *
450 * Testing techniques:
451 * - Interface testing
452 * - Dynamic analysis and testing
453 * - Structural test coverage(entry points,statements,branches)
454 *
455 * Prerequisite Conditions:
456 * - Define and initialize a ringbuffer by RING_BUF_DECLARE
457 *
458 * Input Specifications:
459 * - N/A
460 *
461 * Test Procedure:
462 * -# Define two arrays(inbuf,outbuf) and initialize inbuf
463 * -# Put and get data with "for loop"
464 * -# Check if data size pushed is equal to what are gotten.
465 * -# Then initialize the output buffer
466 * -# Put data with different size to check if data size
467 * pushed is equal to what are gotten.
468 *
469 * Expected Test Result:
470 * - data items pushed shall be equal to what are gotten.
471 *
472 * Pass/Fail Criteria:
473 * - Success if test result of step 4,5 is passed. Otherwise, failure.
474 *
475 * Assumptions and Constraints:
476 * - N/A
477 *
478 * @ingroup lib_ringbuffer_tests
479 *
480 * @see ring_buf_put, ring_buf_get
481 */
ZTEST(ringbuffer_api,test_ringbuffer_raw)482 ZTEST(ringbuffer_api, test_ringbuffer_raw)
483 {
484 int i;
485 uint8_t inbuf[RINGBUFFER_SIZE];
486 uint8_t outbuf[RINGBUFFER_SIZE];
487 size_t in_size;
488 size_t out_size;
489
490 /* Initialize test buffer. */
491 for (i = 0; i < RINGBUFFER_SIZE; i++) {
492 inbuf[i] = i;
493 }
494
495 for (i = 0; i < 10; i++) {
496 memset(outbuf, 0, sizeof(outbuf));
497 in_size = ring_buf_put(&ringbuf_raw, inbuf,
498 RINGBUFFER_SIZE - 2);
499 out_size = ring_buf_get(&ringbuf_raw, outbuf,
500 RINGBUFFER_SIZE - 2);
501
502 zassert_true(in_size == RINGBUFFER_SIZE - 2);
503 zassert_true(in_size == out_size);
504 zassert_true(memcmp(inbuf, outbuf, RINGBUFFER_SIZE - 2) == 0,
505 NULL);
506 }
507
508 memset(outbuf, 0, sizeof(outbuf));
509 in_size = ring_buf_put(&ringbuf_raw, inbuf,
510 RINGBUFFER_SIZE);
511 zassert_equal(in_size, RINGBUFFER_SIZE);
512
513 in_size = ring_buf_put(&ringbuf_raw, inbuf,
514 1);
515 zassert_equal(in_size, 0);
516
517 out_size = ring_buf_get(&ringbuf_raw, outbuf,
518 RINGBUFFER_SIZE);
519
520 zassert_true(out_size == RINGBUFFER_SIZE);
521
522 out_size = ring_buf_get(&ringbuf_raw, outbuf,
523 RINGBUFFER_SIZE + 1);
524 zassert_true(out_size == 0);
525 zassert_true(ring_buf_is_empty(&ringbuf_raw));
526
527 /* Validate that raw bytes can be discarded */
528 in_size = ring_buf_put(&ringbuf_raw, inbuf,
529 RINGBUFFER_SIZE);
530 zassert_equal(in_size, RINGBUFFER_SIZE);
531
532 out_size = ring_buf_get(&ringbuf_raw, NULL,
533 RINGBUFFER_SIZE);
534 zassert_true(out_size == RINGBUFFER_SIZE);
535
536 out_size = ring_buf_get(&ringbuf_raw, NULL,
537 RINGBUFFER_SIZE + 1);
538 zassert_true(out_size == 0);
539 zassert_true(ring_buf_is_empty(&ringbuf_raw));
540 }
541
ZTEST(ringbuffer_api,test_ringbuffer_alloc_put)542 ZTEST(ringbuffer_api, test_ringbuffer_alloc_put)
543 {
544 uint8_t outputbuf[RINGBUFFER_SIZE];
545 uint8_t inputbuf[] = {1, 2, 3, 4};
546 uint32_t read_size;
547 uint32_t allocated;
548 uint8_t *data;
549 int err;
550
551 ring_buf_init(&ringbuf_raw, RINGBUFFER_SIZE, ringbuf_raw.buffer);
552
553 allocated = ring_buf_put_claim(&ringbuf_raw, &data, 1);
554 zassert_true(allocated == 1U);
555
556
557 allocated = ring_buf_put_claim(&ringbuf_raw, &data,
558 RINGBUFFER_SIZE - 1);
559 zassert_true(allocated == RINGBUFFER_SIZE - 1);
560
561 /* Putting too much returns error */
562 err = ring_buf_put_finish(&ringbuf_raw, RINGBUFFER_SIZE + 1);
563 zassert_true(err != 0);
564
565 err = ring_buf_put_finish(&ringbuf_raw, 1);
566 zassert_true(err == 0);
567
568 err = ring_buf_put_finish(&ringbuf_raw, RINGBUFFER_SIZE - 1);
569 zassert_true(err == -EINVAL);
570
571 read_size = ring_buf_get(&ringbuf_raw, outputbuf,
572 RINGBUFFER_SIZE);
573 zassert_true(read_size == 1);
574
575 for (int i = 0; i < 10; i++) {
576 allocated = ring_buf_put_claim(&ringbuf_raw, &data, 2);
577 if (allocated == 2U) {
578 data[0] = inputbuf[0];
579 data[1] = inputbuf[1];
580 } else {
581 data[0] = inputbuf[0];
582 ring_buf_put_claim(&ringbuf_raw, &data, 1);
583 data[0] = inputbuf[1];
584 }
585
586 allocated = ring_buf_put_claim(&ringbuf_raw, &data, 2);
587 if (allocated == 2U) {
588 data[0] = inputbuf[2];
589 data[1] = inputbuf[3];
590 } else {
591 data[0] = inputbuf[2];
592 ring_buf_put_claim(&ringbuf_raw, &data, 1);
593 data[0] = inputbuf[3];
594 }
595
596 err = ring_buf_put_finish(&ringbuf_raw, 4);
597 zassert_true(err == 0);
598
599 read_size = ring_buf_get(&ringbuf_raw,
600 outputbuf, 4);
601 zassert_true(read_size == 4U);
602
603 zassert_true(memcmp(outputbuf, inputbuf, 4) == 0);
604 }
605 }
606
ZTEST(ringbuffer_api,test_byte_put_free)607 ZTEST(ringbuffer_api, test_byte_put_free)
608 {
609 uint8_t indata[] = {1, 2, 3, 4, 5};
610 int err;
611 uint32_t granted;
612 uint8_t *data;
613
614 ring_buf_init(&ringbuf_raw, RINGBUFFER_SIZE, ringbuf_raw.buffer);
615
616 /* Ring buffer is empty */
617 granted = ring_buf_get_claim(&ringbuf_raw, &data, RINGBUFFER_SIZE);
618 zassert_true(granted == 0U);
619
620 for (int i = 0; i < 10; i++) {
621 ring_buf_put(&ringbuf_raw, indata,
622 RINGBUFFER_SIZE-2);
623
624 granted = ring_buf_get_claim(&ringbuf_raw, &data,
625 RINGBUFFER_SIZE);
626
627 if (granted == (RINGBUFFER_SIZE-2)) {
628 zassert_true(memcmp(indata, data, granted) == 0);
629 } else if (granted < (RINGBUFFER_SIZE-2)) {
630 /* When buffer wraps, operation is split. */
631 uint32_t granted_1 = granted;
632
633 zassert_true(memcmp(indata, data, granted) == 0);
634 granted = ring_buf_get_claim(&ringbuf_raw, &data,
635 RINGBUFFER_SIZE);
636
637 zassert_true((granted + granted_1) ==
638 RINGBUFFER_SIZE - 2, NULL);
639 zassert_true(memcmp(&indata[granted_1], data, granted)
640 == 0, NULL);
641 } else {
642 zassert_true(false);
643 }
644
645 /* Freeing more than possible case. */
646 err = ring_buf_get_finish(&ringbuf_raw, RINGBUFFER_SIZE-1);
647 zassert_true(err != 0);
648
649 err = ring_buf_get_finish(&ringbuf_raw, RINGBUFFER_SIZE-2);
650 zassert_true(err == 0);
651 }
652 }
653
ZTEST(ringbuffer_api,test_capacity)654 ZTEST(ringbuffer_api, test_capacity)
655 {
656 uint32_t capacity;
657
658 ring_buf_init(&ringbuf_raw, RINGBUFFER_SIZE, ringbuf_raw.buffer);
659
660 capacity = ring_buf_capacity_get(&ringbuf_raw);
661 zassert_equal(RINGBUFFER_SIZE, capacity,
662 "Unexpected capacity");
663 }
664
ZTEST(ringbuffer_api,test_size)665 ZTEST(ringbuffer_api, test_size)
666 {
667 uint32_t size;
668 static uint8_t buf[RINGBUFFER_SIZE];
669
670 ring_buf_init(&ringbuf_raw, sizeof(buf), ringbuf_raw.buffer);
671
672 /* Test 0 */
673 size = ring_buf_size_get(&ringbuf_raw);
674 zassert_equal(0, size, "wrong size: exp: %u act: %u", 0, size);
675
676 /* Test 1 */
677 ring_buf_put(&ringbuf_raw, "x", 1);
678 size = ring_buf_size_get(&ringbuf_raw);
679 zassert_equal(1, size, "wrong size: exp: %u act: %u", 1, size);
680
681 /* Test N */
682 ring_buf_reset(&ringbuf_raw);
683 ring_buf_put(&ringbuf_raw, buf, sizeof(buf));
684 size = ring_buf_size_get(&ringbuf_raw);
685 zassert_equal(sizeof(buf), size, "wrong size: exp: %u: actual: %u", sizeof(buf), size);
686
687 /* Test N - 2 with wrap-around */
688 ring_buf_put(&ringbuf_raw, buf, sizeof(buf));
689 ring_buf_get(&ringbuf_raw, NULL, 3);
690 ring_buf_put(&ringbuf_raw, "x", 1);
691
692 size = ring_buf_size_get(&ringbuf_raw);
693 zassert_equal(sizeof(buf) - 2, size, "wrong size: exp: %u: actual: %u", sizeof(buf) - 2,
694 size);
695 }
696
ZTEST(ringbuffer_api,test_peek)697 ZTEST(ringbuffer_api, test_peek)
698 {
699 uint32_t size;
700 uint8_t byte = 0x42;
701 static uint8_t buf[RINGBUFFER_SIZE];
702
703 ring_buf_init(&ringbuf_raw, sizeof(buf), ringbuf_raw.buffer);
704
705 /* Test 0 */
706 size = ring_buf_peek(&ringbuf_raw, (uint8_t *)0x1, 42424242);
707 zassert_equal(0, size, "wrong peek size: exp: %u: actual: %u", 0, size);
708
709 /* Test 1 */
710 ring_buf_put(&ringbuf_raw, "*", 1);
711 size = ring_buf_peek(&ringbuf_raw, &byte, 1);
712 zassert_equal(1, size, "wrong peek size: exp: %u: actual: %u", 1, size);
713 zassert_equal('*', byte, "wrong buffer contents: exp: %u: actual: %u", '*', byte);
714 size = ring_buf_size_get(&ringbuf_raw);
715 zassert_equal(1, size, "wrong buffer size: exp: %u: actual: %u", 1, size);
716
717 /* Test N */
718 ring_buf_reset(&ringbuf_raw);
719 for (size = 0; size < sizeof(buf); ++size) {
720 buf[size] = 'A' + (size % ('Z' - 'A' + 1));
721 }
722
723 ring_buf_put(&ringbuf_raw, buf, sizeof(buf));
724 memset(buf, '*', sizeof(buf)); /* fill with pattern */
725
726 size = ring_buf_peek(&ringbuf_raw, buf, sizeof(buf));
727 zassert_equal(sizeof(buf), size, "wrong peek size: exp: %u: actual: %u", sizeof(buf), size);
728 size = ring_buf_size_get(&ringbuf_raw);
729 zassert_equal(sizeof(buf), size, "wrong buffer size: exp: %u: actual: %u", sizeof(buf),
730 size);
731
732 for (size = 0; size < sizeof(buf); ++size) {
733 ringbuf_raw.buffer[size] = 'A' + (size % ('Z' - 'A' + 1));
734 }
735
736 zassert_equal(0, memcmp(buf, ringbuf_raw.buffer, sizeof(buf)),
737 "content validation failed");
738 }
739
ZTEST(ringbuffer_api,test_reset)740 ZTEST(ringbuffer_api, test_reset)
741 {
742 uint8_t indata[] = {1, 2, 3, 4, 5};
743 uint8_t outdata[RINGBUFFER_SIZE];
744 uint8_t *outbuf;
745 uint32_t len;
746 uint32_t out_len;
747 uint32_t granted;
748 uint32_t space;
749
750 ring_buf_init(&ringbuf_raw, RINGBUFFER_SIZE, ringbuf_raw.buffer);
751
752 len = 3;
753 out_len = ring_buf_put(&ringbuf_raw, indata, len);
754 zassert_equal(out_len, len);
755
756 out_len = ring_buf_get(&ringbuf_raw, outdata, len);
757 zassert_equal(out_len, len);
758
759 space = ring_buf_space_get(&ringbuf_raw);
760 zassert_equal(space, RINGBUFFER_SIZE);
761
762 /* Even though ringbuffer is empty, full buffer cannot be allocated
763 * because internal pointers are not at the beginning.
764 */
765 granted = ring_buf_put_claim(&ringbuf_raw, &outbuf, RINGBUFFER_SIZE);
766 zassert_false(granted == RINGBUFFER_SIZE);
767
768 /* After reset full buffer can be allocated. */
769 ring_buf_reset(&ringbuf_raw);
770 granted = ring_buf_put_claim(&ringbuf_raw, &outbuf, RINGBUFFER_SIZE);
771 zassert_true(granted == RINGBUFFER_SIZE);
772 }
773
774 static uint32_t ringbuf_stored[RINGBUFFER_SIZE];
775
776 /**
777 * @brief verify the array stored by ringbuf
778 *
779 * @details
780 * Test Objective:
781 * - Define a buffer stored by ringbuffer. Verify that the address
782 * of the buffer is contiguous.And also verify that data can pass
783 * between buffer and ringbuffer.
784 *
785 * Testing techniques:
786 * - Interface testing
787 * - Dynamic analysis and testing
788 * - Structural test coverage(entry points,statements,branches)
789 *
790 * Prerequisite Conditions:
791 * - Define an array that changes as the system changes.
792 *
793 * Input Specifications:
794 * - N/A
795 *
796 * Test Procedure:
797 * -# Define two buffers(input and output)
798 * -# Put data from input buffer into the ringbuffer
799 * and check if put data are successful.
800 * -# Check if the address stored by ringbuf is contiguous.
801 * -# Get data from the ringbuffer and put them into output buffer
802 * and check if getting data are successful.
803 *
804 * Expected Test Result:
805 * - All assertions can pass.
806 *
807 * Pass/Fail Criteria:
808 * - Success if test result of step 2,3,4,5 is passed. Otherwise, failure.
809 *
810 * Assumptions and Constraints:
811 * - N/A
812 *
813 * @ingroup lib_ringbuffer_tests
814 *
815 * @see ring_buf_item_put, ring_buf_item_get
816 */
ZTEST(ringbuffer_api,test_ringbuffer_array_perf)817 ZTEST(ringbuffer_api, test_ringbuffer_array_perf)
818 {
819 struct ring_buf buf_ii;
820 uint32_t input[3] = {0xaa, 0xbb, 0xcc};
821 uint32_t output[3] = {0};
822 uint16_t type = 0;
823 uint8_t value = 0, size = 3;
824
825 ring_buf_item_init(&buf_ii, RINGBUFFER_SIZE, ringbuf_stored);
826
827 /*Data from the beginning of the array can be copied into the ringbuf*/
828 zassert_true(ring_buf_item_put(&buf_ii, 1, 2, input, 3) == 0);
829
830 /*Verify the address stored by ringbuf is contiguous*/
831 for (int i = 0; i < 3; i++) {
832 uint32_t *buf32 = (uint32_t *)buf_ii.buffer;
833
834 zassert_equal(input[i], buf32[i+1]);
835 }
836
837 /*Data from the end of the ringbuf can be copied into the array*/
838 zassert_true(ring_buf_item_get(&buf_ii, &type, &value,
839 output, &size) == 0, NULL);
840
841 /*Verify the ringbuf defined is working*/
842 for (int i = 0; i < 3; i++) {
843 zassert_equal(input[i], output[i]);
844 }
845 }
846
ZTEST(ringbuffer_api,test_ringbuffer_partial_putting)847 ZTEST(ringbuffer_api, test_ringbuffer_partial_putting)
848 {
849 uint8_t indata[RINGBUFFER_SIZE];
850 uint8_t outdata[RINGBUFFER_SIZE];
851 uint32_t len;
852 uint32_t len2;
853 uint32_t req_len;
854 uint8_t *ptr;
855
856 ring_buf_reset(&ringbuf_raw);
857
858 for (int i = 0; i < 100; i++) {
859 req_len = (i % RINGBUFFER_SIZE) + 1;
860 len = ring_buf_put(&ringbuf_raw, indata, req_len);
861 zassert_equal(req_len, len);
862
863 len = ring_buf_get(&ringbuf_raw, outdata, req_len);
864 zassert_equal(req_len, len);
865
866 req_len = 2;
867 len = ring_buf_put_claim(&ringbuf_raw, &ptr, req_len);
868 zassert_equal(len, req_len);
869
870 req_len = RINGBUFFER_SIZE;
871 len = ring_buf_put_claim(&ringbuf_raw, &ptr, req_len);
872 len2 = ring_buf_put_claim(&ringbuf_raw, &ptr, req_len);
873 zassert_equal(len + len2, req_len - 2);
874
875 ring_buf_put_finish(&ringbuf_raw, req_len);
876
877 len = ring_buf_get(&ringbuf_raw, indata, req_len);
878 zassert_equal(len, req_len);
879 }
880 }
881
ZTEST(ringbuffer_api,test_ringbuffer_partial_getting)882 ZTEST(ringbuffer_api, test_ringbuffer_partial_getting)
883 {
884 uint8_t indata[RINGBUFFER_SIZE];
885 uint8_t outdata[RINGBUFFER_SIZE];
886 uint32_t len;
887 uint32_t len2;
888 uint32_t req_len;
889 uint8_t *ptr;
890
891 ring_buf_reset(&ringbuf_raw);
892
893 for (int i = 0; i < 100; i++) {
894 req_len = (i % RINGBUFFER_SIZE) + 1;
895 len = ring_buf_put(&ringbuf_raw, indata, req_len);
896 zassert_equal(req_len, len);
897
898 len = ring_buf_get(&ringbuf_raw, outdata, req_len);
899 zassert_equal(req_len, len);
900
901 req_len = sizeof(indata);
902 len = ring_buf_put(&ringbuf_raw, indata, req_len);
903 zassert_equal(req_len, len);
904
905 len = ring_buf_get_claim(&ringbuf_raw, &ptr, 2);
906 zassert_equal(len, 2);
907
908 len = ring_buf_get_claim(&ringbuf_raw, &ptr, RINGBUFFER_SIZE);
909 len2 = ring_buf_get_claim(&ringbuf_raw, &ptr, RINGBUFFER_SIZE);
910 zassert_equal(len + len2, RINGBUFFER_SIZE - 2);
911
912 ring_buf_get_finish(&ringbuf_raw, RINGBUFFER_SIZE);
913 }
914 }
915
ZTEST(ringbuffer_api,test_ringbuffer_equal_bufs)916 ZTEST(ringbuffer_api, test_ringbuffer_equal_bufs)
917 {
918 struct ring_buf buf_ii;
919 uint8_t *data;
920 uint32_t claimed;
921 uint8_t buf[8];
922 size_t halfsize = sizeof(buf)/2;
923
924 ring_buf_init(&buf_ii, sizeof(buf), buf);
925
926 for (int i = 0; i < 100; i++) {
927 claimed = ring_buf_put_claim(&buf_ii, &data, halfsize);
928 zassert_equal(claimed, halfsize);
929 ring_buf_put_finish(&buf_ii, claimed);
930
931 claimed = ring_buf_get_claim(&buf_ii, &data, halfsize);
932 zassert_equal(claimed, halfsize);
933 ring_buf_get_finish(&buf_ii, claimed);
934 }
935 }
936
ZTEST(ringbuffer_api,test_ringbuffer_performance)937 ZTEST(ringbuffer_api, test_ringbuffer_performance)
938 {
939 uint8_t buf[16];
940 static struct ring_buf rbuf;
941 uint8_t indata[16];
942 uint8_t outdata[16];
943 uint8_t *ptr;
944 uint32_t timestamp;
945 int loop = 1000;
946
947 ring_buf_init(&rbuf, sizeof(buf), buf);
948
949 /* Test performance of copy put get 1 byte */
950 timestamp = k_cycle_get_32();
951 for (int i = 0; i < loop; i++) {
952 ring_buf_put(&rbuf, indata, 1);
953 ring_buf_get(&rbuf, outdata, 1);
954 }
955 timestamp = k_cycle_get_32() - timestamp;
956 PRINT("1 byte put-get, avg cycles: %d\n", timestamp/loop);
957
958 /* Test performance of copy put get 1 byte */
959 ring_buf_reset(&rbuf);
960 timestamp = k_cycle_get_32();
961 for (int i = 0; i < loop; i++) {
962 ring_buf_put(&rbuf, indata, 4);
963 ring_buf_get(&rbuf, outdata, 4);
964 }
965 timestamp = k_cycle_get_32() - timestamp;
966 PRINT("4 byte put-get, avg cycles: %d\n", timestamp/loop);
967
968 /* Test performance of put claim finish 1 byte */
969 ring_buf_reset(&rbuf);
970 timestamp = k_cycle_get_32();
971 for (int i = 0; i < loop; i++) {
972 ring_buf_put_claim(&rbuf, &ptr, 1);
973 ring_buf_put_finish(&rbuf, 1);
974 ring_buf_get(&rbuf, outdata, 1);
975 }
976 timestamp = k_cycle_get_32() - timestamp;
977 PRINT("1 byte put claim-finish, avg cycles: %d\n", timestamp/loop);
978
979 /* Test performance of put claim finish 5 byte */
980 ring_buf_reset(&rbuf);
981 timestamp = k_cycle_get_32();
982 for (int i = 0; i < loop; i++) {
983 ring_buf_put_claim(&rbuf, &ptr, 5);
984 ring_buf_put_finish(&rbuf, 5);
985 ring_buf_get(&rbuf, outdata, 5);
986 }
987 timestamp = k_cycle_get_32() - timestamp;
988 PRINT("5 byte put claim-finish, avg cycles: %d\n", timestamp/loop);
989
990 /* Test performance of copy put claim finish 5 byte */
991 ring_buf_reset(&rbuf);
992 timestamp = k_cycle_get_32();
993 for (int i = 0; i < loop; i++) {
994 ring_buf_put(&rbuf, indata, 5);
995 ring_buf_get_claim(&rbuf, &ptr, 5);
996 ring_buf_get_finish(&rbuf, 5);
997 }
998 timestamp = k_cycle_get_32() - timestamp;
999 PRINT("5 byte get claim-finish, avg cycles: %d\n", timestamp/loop);
1000 }
1001
1002 /*test case main entry*/
1003 ZTEST_SUITE(ringbuffer_api, NULL, NULL, NULL, NULL, NULL);
1004