1 /*
2  * Copyright (c) 2016 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <assert.h>
9 #include <lk/debug.h>
10 #include <lk/err.h>
11 #include <lib/cbuf.h>
12 #include <lk/console_cmd.h>
13 #include <lib/heap.h>
14 #include <rand.h>
15 #include <app/tests.h>
16 #include <stdlib.h>
17 
18 #define ASSERT_EQ(a, b)                                            \
19     do {                                                           \
20         typeof(a) _a = (a);                                        \
21         typeof(b) _b = (b);                                        \
22         if (_a != _b) {                                            \
23             panic("%lu != %lu (%s:%d)\n", (ulong)a, (ulong)b, __FILE__, __LINE__); \
24         }                                                          \
25     } while (0);
26 
27 #define ASSERT_LEQ(a, b)                                               \
28     do {                                                               \
29         typeof(a) _a = (a);                                            \
30         typeof(b) _b = (b);                                            \
31         if (_a > _b) {                                                 \
32             panic("%lu not <= %lu (%s:%d)\n", (ulong)a, (ulong)b, __FILE__, __LINE__); \
33         }                                                              \
34     } while (0);
35 
cbuf_tests(int argc,const console_cmd_args * argv)36 int cbuf_tests(int argc, const console_cmd_args *argv) {
37     cbuf_t cbuf;
38 
39     printf("running basic tests...\n");
40 
41     cbuf_initialize(&cbuf, 16);
42 
43     ASSERT_EQ(15UL, cbuf_space_avail(&cbuf));
44 
45     ASSERT_EQ(8UL, cbuf_write(&cbuf, "abcdefgh", 8, false));
46 
47     ASSERT_EQ(7UL, cbuf_space_avail(&cbuf));
48 
49     // Only 7 bytes should fit since if we write all 16 bytes,
50     // head == tail and we can't distinguish it from the start case.
51     ASSERT_EQ(7UL, cbuf_write(&cbuf, "ijklmnop", 8, false));
52 
53     ASSERT_EQ(0UL, cbuf_space_avail(&cbuf));
54 
55     // Nothing should fit.
56     ASSERT_EQ(0UL, cbuf_write(&cbuf, "XXXXXXXX", 8, false));
57 
58     ASSERT_EQ(0UL, cbuf_space_avail(&cbuf));
59 
60     // Read a few bytes.
61     {
62         char buf[32];
63         ASSERT_EQ(3UL, cbuf_read(&cbuf, buf, 3, false));
64         for (int i = 0; i < 3; ++i) {
65             ASSERT_EQ(buf[i], 'a' + i);
66         }
67 
68         // Try reading 32 bytes.
69         ASSERT_EQ(12UL, cbuf_read(&cbuf, buf, 32, false));
70         for (int i = 0; i < 12; ++i) {
71             ASSERT_EQ(buf[i], 'd' + i);
72         }
73     }
74 
75     cbuf_reset(&cbuf);
76 
77     ASSERT_EQ(15UL, cbuf_space_avail(&cbuf));
78 
79     // Random tests. Keep writing in random chunks up to 8 bytes, then
80     // reading in chunks up to 8 bytes. Verify values.
81 
82     int pos_out = 0;
83     int pos_in = 0;
84     printf("running random tests...\n");
85     while (pos_in < 256) {
86         if (pos_out < 256) {
87             // Write up to 8 bytes.
88             char buf_out[8];
89             int to_write_random = rand() & 7;
90             int to_write = MIN(to_write_random, 256 - pos_out);
91             for (int i = 0; i < to_write; ++i) {
92                 buf_out[i] = pos_out + i;
93             }
94             // Advance the out pointer based on how many bytes fit.
95             int wrote = cbuf_write(&cbuf, buf_out, to_write, false);
96             ASSERT_LEQ(wrote, to_write);
97             pos_out += wrote;
98         }
99 
100         // Read up to 8 bytes, make sure they are right.
101         if (pos_in < pos_out) {
102             char buf_in[8];
103             int to_read_random = rand() & 7;
104             int to_read = MIN(to_read_random, pos_out - pos_in);
105             int read = cbuf_read(&cbuf, buf_in, to_read, false);
106             ASSERT_LEQ(read, to_read);
107 
108             for (int i = 0; i < read; ++i) {
109                 ASSERT_EQ(pos_in + i, buf_in[i]);
110             }
111 
112             pos_in += read;
113         }
114 
115         ASSERT_LEQ(pos_in, pos_out);
116     }
117 
118     free(cbuf.buf);
119 
120     printf("cbuf tests passed\n");
121 
122     return NO_ERROR;
123 }
124