Skip to content

Commit 34c54a8

Browse files
committed
tests/lib/: ring_buffer test cases
Introducing basic tests for the new ring_buffer API. Moving the existing tests for the deprecated ringbuffer API to a separate directory ensuring both can be maintained and run independently. Signed-off-by: Måns Ansgariusson <[email protected]>
1 parent d1327c4 commit 34c54a8

File tree

10 files changed

+235
-0
lines changed

10 files changed

+235
-0
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
common:
2+
tags:
3+
- ring_buffer
4+
- circular_buffer
5+
ignore_faults: true
6+
timeout: 150
7+
8+
tests:
9+
libraries.ring_buffer:
10+
integration_platforms:
11+
- native_sim
12+
- native_sim/native/64
13+
14+
libraries.ring_buffer.concurrent:
15+
platform_allow: qemu_x86
16+
extra_configs:
17+
- CONFIG_SYS_CLOCK_TICKS_PER_SEC=100000
18+
integration_platforms:
19+
- qemu_x86
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(ringbuffer)
6+
7+
target_sources(app PRIVATE
8+
src/main.c
9+
)

tests/lib/ring_buffer/prj.conf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CONFIG_ZTEST=y
2+
3+
CONFIG_ENTROPY_GENERATOR=y
4+
CONFIG_TEST_RANDOM_GENERATOR=y
5+
CONFIG_RING_BUFFER=n

