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