1 /*
2  * Copyright (c) 2021 Intel Corporation
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include <zephyr/ztest.h>
6 #include <zephyr/sys/winstream.h>
7 
8 /* This, uh, seems to be the standard way to unit test library code.
9  * Or so I gather from tests/unit/rbtree ...
10  */
11 #include "../../../lib/utils/winstream.c"
12 
13 #define BUFLEN 64
14 
15 const char *msg = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
16 char wsmem[BUFLEN + 1]; /* Extra 1 to have a null for easier debugging */
17 
ZTEST(winstream,test_winstream)18 ZTEST(winstream, test_winstream)
19 {
20 	struct sys_winstream *ws = sys_winstream_init(wsmem, BUFLEN);
21 
22 	/* Write one byte */
23 	sys_winstream_write(ws, "a", 1);
24 
25 	uint32_t seq = 0;
26 	char c;
27 
28 	/* Read the byte back */
29 	uint32_t bytes = sys_winstream_read(ws, &seq, &c, 1);
30 
31 	zassert_true(bytes == 1, "");
32 	zassert_true(seq == 1, "");
33 	zassert_true(c == 'a', "");
34 
35 	/* Read from an empty buffer */
36 	bytes = sys_winstream_read(ws, &seq, &c, 1);
37 	zassert_true(bytes == 0, "");
38 	zassert_true(seq == 1, "");
39 
40 	/* Write an overflowing string */
41 	sys_winstream_write(ws, msg, strlen(msg));
42 	zassert_true(ws->seq == 1 + strlen(msg), "");
43 	zassert_true(ws->start == 1, "");
44 	zassert_true(ws->end == 0, "");
45 
46 	/* Read after underflow, verify empty string comes back with the
47 	 * correct sequence number
48 	 */
49 	char readback[BUFLEN + 1];
50 
51 	memset(readback, 0, sizeof(readback));
52 	bytes = sys_winstream_read(ws, &seq, readback, sizeof(readback));
53 	zassert_true(seq == ws->seq, "");
54 	zassert_true(bytes == 0, "");
55 
56 	/* Read back from empty buffer */
57 	uint32_t seq0 = seq;
58 
59 	bytes = sys_winstream_read(ws, &seq, readback, sizeof(readback));
60 	zassert_true(seq == seq0, "");
61 	zassert_true(bytes == 0, "");
62 
63 	/* Write a "short-enough" string that fits in before the wrap,
64 	 * then read it out
65 	 */
66 	seq0 = seq;
67 	sys_winstream_write(ws, msg, ws->len / 2);
68 	bytes = sys_winstream_read(ws, &seq, readback, sizeof(readback));
69 	zassert_true(bytes == ws->len / 2, "");
70 	zassert_true(seq == seq0 + ws->len / 2, "");
71 	zassert_true(strncmp(readback, msg, ws->len / 2) == 0, "");
72 
73 	/* Do it again, this time it will need to wrap around the buffer */
74 	memset(readback, 0, sizeof(readback));
75 	seq0 = seq;
76 	sys_winstream_write(ws, msg, ws->len / 2);
77 	bytes = sys_winstream_read(ws, &seq, readback, sizeof(readback));
78 	zassert_true(bytes == ws->len / 2, "");
79 	zassert_true(seq == seq0 + ws->len / 2, "");
80 	zassert_true(strncmp(readback, msg, ws->len / 2) == 0, "");
81 
82 	/* Finally loop with a relatively prime (actually prime prime)
83 	 * buffer size to stress for edges.
84 	 */
85 	int n = 13;
86 	char msg2[13];
87 
88 	for (int i = 0; i < (n + 1) * (ws->len + 1); i++) {
89 		memset(msg2, 'A' + (i % 26), n);
90 		seq0 = seq;
91 		memset(readback, 0, sizeof(readback));
92 		sys_winstream_write(ws, msg2, n);
93 		bytes = sys_winstream_read(ws, &seq, readback, sizeof(readback));
94 		zassert_true(bytes == n, "");
95 		zassert_true(seq == seq0 + n, "");
96 		zassert_true(strncmp(readback, msg2, n) == 0, "");
97 	}
98 }
99 
100 ZTEST_SUITE(winstream, NULL, NULL, NULL, NULL, NULL);
101