tests/lib/ring_buffer/src/main.c

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
* Copyright (c) Måns Ansgariusson 2025
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/ztest.h>
8+
#include <zephyr/random/random.h>
9+
#include <zephyr/sys/ring_buffer.h>
10+
11+
#include <zephyr/logging/log.h>
12+
LOG_MODULE_REGISTER(ring_buffer_test);
13+
14+
ZTEST_SUITE(ringbuffer_api, NULL, NULL, NULL, NULL, NULL);
15+
16+
ZTEST(ringbuffer_api, test_init)
17+
{
18+
uint8_t buffer[12];
19+
struct ring_buffer rb;
20+
21+
ring_buffer_init(&rb, buffer, sizeof(buffer));
22+
23+
zassert_true(rb.buffer == buffer, "Incorrect buffer pointer");
24+
zassert_true(ring_buffer_size(&rb) == 0, "No bytes should be available");
25+
zassert_true(ring_buffer_capacity(&rb) == sizeof(buffer), "capacity != input size");
26+
}
27+
28+
ZTEST(ringbuffer_api, test_io)
29+
{
30+
struct ring_buffer rb;
31+
uint8_t buffer[12];
32+
uint8_t input[12];
33+
uint8_t res[12];
34+
35+
sys_rand_get(input, sizeof(input));
36+
ring_buffer_init(&rb, buffer, sizeof(buffer));
37+
38+
zassert_true(sizeof(input) == ring_buffer_write(&rb, input, sizeof(input)),
39+
"Failed to write input to ring_buffer");
40+
zassert_true(ring_buffer_size(&rb) == sizeof(input),
41+
"ring_buffer should have written bytes available for reading");
42+
zassert_true(sizeof(res) == ring_buffer_read(&rb, res, sizeof(res)),
43+
"failed to read written bytes");
44+
zassert_true(!memcmp(input, res, sizeof(input)), "read != written");
45+
zassert_true(ring_buffer_size(&rb) == 0, "ring_buffer should be empty");
46+
}
47+
48+
ZTEST(ringbuffer_api, test_dma_io)
49+
{
50+
size_t read = 0;
51+
size_t written = 0;
52+
struct ring_buffer rb;
53+
uint8_t buffer[12];
54+
uint8_t input[12];
55+
uint8_t res[12];
56+
uint8_t *ref;
57+
58+
sys_rand_get(input, sizeof(input));
59+
ring_buffer_init(&rb, buffer, sizeof(buffer));
60+
61+
while (written < sizeof(input)) {
62+
size_t write_sz = MIN(ring_buffer_write_ptr(&rb, &ref), sizeof(input) - written);
63+
64+
zassert_true(write_sz > 0, "there should be space in the buffer");
65+
memcpy(ref, &input[written], write_sz);
66+
ring_buffer_commit(&rb, write_sz);
67+
written += write_sz;
68+
}
69+
70+
zassert_true(sizeof(input) == ring_buffer_size(&rb),
71+
"there should be written bytes available to read");
72+
73+
while (read < sizeof(res)) {
74+
size_t read_sz = MIN(ring_buffer_read_ptr(&rb, &ref), sizeof(input) - read);
75+
76+
zassert_true(read_sz > 0, "there should be data in the buffer");
77+
memcpy(&res[read], ref, read_sz);
78+
ring_buffer_consume(&rb, read_sz);
79+
read += read_sz;
80+
}
81+
82+
zassert_true(!memcmp(input, res, sizeof(input)), "read != written");
83+
zassert_true(ring_buffer_size(&rb) == 0, "no bytes should be available to read");
84+
}
85+
86+
#define MONOTONIC_MAX_VALUE ((((size_t)1) << (8 * sizeof(ring_buffer_index_t))) - 1)
87+
ZTEST(ringbuffer_api, test_index_overflow)
88+
{
89+
struct ring_buffer rb;
90+
uint8_t buffer[12];
91+
uint8_t input[12];
92+
uint8_t res[12];
93+
94+
sys_rand_get(input, sizeof(input));
95+
ring_buffer_init(&rb, buffer, sizeof(buffer));
96+
97+
/* Moving the monotonic counters to the end of their range. */
98+
rb.write_ptr = MONOTONIC_MAX_VALUE - 3;
99+
rb.read_ptr = MONOTONIC_MAX_VALUE - 3;
100+
101+
zassert_true(sizeof(input) == ring_buffer_write(&rb, input, sizeof(input)),
102+
"Failed to write input to ring_buffer");
103+
zassert_true(ring_buffer_size(&rb) == sizeof(input),
104+
"ring_buffer should have written bytes available for reading");
105+
zassert_true(sizeof(res) == ring_buffer_read(&rb, res, sizeof(res)),
106+
"failed to read written bytes");
107+
zassert_true(!memcmp(input, res, sizeof(input)), "read != written");
108+
zassert_true(ring_buffer_size(&rb) == 0, "ring_buffer should be empty");
109+
}
110+
111+
ZTEST(ringbuffer_api, test_stress)
112+
{
113+
struct ring_buffer rb;
114+
uint8_t buffer[12];
115+
uint8_t input[128];
116+
uint8_t res[128];
117+
size_t read = 0;
118+
size_t written = 0;
119+
size_t to_write;
120+
size_t to_read;
121+
122+
sys_rand_get(input, sizeof(input));
123+
ring_buffer_init(&rb, buffer, sizeof(buffer));
124+
125+
while (read < sizeof(input)) {
126+
to_write = MIN(sys_rand32_get() % (ring_buffer_space(&rb) + 1),
127+
sizeof(input) - written);
128+
zassert_true(ring_buffer_write(&rb, &input[written], to_write) == to_write,
129+
"Failed to write");
130+
written += to_write;
131+
132+
while (read < written) {
133+
to_read = MIN(sys_rand32_get() % (ring_buffer_size(&rb) + 1),
134+
written - read);
135+
zassert_true(ring_buffer_read(&rb, &res[read], to_read) == to_read,
136+
"Failed to read");
137+
read += to_read;
138+
}
139+
140+
}
141+
zassert_true(!memcmp(input, res, read), "read != written");
142+
}
143+
144+
ZTEST(ringbuffer_api, test_ringbuffer_performance)
145+
{
146+
struct ring_buffer rb;
147+
uint8_t buffer[12];
148+
uint8_t indata[16];
149+
uint8_t outdata[16];
150+
uint8_t *ptr;
151+
uint32_t timestamp;
152+
int loop = 1000;
153+
154+
ring_buffer_init(&rb, buffer, sizeof(buffer));
155+
156+
timestamp = k_cycle_get_32();
157+
for (int i = 0; i < loop; i++) {
158+
ring_buffer_write(&rb, indata, 1);
159+
ring_buffer_read(&rb, outdata, 1);
160+
}
161+
timestamp = k_cycle_get_32() - timestamp;
162+
LOG_INF("1 byte write+read, avg cycles: %d", timestamp/loop);
163+
164+
ring_buffer_reset(&rb);
165+
timestamp = k_cycle_get_32();
166+
for (int i = 0; i < loop; i++) {
167+
ring_buffer_write(&rb, indata, 4);
168+
ring_buffer_read(&rb, outdata, 4);
169+
}
170+
timestamp = k_cycle_get_32() - timestamp;
171+
LOG_INF("4 byte write+read, avg cycles: %d", timestamp/loop);
172+
173+
ring_buffer_reset(&rb);
174+
timestamp = k_cycle_get_32();
175+
for (int i = 0; i < loop; i++) {
176+
ring_buffer_write_ptr(&rb, &ptr);
177+
ring_buffer_commit(&rb, 1);
178+
ring_buffer_read(&rb, outdata, 1);
179+
}
180+
timestamp = k_cycle_get_32() - timestamp;
181+
LOG_INF("1 byte write_ptr+commit+read, avg cycles: %d", timestamp/loop);
182+
183+
ring_buffer_reset(&rb);
184+
timestamp = k_cycle_get_32();
185+
for (int i = 0; i < loop; i++) {
186+
ring_buffer_write_ptr(&rb, &ptr);
187+
ring_buffer_commit(&rb, 5);
188+
ring_buffer_read(&rb, outdata, 5);
189+
}
190+
timestamp = k_cycle_get_32() - timestamp;
191+
LOG_INF("5 byte write_ptr+commit+read, avg cycles: %d", timestamp/loop);
192+
193+
ring_buffer_reset(&rb);
194+
timestamp = k_cycle_get_32();
195+
for (int i = 0; i < loop; i++) {
196+
ring_buffer_write(&rb, indata, 5);
197+
ring_buffer_read_ptr(&rb, &ptr);
198+
ring_buffer_consume(&rb, 5);
199+
}
200+
timestamp = k_cycle_get_32() - timestamp;
201+
LOG_INF("5 byte write+read_ptr+consume, avg cycles: %d", timestamp/loop);
202+
}
File renamed without changes.

0 commit comments

Comments
 (0)