1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /** @file
8 * @brief Interactive shell test suite
9 *
10 */
11
12 #include <zephyr/kernel.h>
13 #include <zephyr/ztest.h>
14
15 #include <zephyr/shell/shell_history.h>
16
17 #define HIST_BUF_SIZE 160
18 Z_SHELL_HISTORY_DEFINE(history, HIST_BUF_SIZE);
19
init_test_buf(uint8_t * buf,size_t len,uint8_t offset)20 static void init_test_buf(uint8_t *buf, size_t len, uint8_t offset)
21 {
22 for (int i = 0; i < len; i++) {
23 buf[i] = offset + i;
24 }
25 }
26
27 /**
28 * Function tests getting line from history and compares it against expected
29 * result.
30 */
test_get(bool ok,bool up,uint8_t * exp_buf,uint16_t exp_len)31 static void test_get(bool ok, bool up, uint8_t *exp_buf, uint16_t exp_len)
32 {
33 bool res;
34 uint8_t out_buf[HIST_BUF_SIZE];
35 uint16_t out_len;
36
37 out_len = sizeof(out_buf);
38
39 res = z_shell_history_get(&history, up, out_buf, &out_len);
40
41 if (ok) {
42 zassert_true(res, "history should contain one entry.\n");
43
44 zassert_equal(out_len, exp_len, "Unexpected entry length.\n");
45 if (out_len) {
46 zassert_equal(memcmp(out_buf, exp_buf, out_len), 0,
47 "Expected equal buffers.\n");
48 }
49 } else {
50 zassert_false(res, "History should return nothing.\n");
51 }
52 }
53
54 /* Test put line to history and get it.
55 *
56 * Test steps:
57 * - initialize history.
58 * - put line to the history.
59 * - read line and verify that it is the one that was put.
60 */
ZTEST(shell_test,test_history_add_get)61 ZTEST(shell_test, test_history_add_get)
62 {
63 uint8_t exp_buf[HIST_BUF_SIZE];
64
65 init_test_buf(exp_buf, sizeof(exp_buf), 0);
66
67 z_shell_history_init(&history);
68
69 test_get(false, true, NULL, 0);
70
71 z_shell_history_put(&history, exp_buf, 20);
72
73 test_get(true, true, exp_buf, 20);
74
75 z_shell_history_purge(&history);
76 }
77
78 /* Test verifies that after purging there is no line in the history. */
ZTEST(shell_test,test_history_purge)79 ZTEST(shell_test, test_history_purge)
80 {
81 uint8_t exp_buf[HIST_BUF_SIZE];
82
83 init_test_buf(exp_buf, sizeof(exp_buf), 0);
84
85 z_shell_history_init(&history);
86
87 z_shell_history_put(&history, exp_buf, 20);
88 z_shell_history_put(&history, exp_buf, 20);
89
90 z_shell_history_purge(&history);
91
92 test_get(false, true, NULL, 0);
93 }
94
95 /* Test browsing history.
96 *
97 * Test steps:
98 * - initialize history.
99 * - put lines 1,2,3 to history.
100 * - get in up direction a line and verify that it's the last one added (3).
101 * - get next line in up direction and verify that it's line 2.
102 * - get next line in up direction and verify that it's line 1.
103 * - get next line in down direction and verify that it's line 2.
104 * - get next line in up direction and verify that it's line 1.
105 * - get next line in down direction and verify that it's line 2.
106 * - get next line in down direction and verify that it's line 3.
107 * - attempt to get next line in down direction and verify that there is no
108 * line.
109 */
ZTEST(shell_test,test_history_get_up_and_down)110 ZTEST(shell_test, test_history_get_up_and_down)
111 {
112 uint8_t exp1_buf[HIST_BUF_SIZE];
113 uint8_t exp2_buf[HIST_BUF_SIZE];
114 uint8_t exp3_buf[HIST_BUF_SIZE];
115
116 init_test_buf(exp1_buf, sizeof(exp1_buf), 0);
117 init_test_buf(exp2_buf, sizeof(exp2_buf), 10);
118 init_test_buf(exp3_buf, sizeof(exp3_buf), 20);
119
120 z_shell_history_init(&history);
121
122 z_shell_history_put(&history, exp1_buf, 20);
123 z_shell_history_put(&history, exp2_buf, 15);
124 z_shell_history_put(&history, exp3_buf, 20);
125
126 test_get(true, true, exp3_buf, 20); /* up - 3*/
127 test_get(true, true, exp2_buf, 15); /* up - 2*/
128 test_get(true, true, exp1_buf, 20); /* up - 1*/
129 test_get(true, false, exp2_buf, 15); /* down - 2 */
130 test_get(true, true, exp1_buf, 20); /* up - 1*/
131 test_get(true, false, exp2_buf, 15); /* down - 2 */
132 test_get(true, false, exp3_buf, 20); /* down - 3 */
133 test_get(false, false, NULL, 0); /* down - nothing */
134
135 z_shell_history_purge(&history);
136 }
137
138 /* Function for getting maximal buffer size that can be stored in the history */
get_max_buffer_len(void)139 static int get_max_buffer_len(void)
140 {
141 uint8_t buf[HIST_BUF_SIZE];
142 uint8_t out_buf[HIST_BUF_SIZE];
143 int len = sizeof(buf);
144 uint16_t out_len;
145
146 z_shell_history_init(&history);
147
148 do {
149 z_shell_history_put(&history, buf, len);
150 out_len = sizeof(out_buf);
151 if (z_shell_history_get(&history, true, out_buf, &out_len)) {
152 z_shell_history_purge(&history);
153 break;
154 }
155 } while (len--);
156
157 return len;
158 }
159
160 /* Test verifies that line that cannot fit into history buffer is not stored.
161 *
162 * Test steps:
163 * - initialize history.
164 * - put buffer that is bigger than history overall capacity.
165 * - verify that history is empty.
166 * - put short line followed by line that is close to max.
167 * - verify that long line evicted first line from history.
168 */
ZTEST(shell_test,test_too_long_line_not_stored)169 ZTEST(shell_test, test_too_long_line_not_stored)
170 {
171 uint8_t exp1_buf[HIST_BUF_SIZE];
172 int max_len = get_max_buffer_len();
173
174 init_test_buf(exp1_buf, sizeof(exp1_buf), 0);
175 z_shell_history_init(&history);
176
177 z_shell_history_put(&history, exp1_buf, max_len + 1);
178
179 /*validate that nothing is stored */
180 test_get(false, true, NULL, 0); /* empty */
181
182 z_shell_history_put(&history, exp1_buf, 20);
183 z_shell_history_put(&history, exp1_buf, max_len - 10);
184
185 /* Test that long entry evicts older entry. */
186 test_get(true, true, exp1_buf, max_len - 10);
187 test_get(false, true, NULL, 0); /* only one entry */
188
189 z_shell_history_purge(&history);
190 }
191
192 /* Test verifies that same line as the previous one is not stored in the
193 * history.
194 *
195 * Test steps:
196 * - initialize history.
197 * - put same line twice.
198 * - verify that only one line is in the history.
199 */
ZTEST(shell_test,test_no_duplicates_in_a_row)200 ZTEST(shell_test, test_no_duplicates_in_a_row)
201 {
202 uint8_t exp1_buf[HIST_BUF_SIZE];
203
204 init_test_buf(exp1_buf, sizeof(exp1_buf), 0);
205 z_shell_history_init(&history);
206
207 z_shell_history_put(&history, exp1_buf, 20);
208 z_shell_history_put(&history, exp1_buf, 20);
209
210 test_get(true, true, exp1_buf, 20);
211 /* only one line stored. */
212 test_get(false, true, NULL, 0);
213
214 z_shell_history_purge(&history);
215 }
216
217 /* Test storing long lines in the history.
218 *
219 * * Test steps:
220 * - initialize history.
221 * - Put max length line 1 in history.
222 * - Verify that it is present.
223 * - Put max length line 2 in history.
224 * - Verify that line 2 is present and line 1 was evicted.
225 * - Put max length line 3 in history.
226 * - Verify that line 3 is present and line 2 was evicted.
227 */
ZTEST(shell_test,test_storing_long_buffers)228 ZTEST(shell_test, test_storing_long_buffers)
229 {
230 uint8_t exp1_buf[HIST_BUF_SIZE];
231 uint8_t exp2_buf[HIST_BUF_SIZE];
232 uint8_t exp3_buf[HIST_BUF_SIZE];
233 int max_len = get_max_buffer_len();
234
235 init_test_buf(exp1_buf, sizeof(exp1_buf), 0);
236 init_test_buf(exp2_buf, sizeof(exp2_buf), 10);
237 init_test_buf(exp3_buf, sizeof(exp3_buf), 20);
238
239 z_shell_history_init(&history);
240
241 z_shell_history_put(&history, exp1_buf, max_len);
242 test_get(true, true, exp1_buf, max_len);
243 test_get(false, true, NULL, 0); /* only one entry */
244
245 z_shell_history_put(&history, exp2_buf, max_len);
246 test_get(true, true, exp2_buf, max_len);
247 test_get(false, true, NULL, 0); /* only one entry */
248
249 z_shell_history_put(&history, exp3_buf, max_len);
250 test_get(true, true, exp3_buf, max_len);
251 test_get(false, true, NULL, 0); /* only one entry */
252
253 z_shell_history_purge(&history);
254 }
255
256 ZTEST_SUITE(shell_test, NULL, NULL, NULL, NULL, NULL);
257