| /* |
| * Copyright (c) 2017 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** @file |
| * @brief Interactive shell test suite |
| * |
| */ |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/ztest.h> |
| |
| #include <zephyr/shell/shell_history.h> |
| |
| #define HIST_BUF_SIZE 160 |
| Z_SHELL_HISTORY_DEFINE(history, HIST_BUF_SIZE); |
| |
| static void init_test_buf(uint8_t *buf, size_t len, uint8_t offset) |
| { |
| for (int i = 0; i < len; i++) { |
| buf[i] = offset + i; |
| } |
| } |
| |
| /** |
| * Function tests getting line from history and compares it against expected |
| * result. |
| */ |
| static void test_get(bool ok, bool up, uint8_t *exp_buf, uint16_t exp_len) |
| { |
| bool res; |
| uint8_t out_buf[HIST_BUF_SIZE]; |
| uint16_t out_len; |
| |
| out_len = sizeof(out_buf); |
| |
| res = z_shell_history_get(&history, up, out_buf, &out_len); |
| |
| if (ok) { |
| zassert_true(res, "history should contain one entry.\n"); |
| |
| zassert_equal(out_len, exp_len, "Unexpected entry length.\n"); |
| if (out_len) { |
| zassert_equal(memcmp(out_buf, exp_buf, out_len), 0, |
| "Expected equal buffers.\n"); |
| } |
| } else { |
| zassert_false(res, "History should return nothing.\n"); |
| } |
| } |
| |
| /* Test put line to history and get it. |
| * |
| * Test steps: |
| * - initialize history. |
| * - put line to the history. |
| * - read line and verify that it is the one that was put. |
| */ |
| ZTEST(shell_test, test_history_add_get) |
| { |
| uint8_t exp_buf[HIST_BUF_SIZE]; |
| |
| init_test_buf(exp_buf, sizeof(exp_buf), 0); |
| |
| z_shell_history_init(&history); |
| |
| test_get(false, true, NULL, 0); |
| |
| z_shell_history_put(&history, exp_buf, 20); |
| |
| test_get(true, true, exp_buf, 20); |
| |
| z_shell_history_purge(&history); |
| } |
| |
| /* Test verifies that after purging there is no line in the history. */ |
| ZTEST(shell_test, test_history_purge) |
| { |
| uint8_t exp_buf[HIST_BUF_SIZE]; |
| |
| init_test_buf(exp_buf, sizeof(exp_buf), 0); |
| |
| z_shell_history_init(&history); |
| |
| z_shell_history_put(&history, exp_buf, 20); |
| z_shell_history_put(&history, exp_buf, 20); |
| |
| z_shell_history_purge(&history); |
| |
| test_get(false, true, NULL, 0); |
| } |
| |
| /* Test browsing history. |
| * |
| * Test steps: |
| * - initialize history. |
| * - put lines 1,2,3 to history. |
| * - get in up direction a line and verify that it's the last one added (3). |
| * - get next line in up direction and verify that it's line 2. |
| * - get next line in up direction and verify that it's line 1. |
| * - get next line in down direction and verify that it's line 2. |
| * - get next line in up direction and verify that it's line 1. |
| * - get next line in down direction and verify that it's line 2. |
| * - get next line in down direction and verify that it's line 3. |
| * - attempt to get next line in down direction and verify that there is no |
| * line. |
| */ |
| ZTEST(shell_test, test_history_get_up_and_down) |
| { |
| uint8_t exp1_buf[HIST_BUF_SIZE]; |
| uint8_t exp2_buf[HIST_BUF_SIZE]; |
| uint8_t exp3_buf[HIST_BUF_SIZE]; |
| |
| init_test_buf(exp1_buf, sizeof(exp1_buf), 0); |
| init_test_buf(exp2_buf, sizeof(exp2_buf), 10); |
| init_test_buf(exp3_buf, sizeof(exp3_buf), 20); |
| |
| z_shell_history_init(&history); |
| |
| z_shell_history_put(&history, exp1_buf, 20); |
| z_shell_history_put(&history, exp2_buf, 15); |
| z_shell_history_put(&history, exp3_buf, 20); |
| |
| test_get(true, true, exp3_buf, 20); /* up - 3*/ |
| test_get(true, true, exp2_buf, 15); /* up - 2*/ |
| test_get(true, true, exp1_buf, 20); /* up - 1*/ |
| test_get(true, false, exp2_buf, 15); /* down - 2 */ |
| test_get(true, true, exp1_buf, 20); /* up - 1*/ |
| test_get(true, false, exp2_buf, 15); /* down - 2 */ |
| test_get(true, false, exp3_buf, 20); /* down - 3 */ |
| test_get(false, false, NULL, 0); /* down - nothing */ |
| |
| z_shell_history_purge(&history); |
| } |
| |
| /* Function for getting maximal buffer size that can be stored in the history */ |
| static int get_max_buffer_len(void) |
| { |
| uint8_t buf[HIST_BUF_SIZE]; |
| uint8_t out_buf[HIST_BUF_SIZE]; |
| int len = sizeof(buf); |
| uint16_t out_len; |
| |
| z_shell_history_init(&history); |
| |
| do { |
| z_shell_history_put(&history, buf, len); |
| out_len = sizeof(out_buf); |
| if (z_shell_history_get(&history, true, out_buf, &out_len)) { |
| z_shell_history_purge(&history); |
| break; |
| } |
| } while (len--); |
| |
| return len; |
| } |
| |
| /* Test verifies that line that cannot fit into history buffer is not stored. |
| * |
| * Test steps: |
| * - initialize history. |
| * - put buffer that is bigger than history overall capacity. |
| * - verify that history is empty. |
| * - put short line followed by line that is close to max. |
| * - verify that long line evicted first line from history. |
| */ |
| ZTEST(shell_test, test_too_long_line_not_stored) |
| { |
| uint8_t exp1_buf[HIST_BUF_SIZE]; |
| int max_len = get_max_buffer_len(); |
| |
| init_test_buf(exp1_buf, sizeof(exp1_buf), 0); |
| z_shell_history_init(&history); |
| |
| z_shell_history_put(&history, exp1_buf, max_len + 1); |
| |
| /*validate that nothing is stored */ |
| test_get(false, true, NULL, 0); /* empty */ |
| |
| z_shell_history_put(&history, exp1_buf, 20); |
| z_shell_history_put(&history, exp1_buf, max_len - 10); |
| |
| /* Test that long entry evicts older entry. */ |
| test_get(true, true, exp1_buf, max_len - 10); |
| test_get(false, true, NULL, 0); /* only one entry */ |
| |
| z_shell_history_purge(&history); |
| } |
| |
| /* Test verifies that same line as the previous one is not stored in the |
| * history. |
| * |
| * Test steps: |
| * - initialize history. |
| * - put same line twice. |
| * - verify that only one line is in the history. |
| */ |
| ZTEST(shell_test, test_no_duplicates_in_a_row) |
| { |
| uint8_t exp1_buf[HIST_BUF_SIZE]; |
| |
| init_test_buf(exp1_buf, sizeof(exp1_buf), 0); |
| z_shell_history_init(&history); |
| |
| z_shell_history_put(&history, exp1_buf, 20); |
| z_shell_history_put(&history, exp1_buf, 20); |
| |
| test_get(true, true, exp1_buf, 20); |
| /* only one line stored. */ |
| test_get(false, true, NULL, 0); |
| |
| z_shell_history_purge(&history); |
| } |
| |
| /* Test storing long lines in the history. |
| * |
| * * Test steps: |
| * - initialize history. |
| * - Put max length line 1 in history. |
| * - Verify that it is present. |
| * - Put max length line 2 in history. |
| * - Verify that line 2 is present and line 1 was evicted. |
| * - Put max length line 3 in history. |
| * - Verify that line 3 is present and line 2 was evicted. |
| */ |
| ZTEST(shell_test, test_storing_long_buffers) |
| { |
| uint8_t exp1_buf[HIST_BUF_SIZE]; |
| uint8_t exp2_buf[HIST_BUF_SIZE]; |
| uint8_t exp3_buf[HIST_BUF_SIZE]; |
| int max_len = get_max_buffer_len(); |
| |
| init_test_buf(exp1_buf, sizeof(exp1_buf), 0); |
| init_test_buf(exp2_buf, sizeof(exp2_buf), 10); |
| init_test_buf(exp3_buf, sizeof(exp3_buf), 20); |
| |
| z_shell_history_init(&history); |
| |
| z_shell_history_put(&history, exp1_buf, max_len); |
| test_get(true, true, exp1_buf, max_len); |
| test_get(false, true, NULL, 0); /* only one entry */ |
| |
| z_shell_history_put(&history, exp2_buf, max_len); |
| test_get(true, true, exp2_buf, max_len); |
| test_get(false, true, NULL, 0); /* only one entry */ |
| |
| z_shell_history_put(&history, exp3_buf, max_len); |
| test_get(true, true, exp3_buf, max_len); |
| test_get(false, true, NULL, 0); /* only one entry */ |
| |
| z_shell_history_purge(&history); |
| } |
| |
| ZTEST_SUITE(shell_test, NULL, NULL, NULL, NULL, NULL); |