tests: lib: spsc_pbuf: Improve stress test

Improve stress tests to be more robust and demanding. Previous
implementation did not reveal race condition.

Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruscinski 2022-08-22 14:27:20 +02:00 committed by Fabio Baltieri
parent 6928c4a546
commit 716fa446cd

View File

@ -11,6 +11,7 @@
#define HDR_LEN sizeof(uint32_t)
#define TLEN(len) ROUND_UP(HDR_LEN + len, sizeof(uint32_t))
#define STRESS_TIMEOUT_MS ((CONFIG_SYS_CLOCK_TICKS_PER_SEC < 10000) ? 1000 : 15000)
/* The buffer size itself would be 199 bytes.
* 212 - sizeof(struct spsc_pbuf) - 1 = 199.
@ -415,6 +416,7 @@ struct stress_data {
uint32_t capacity;
uint32_t write_cnt;
uint32_t read_cnt;
uint32_t wr_err;
};
bool stress_read(void *user_data, uint32_t cnt, bool last, int prio)
@ -422,20 +424,22 @@ bool stress_read(void *user_data, uint32_t cnt, bool last, int prio)
struct stress_data *ctx = (struct stress_data *)user_data;
char buf[128];
int len;
int rpt = (sys_rand32_get() & 3) + 1;
len = spsc_pbuf_read(ctx->pbuf, buf, (uint16_t)sizeof(buf));
for (int i = 0; i < rpt; i++) {
len = spsc_pbuf_read(ctx->pbuf, buf, (uint16_t)sizeof(buf));
if (len == 0) {
return true;
}
if (len == 0) {
return true;
if (len < 0) {
zassert_true(false, "Unexpected error: %d, cnt:%d", len, ctx->read_cnt);
}
check_buffer(buf, len, ctx->read_cnt);
ctx->read_cnt++;
}
if (len < 0) {
zassert_true(false, "Unexpected error: %d, cnt:%d", len, ctx->read_cnt);
}
check_buffer(buf, len, ctx->read_cnt);
ctx->read_cnt++;
return true;
}
@ -444,36 +448,41 @@ bool stress_write(void *user_data, uint32_t cnt, bool last, int prio)
struct stress_data *ctx = (struct stress_data *)user_data;
char buf[128];
uint16_t len = 1 + (sys_rand32_get() % (ctx->capacity / 4));
int rpt = (sys_rand32_get() & 1) + 1;
zassert_true(len < sizeof(buf), "len:%d %d", len, ctx->capacity);
memset(buf, (uint8_t)ctx->write_cnt, len);
if (spsc_pbuf_write(ctx->pbuf, buf, len) == 0) {
ctx->write_cnt++;
for (int i = 0; i < rpt; i++) {
memset(buf, (uint8_t)ctx->write_cnt, len);
if (spsc_pbuf_write(ctx->pbuf, buf, len) == len) {
ctx->write_cnt++;
} else {
ctx->wr_err++;
}
}
return true;
}
ZTEST(test_spsc_pbuf, test_stress)
{
static uint8_t buffer[128] __aligned(MAX(Z_SPSC_PBUF_DCACHE_LINE, 4));
static struct stress_data ctx;
static struct stress_data ctx = {};
uint32_t repeat = 0;
ctx.write_cnt = 0;
ctx.read_cnt = 0;
ctx.pbuf = spsc_pbuf_init(buffer, sizeof(buffer), 0);
ctx.capacity = spsc_pbuf_capacity(ctx.pbuf);
ztress_set_timeout(K_MSEC(5000));
ZTRESS_EXECUTE(ZTRESS_THREAD(stress_read, &ctx, repeat, 0, Z_TIMEOUT_TICKS(4)),
ZTRESS_THREAD(stress_write, &ctx, repeat, 1000, Z_TIMEOUT_TICKS(4)));
ztress_set_timeout(K_MSEC(STRESS_TIMEOUT_MS));
TC_PRINT("Reading from an interrupt, writing from a thread\n");
ZTRESS_EXECUTE(ZTRESS_TIMER(stress_read, &ctx, repeat, Z_TIMEOUT_TICKS(4)),
ZTRESS_THREAD(stress_write, &ctx, repeat, 2000, Z_TIMEOUT_TICKS(4)));
TC_PRINT("Writes:%d failures: %d\n", ctx.write_cnt, ctx.wr_err);
ZTRESS_EXECUTE(ZTRESS_THREAD(stress_write, &ctx, repeat, 0, Z_TIMEOUT_TICKS(4)),
TC_PRINT("Writing from an interrupt, reading from a thread\n");
ZTRESS_EXECUTE(ZTRESS_TIMER(stress_write, &ctx, repeat, Z_TIMEOUT_TICKS(4)),
ZTRESS_THREAD(stress_read, &ctx, repeat, 1000, Z_TIMEOUT_TICKS(4)));
TC_PRINT("Writes:%d failures: %d\n", ctx.write_cnt, ctx.wr_err);
}
bool stress_claim_free(void *user_data, uint32_t cnt, bool last, int prio)
@ -481,40 +490,47 @@ bool stress_claim_free(void *user_data, uint32_t cnt, bool last, int prio)
struct stress_data *ctx = (struct stress_data *)user_data;
char *buf;
uint16_t len;
int rpt = sys_rand32_get() % 0x3;
len = spsc_pbuf_claim(ctx->pbuf, &buf);
for (int i = 0; i < rpt; i++) {
len = spsc_pbuf_claim(ctx->pbuf, &buf);
if (len == 0) {
return true;
if (len == 0) {
return true;
}
check_buffer(buf, len, ctx->read_cnt);
spsc_pbuf_free(ctx->pbuf, len);
ctx->read_cnt++;
}
check_buffer(buf, len, ctx->read_cnt);
spsc_pbuf_free(ctx->pbuf, len);
ctx->read_cnt++;
return true;
}
bool stress_alloc_commit(void *user_data, uint32_t cnt, bool last, int prio)
{
struct stress_data *ctx = (struct stress_data *)user_data;
uint16_t len = 1 + (sys_rand32_get() % (ctx->capacity / 4));
uint32_t rnd = sys_rand32_get();
uint16_t len = 1 + (rnd % (ctx->capacity / 4));
int rpt = rnd % 0x3;
char *buf;
int err;
err = spsc_pbuf_alloc(ctx->pbuf, len, &buf);
zassert_true(err >= 0, NULL);
if (err != len) {
return true;
for (int i = 0; i < rpt; i++) {
err = spsc_pbuf_alloc(ctx->pbuf, len, &buf);
zassert_true(err >= 0, NULL);
if (err != len) {
return true;
}
memset(buf, (uint8_t)ctx->write_cnt, len);
spsc_pbuf_commit(ctx->pbuf, len);
ctx->write_cnt++;
}
memset(buf, (uint8_t)ctx->write_cnt, len);
spsc_pbuf_commit(ctx->pbuf, len);
ctx->write_cnt++;
return true;
}
@ -529,7 +545,7 @@ ZTEST(test_spsc_pbuf, test_stress_0cpy)
ctx.pbuf = spsc_pbuf_init(buffer, sizeof(buffer), 0);
ctx.capacity = spsc_pbuf_capacity(ctx.pbuf);
ztress_set_timeout(K_MSEC(5000));
ztress_set_timeout(K_MSEC(STRESS_TIMEOUT_MS));
ZTRESS_EXECUTE(ZTRESS_THREAD(stress_claim_free, &ctx, repeat, 0, Z_TIMEOUT_TICKS(4)),
ZTRESS_THREAD(stress_alloc_commit, &ctx, repeat, 1000, Z_TIMEOUT_TICKS(4)));