From 0b246b8c0ba029a9f71fdcbee14c0414bb41e5ed Mon Sep 17 00:00:00 2001 From: Jakob Hasse Date: Wed, 13 Mar 2024 10:53:05 +0800 Subject: [PATCH] refactor(console): made help command sorting depend on Kconfig option --- components/console/Kconfig | 10 +++ components/console/commands.c | 12 ++- .../console/test_apps/.build-test-rules.yml | 4 +- .../console/test_apps/console/README.md | 4 +- .../test_apps/console/main/test_console.c | 8 +- .../test_apps/console/pytest_console.py | 89 +++++++++++++++++-- .../test_apps/console/sdkconfig.ci.defaults | 3 + .../console/sdkconfig.ci.defaults.linux | 4 + .../test_apps/console/sdkconfig.ci.sorted | 2 + .../console/sdkconfig.ci.sorted.linux | 7 ++ 10 files changed, 129 insertions(+), 14 deletions(-) create mode 100644 components/console/Kconfig create mode 100644 components/console/test_apps/console/sdkconfig.ci.defaults create mode 100644 components/console/test_apps/console/sdkconfig.ci.defaults.linux create mode 100644 components/console/test_apps/console/sdkconfig.ci.sorted create mode 100644 components/console/test_apps/console/sdkconfig.ci.sorted.linux diff --git a/components/console/Kconfig b/components/console/Kconfig new file mode 100644 index 0000000000..6f375200f2 --- /dev/null +++ b/components/console/Kconfig @@ -0,0 +1,10 @@ +menu "Console Library" + + config CONSOLE_SORTED_HELP + bool "Enable sorted help" + default n + help + Instead of listing the commands in the order of registration, the help command lists + the available commands in sorted order, if this option is enabled. + +endmenu diff --git a/components/console/commands.c b/components/console/commands.c index a91e4fc337..bdeef9b393 100644 --- a/components/console/commands.c +++ b/components/console/commands.c @@ -144,17 +144,27 @@ esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd) item->context = cmd->context; } - cmd_item_t *last = NULL; + cmd_item_t *last; cmd_item_t *it; +#if CONFIG_CONSOLE_SORTED_HELP + last = NULL; SLIST_FOREACH(it, &s_cmd_list, next) { if (strcmp(it->command, item->command) > 0) { break; } last = it; } +#else + last = SLIST_FIRST(&s_cmd_list); +#endif if (last == NULL) { SLIST_INSERT_HEAD(&s_cmd_list, item, next); } else { +#if !CONFIG_CONSOLE_SORTED_HELP + while ((it = SLIST_NEXT(last, next)) != NULL) { + last = it; + } +#endif SLIST_INSERT_AFTER(last, item, next); } return ESP_OK; diff --git a/components/console/test_apps/.build-test-rules.yml b/components/console/test_apps/.build-test-rules.yml index 2878ea71c2..edfc607319 100644 --- a/components/console/test_apps/.build-test-rules.yml +++ b/components/console/test_apps/.build-test-rules.yml @@ -2,5 +2,5 @@ components/console/test_apps/console: enable: - - if: INCLUDE_DEFAULT == 1 or IDF_TARGET == "linux" - reason: Tested on all chips before, now also testing on Linux + - if: IDF_TARGET in["esp32", "esp32c3", "linux"] + reason: Testing all major architectures diff --git a/components/console/test_apps/console/README.md b/components/console/test_apps/console/README.md index bd34510f87..b23ffc6d33 100644 --- a/components/console/test_apps/console/README.md +++ b/components/console/test_apps/console/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | Linux | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | ----- | +| Supported Targets | ESP32 | ESP32-C3 | Linux | +| ----------------- | ----- | -------- | ----- | Note: Most of the test cases shouldn't be run manually, but [pytest](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/contribute/esp-idf-tests-with-pytest.html) should be used instead. E.g., to run all test cases on ESP32 using pytest, use: diff --git a/components/console/test_apps/console/main/test_console.c b/components/console/test_apps/console/main/test_console.c index d2364cd940..0b6a7d1b58 100644 --- a/components/console/test_apps/console/main/test_console.c +++ b/components/console/test_apps/console/main/test_console.c @@ -174,9 +174,9 @@ TEST_CASE("esp console help command - sorted registration", "[console][ignore]") esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); TEST_ESP_OK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl)); - TEST_ESP_OK(esp_console_cmd_register(&s_quit_cmd)); - TEST_ESP_OK(esp_console_register_help_command()); TEST_ESP_OK(esp_console_cmd_register(&cmd_a)); + TEST_ESP_OK(esp_console_register_help_command()); + TEST_ESP_OK(esp_console_cmd_register(&s_quit_cmd)); TEST_ESP_OK(esp_console_cmd_register(&cmd_z)); TEST_ESP_OK(esp_console_start_repl(s_repl)); @@ -194,9 +194,9 @@ TEST_CASE("esp console help command - reverse registration", "[console][ignore]" TEST_ESP_OK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl)); TEST_ESP_OK(esp_console_cmd_register(&cmd_z)); - TEST_ESP_OK(esp_console_cmd_register(&cmd_a)); - TEST_ESP_OK(esp_console_register_help_command()); TEST_ESP_OK(esp_console_cmd_register(&s_quit_cmd)); + TEST_ESP_OK(esp_console_register_help_command()); + TEST_ESP_OK(esp_console_cmd_register(&cmd_a)); TEST_ESP_OK(esp_console_start_repl(s_repl)); vTaskDelay(pdMS_TO_TICKS(5000)); diff --git a/components/console/test_apps/console/pytest_console.py b/components/console/test_apps/console/pytest_console.py index d92ed11037..edee3741b5 100644 --- a/components/console/test_apps/console/pytest_console.py +++ b/components/console/test_apps/console/pytest_console.py @@ -49,10 +49,16 @@ def do_test_help_quit(dut: Dut) -> None: dut.expect(r'quit\s+Quit REPL environment\s+esp>', timeout=5) +@pytest.mark.parametrize( + 'config', [ + pytest.param('defaults'), + ] +) @pytest.mark.parametrize( 'test_on', [ pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.supported_targets, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), ] ) @@ -62,10 +68,16 @@ def test_console(dut: Dut, test_on: str) -> None: dut.expect(r'\d{1} Tests 0 Failures 0 Ignored', timeout=120) +@pytest.mark.parametrize( + 'config', [ + pytest.param('defaults'), + ] +) @pytest.mark.parametrize( 'test_on', [ pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.supported_targets, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), ] ) @@ -73,10 +85,16 @@ def test_console_repl(dut: Dut, test_on: str) -> None: do_test_quit(dut) +@pytest.mark.parametrize( + 'config', [ + pytest.param('defaults'), + ] +) @pytest.mark.parametrize( 'test_on', [ pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.supported_targets, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), ] ) @@ -84,21 +102,82 @@ def test_console_help_sorted_registration(dut: Dut, test_on: str) -> None: do_test_help_generic(dut, 'sorted') +@pytest.mark.parametrize( + 'config', [ + pytest.param('defaults'), + ] +) @pytest.mark.parametrize( 'test_on', [ pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.supported_targets, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), ] ) def test_console_help_reverse_registration(dut: Dut, test_on: str) -> None: + dut.expect_exact('Press ENTER to see the list of tests') + dut.write('"esp console help command - reverse registration"') + + dut.expect_exact('esp>', timeout=5) + dut.write('help') + + dut.expect_exact('zzz', timeout=5) + dut.expect_exact('should appear last in help', timeout=5) + + dut.expect_exact('quit', timeout=5) + dut.expect_exact('Quit REPL environment', timeout=5) + + dut.expect(r'help\s+\[\]', timeout=5) + + # Note: repl seems to do the line breaks by itself, this needs to be adjusted if repl changes its line width + dut.expect_exact('Print the summary of all registered commands if no arguments are given,', timeout=5) + dut.expect_exact('otherwise print summary of given command.', timeout=5) + dut.expect(r'\s+Name of command', timeout=5) + + dut.expect_exact('aaa', timeout=5) + dut.expect_exact('should appear first in help', timeout=5) + dut.expect_exact('esp>', timeout=5) + + +@pytest.mark.parametrize( + 'config', [ + pytest.param('sorted'), + ] +) +@pytest.mark.parametrize( + 'test_on', [ + pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), + ] +) +def test_console_sorted_help_sorted_registration(dut: Dut, test_on: str) -> None: + do_test_help_generic(dut, 'sorted') + + +@pytest.mark.parametrize( + 'config', [ + pytest.param('sorted', marks=[pytest.mark.linux, pytest.mark.host_test]), + ] +) +@pytest.mark.parametrize( + 'test_on', [ + pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), + ] +) +def test_console_sorted_help_reverse_registration(dut: Dut, test_on: str) -> None: do_test_help_generic(dut, 'reverse') +@pytest.mark.parametrize( + 'config', [ + pytest.param('defaults'), + ] +) @pytest.mark.parametrize( 'test_on', [ pytest.param('host', marks=[pytest.mark.linux, pytest.mark.host_test]), - pytest.param('target', marks=[pytest.mark.supported_targets, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32, pytest.mark.generic]), + pytest.param('target', marks=[pytest.mark.esp32c3, pytest.mark.generic]), pytest.param('qemu', marks=[pytest.mark.esp32, pytest.mark.host_test, pytest.mark.qemu]), ] ) diff --git a/components/console/test_apps/console/sdkconfig.ci.defaults b/components/console/test_apps/console/sdkconfig.ci.defaults new file mode 100644 index 0000000000..ba19fc5604 --- /dev/null +++ b/components/console/test_apps/console/sdkconfig.ci.defaults @@ -0,0 +1,3 @@ +# This "default" configuration is appended to all other configurations +# The contents of "sdkconfig.debug_helpers" is also appended to all other configurations (see CMakeLists.txt) +CONFIG_ESP_TASK_WDT_INIT=n diff --git a/components/console/test_apps/console/sdkconfig.ci.defaults.linux b/components/console/test_apps/console/sdkconfig.ci.defaults.linux new file mode 100644 index 0000000000..640c6739d0 --- /dev/null +++ b/components/console/test_apps/console/sdkconfig.ci.defaults.linux @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="linux" + +# Not necessary on Linux +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=n diff --git a/components/console/test_apps/console/sdkconfig.ci.sorted b/components/console/test_apps/console/sdkconfig.ci.sorted new file mode 100644 index 0000000000..fa098a36d0 --- /dev/null +++ b/components/console/test_apps/console/sdkconfig.ci.sorted @@ -0,0 +1,2 @@ +# enable sorted commands in the help command +CONFIG_CONSOLE_SORTED_HELP=y diff --git a/components/console/test_apps/console/sdkconfig.ci.sorted.linux b/components/console/test_apps/console/sdkconfig.ci.sorted.linux new file mode 100644 index 0000000000..aa7094abbb --- /dev/null +++ b/components/console/test_apps/console/sdkconfig.ci.sorted.linux @@ -0,0 +1,7 @@ +CONFIG_IDF_TARGET="linux" + +# Not necessary on Linux +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=n + +# enable sorted commands in the help command +CONFIG_CONSOLE_SORTED_HELP=y