mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-25 23:06:15 +00:00
239 lines
5.2 KiB
C
239 lines
5.2 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright 2024 Google LLC
|
|
* Written by Simon Glass <sjg@chromium.org>
|
|
*/
|
|
|
|
#include <membuf.h>
|
|
#include <os.h>
|
|
#include <rand.h>
|
|
#include <string.h>
|
|
#include <test/lib.h>
|
|
#include <test/test.h>
|
|
#include <test/ut.h>
|
|
|
|
#define TEST_SIZE 16
|
|
#define TEST_COUNT 10000
|
|
|
|
static void membuf_zero(struct membuf *mb)
|
|
{
|
|
memset(mb->start, '\0', mb->end - mb->start);
|
|
}
|
|
|
|
static int membuf_check(struct unit_test_state *uts, struct membuf *mb,
|
|
int value)
|
|
{
|
|
/* head is out of range */
|
|
ut_assert(!(mb->head < mb->start || mb->head >= mb->end));
|
|
|
|
/* tail is out of range */
|
|
ut_assert(!(mb->tail < mb->start || mb->tail >= mb->end));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* write from 1 to test_size bytes, and check they come back OK */
|
|
static int lib_test_membuf_one(struct unit_test_state *uts)
|
|
{
|
|
char in[TEST_SIZE * 2], out[TEST_SIZE * 2];
|
|
struct membuf mb;
|
|
int size, ret, test_size, i;
|
|
|
|
ut_assertok(membuf_new(&mb, TEST_SIZE));
|
|
|
|
/* setup in test */
|
|
for (i = 0; i < TEST_SIZE; i++) {
|
|
in[i] = (i & 63) + '0';
|
|
in[i + TEST_SIZE] = in[i];
|
|
}
|
|
|
|
test_size = TEST_SIZE;
|
|
|
|
for (i = 1; i < TEST_COUNT; i++) {
|
|
membuf_zero(&mb);
|
|
size = rand() % test_size;
|
|
|
|
// now write patterns and check they come back OK
|
|
ret = membuf_put(&mb, in, 0);
|
|
ret = membuf_put(&mb, in, size);
|
|
ut_asserteq(size, ret);
|
|
|
|
ret = membuf_put(&mb, in, 0);
|
|
ut_assertok(membuf_check(uts, &mb, i));
|
|
|
|
ret = membuf_get(&mb, out, 0);
|
|
ret = membuf_get(&mb, out, size);
|
|
ut_asserteq(size, ret);
|
|
|
|
ret = membuf_get(&mb, out, 0);
|
|
ut_assertok(membuf_check(uts, &mb, i));
|
|
|
|
ut_asserteq_mem(in, out, size);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
LIB_TEST(lib_test_membuf_one, 0);
|
|
|
|
/* write random number of bytes, and check they come back OK */
|
|
static int lib_test_membuf_random(struct unit_test_state *uts)
|
|
{
|
|
char in[TEST_SIZE * 2];
|
|
char buf[TEST_SIZE * 2];
|
|
struct membuf mb;
|
|
int size, ret, test_size, i;
|
|
char *inptr, *outptr;
|
|
int max_avail, min_free;
|
|
|
|
ut_assertok(membuf_new(&mb, TEST_SIZE));
|
|
|
|
for (i = 0; i < TEST_SIZE; i++) {
|
|
in[i] = (i & 63) + '0';
|
|
in[i + TEST_SIZE] = in[i];
|
|
}
|
|
|
|
test_size = TEST_SIZE;
|
|
|
|
inptr = in;
|
|
outptr = in;
|
|
min_free = TEST_COUNT;
|
|
max_avail = 0;
|
|
membuf_zero(&mb);
|
|
for (i = 0; i < TEST_COUNT; i++) {
|
|
size = rand() % test_size;
|
|
|
|
if (membuf_free(&mb) < min_free)
|
|
min_free = membuf_free(&mb);
|
|
|
|
ret = membuf_put(&mb, inptr, size);
|
|
ut_assertok(membuf_check(uts, &mb, i));
|
|
inptr += ret;
|
|
if (inptr >= in + TEST_SIZE)
|
|
inptr -= TEST_SIZE;
|
|
|
|
size = rand() % (test_size - 1);
|
|
|
|
if (membuf_avail(&mb) > max_avail)
|
|
max_avail = membuf_avail(&mb);
|
|
|
|
ret = membuf_get(&mb, buf, size);
|
|
ut_assertok(membuf_check(uts, &mb, i));
|
|
ut_asserteq_mem(buf, outptr, ret);
|
|
|
|
outptr += ret;
|
|
if (outptr >= in + TEST_SIZE)
|
|
outptr -= TEST_SIZE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
LIB_TEST(lib_test_membuf_random, 0);
|
|
|
|
/* test membuf_extend() with split segments */
|
|
static int lib_test_membuf_extend(struct unit_test_state *uts)
|
|
{
|
|
char in[TEST_SIZE * 2];
|
|
char buf[TEST_SIZE * 2];
|
|
struct membuf mb;
|
|
int ret, test_size, i, cur;
|
|
char *data;
|
|
|
|
ut_assertok(membuf_new(&mb, TEST_SIZE));
|
|
|
|
for (i = 0; i < TEST_SIZE; i++) {
|
|
in[i] = (i & 63) + '0';
|
|
in[i + TEST_SIZE] = in[i];
|
|
}
|
|
|
|
test_size = TEST_SIZE - 1;
|
|
|
|
for (cur = 0; cur <= test_size; cur++) {
|
|
ut_assertok(membuf_new(&mb, TEST_SIZE));
|
|
|
|
membuf_zero(&mb);
|
|
|
|
/*
|
|
* add some bytes, then remove them - this will force the membuf
|
|
* to have data split into two segments when we fill it
|
|
*/
|
|
ret = membuf_putraw(&mb, TEST_SIZE / 2, true, &data);
|
|
membuf_getraw(&mb, ret, true, &data);
|
|
ut_asserteq(TEST_SIZE / 2, ret);
|
|
|
|
/* fill it */
|
|
ret = membuf_put(&mb, in, cur);
|
|
ut_assertok(membuf_check(uts, &mb, cur));
|
|
ut_asserteq(cur, ret);
|
|
|
|
/* extend the buffer */
|
|
ut_assertok(membuf_extend_by(&mb, TEST_SIZE, -1));
|
|
ut_assertok(membuf_check(uts, &mb, cur));
|
|
|
|
/* check our data is still there */
|
|
ret = membuf_get(&mb, buf, TEST_SIZE * 2);
|
|
ut_assertok(membuf_check(uts, &mb, cur));
|
|
ut_asserteq(cur, ret);
|
|
ut_asserteq_mem(in, buf, cur);
|
|
membuf_uninit(&mb);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
LIB_TEST(lib_test_membuf_extend, 0);
|
|
|
|
/* test membuf_readline() with generated data */
|
|
static int lib_test_membuf_readline(struct unit_test_state *uts)
|
|
{
|
|
char *buf;
|
|
int size, cur, i, ret, readptr, cmpptr;
|
|
struct membuf mb;
|
|
char *data;
|
|
char str[256];
|
|
char *s;
|
|
|
|
ut_assertok(membuf_new(&mb, 1024));
|
|
membuf_zero(&mb);
|
|
|
|
/* Use the README as test data */
|
|
ut_assertok(os_read_file("README", (void **)&buf, &size));
|
|
|
|
cur = 0;
|
|
readptr = 0;
|
|
cmpptr = 0;
|
|
for (i = 0; i < 100000; i++, cur += 1) {
|
|
/* fill the buffer with up to 'cur' bytes */
|
|
ret = membuf_putraw(&mb, cur, false, &data);
|
|
|
|
if (ret > 0) {
|
|
int can_read = min(ret, size - readptr);
|
|
|
|
memcpy(data, &buf[readptr], can_read);
|
|
readptr += can_read;
|
|
|
|
membuf_putraw(&mb, can_read, true, &data);
|
|
ut_assertok(membuf_check(uts, &mb, i));
|
|
}
|
|
|
|
/* read a line and compare */
|
|
ret = membuf_readline(&mb, str, 256, 0, true);
|
|
ut_assertok(membuf_check(uts, &mb, i));
|
|
if (ret) {
|
|
char *ptr;
|
|
|
|
s = &buf[cmpptr];
|
|
ptr = strchr(s, '\n');
|
|
*ptr = '\0';
|
|
|
|
ut_asserteq_str(s, str);
|
|
cmpptr += strlen(s) + 1;
|
|
*ptr = '\n';
|
|
} else {
|
|
ut_assert(membuf_free(&mb));
|
|
}
|
|
}
|
|
membuf_dispose(&mb);
|
|
os_free(buf);
|
|
|
|
return 0;
|
|
}
|
|
LIB_TEST(lib_test_membuf_readline, 0);
|