Skip to content

Commit 7f8ef19

Browse files
committed
feat(esp_commands): Add tests to the esp_commands component
1 parent ee04c51 commit 7f8ef19

File tree

8 files changed

+349
-0
lines changed

8 files changed

+349
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
3+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
4+
set(COMPONENTS main)
5+
project(esp_commands_test)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
idf_component_register(SRCS "test_esp_commands.c" "test_main.c"
2+
PRIV_INCLUDE_DIRS "." "include"
3+
PRIV_REQUIRES unity
4+
WHOLE_ARCHIVE)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
dependencies:
2+
espressif/esp_commands:
3+
version: "*"
4+
override_path: "../.."
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
#define NB_OF_REGISTERED_CMD 8
14+
15+
#define GET_NAME(NAME, SUFFIX) NAME##SUFFIX
16+
#define GET_STR(STR) #STR
17+
18+
#define CREATE_CMD_FUNC(NAME) \
19+
static int GET_NAME(NAME, _func)(int argc, char **argv) { \
20+
printf(GET_STR(NAME) GET_STR(_func)); \
21+
printf("\n"); \
22+
return 0; \
23+
}
24+
25+
#define CREATE_FUNC(NAME, SUFFIX) \
26+
static const char *GET_NAME(NAME, SUFFIX)(void) { \
27+
return #NAME #SUFFIX; \
28+
}
29+
30+
/* static command functions*/
31+
CREATE_CMD_FUNC(cmd_a)
32+
CREATE_CMD_FUNC(cmd_b)
33+
CREATE_CMD_FUNC(cmd_c)
34+
CREATE_CMD_FUNC(cmd_d)
35+
CREATE_CMD_FUNC(cmd_e)
36+
CREATE_CMD_FUNC(cmd_f)
37+
CREATE_CMD_FUNC(cmd_g)
38+
CREATE_CMD_FUNC(cmd_h)
39+
40+
/* static hint functions*/
41+
CREATE_FUNC(cmd_a, _hint)
42+
CREATE_FUNC(cmd_b, _hint)
43+
CREATE_FUNC(cmd_c, _hint)
44+
CREATE_FUNC(cmd_d, _hint)
45+
CREATE_FUNC(cmd_e, _hint)
46+
CREATE_FUNC(cmd_f, _hint)
47+
CREATE_FUNC(cmd_g, _hint)
48+
CREATE_FUNC(cmd_h, _hint)
49+
50+
/* static glossary functions*/
51+
CREATE_FUNC(cmd_a, _glossary)
52+
CREATE_FUNC(cmd_b, _glossary)
53+
CREATE_FUNC(cmd_c, _glossary)
54+
CREATE_FUNC(cmd_d, _glossary)
55+
CREATE_FUNC(cmd_e, _glossary)
56+
CREATE_FUNC(cmd_f, _glossary)
57+
CREATE_FUNC(cmd_g, _glossary)
58+
CREATE_FUNC(cmd_h, _glossary)
59+
60+
/* command registration */
61+
ESP_COMMAND_REGISTER(cmd_a, group_1, GET_STR(cmd_a_help), cmd_a_func, NULL, NULL, cmd_a_hint, cmd_a_glossary);
62+
ESP_COMMAND_REGISTER(cmd_b, group_1, GET_STR(cmd_b_help), cmd_b_func, NULL, NULL, cmd_b_hint, cmd_b_glossary);
63+
ESP_COMMAND_REGISTER(cmd_c, group_2, GET_STR(cmd_c_help), cmd_c_func, NULL, NULL, cmd_c_hint, cmd_c_glossary);
64+
ESP_COMMAND_REGISTER(cmd_d, group_2, GET_STR(cmd_d_help), cmd_d_func, NULL, NULL, cmd_d_hint, cmd_d_glossary);
65+
ESP_COMMAND_REGISTER(cmd_e, group_3, GET_STR(cmd_e_help), cmd_e_func, NULL, NULL, cmd_e_hint, cmd_e_glossary);
66+
ESP_COMMAND_REGISTER(cmd_f, group_3, GET_STR(cmd_f_help), cmd_f_func, NULL, NULL, cmd_f_hint, cmd_f_glossary);
67+
ESP_COMMAND_REGISTER(cmd_g, group_4, GET_STR(cmd_g_help), cmd_g_func, NULL, NULL, cmd_g_hint, cmd_g_glossary);
68+
ESP_COMMAND_REGISTER(cmd_h, group_4, GET_STR(cmd_h_help), cmd_h_func, NULL, NULL, cmd_h_hint, cmd_h_glossary);
69+
70+
#ifdef __cplusplus
71+
}
72+
#endif
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <string.h>
8+
#include <stdio.h>
9+
#include <pthread.h>
10+
#include "unity.h"
11+
#include "esp_commands.h"
12+
#include "test_esp_commands_utils.h"
13+
14+
/*
15+
* IMPORTANT:
16+
* - 8 commands are created in test_esp_commands_utils.h (cmd_a - cmd_h)
17+
* - the commands are divided in 4 groups (group_1 - group_4)
18+
* - each group contains 2 commands.
19+
* - group_1 contains cmd_a and cmd_b,
20+
* [...]
21+
* - group_4 contains cmd_g and cmd_h
22+
*/
23+
24+
static void test_setup(void)
25+
{
26+
const esp_commands_config_t config = ESP_COMMANDS_CONFIG_DEFAULT();
27+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_init(&config));
28+
}
29+
30+
static void test_teardown(void)
31+
{
32+
esp_commands_deinit();
33+
}
34+
35+
TEST_CASE("help command - called without command set", "[esp_commands]")
36+
{
37+
test_setup();
38+
39+
/* call esp_commands_execute to run help command with verbosity 0 */
40+
int cmd_ret = -1;
41+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(NULL, "help -v 0", &cmd_ret));
42+
TEST_ASSERT_EQUAL(0, cmd_ret);
43+
44+
/* call esp_commands_execute to run help command with verbosity 1 */
45+
cmd_ret = -1;
46+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(NULL, "help -v 1", &cmd_ret));
47+
TEST_ASSERT_EQUAL(0, cmd_ret);
48+
49+
/* call esp_commands_execute to run help command on a registered command */
50+
cmd_ret = -1;
51+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(NULL, "help cmd_a -v 0", &cmd_ret));
52+
TEST_ASSERT_EQUAL(0, cmd_ret);
53+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(NULL, "help cmd_a -v 1", &cmd_ret));
54+
TEST_ASSERT_EQUAL(0, cmd_ret);
55+
56+
/* call esp_commands_execute to run help command on an unregistered command */
57+
cmd_ret = -1;
58+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(NULL, "help cmd_w", &cmd_ret));
59+
TEST_ASSERT_EQUAL(1, cmd_ret);
60+
61+
/* call esp_commands_execute to run help command on a registered command with wrong
62+
* verbosity syntax */
63+
cmd_ret = -1;
64+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(NULL, "help cmd_a -v=1", &cmd_ret));
65+
TEST_ASSERT_EQUAL(1, cmd_ret);
66+
67+
/* call esp_commands_execute to run help command with too many command names */
68+
cmd_ret = -1;
69+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(NULL, "help cmd_a cmd_b -v 1", &cmd_ret));
70+
TEST_ASSERT_EQUAL(1, cmd_ret);
71+
72+
test_teardown();
73+
}
74+
75+
typedef struct cmd_test_sequence {
76+
const char *cmd_list[NB_OF_REGISTERED_CMD];
77+
int expected_ret_val[NB_OF_REGISTERED_CMD];
78+
} cmd_test_sequence_t;
79+
80+
TEST_CASE("test command set by group, by name and concatenate", "[esp_commands]")
81+
{
82+
test_setup();
83+
84+
int cmd_ret = -1;
85+
86+
/* create a command set with group 1 and 3 */
87+
const char *group_set_a[] = {"group_1", "group_3"};
88+
esp_command_set_handle_t handle_set_a = ESP_COMMANDS_CREATE_CMD_SET(group_set_a, FIELD_ACCESSOR(group));
89+
TEST_ASSERT_NOT_NULL(handle_set_a);
90+
91+
/* create a command set with group 2 and 4 */
92+
const char *group_set_b[] = {"group_2", "group_4"};
93+
esp_command_set_handle_t handle_set_b = ESP_COMMANDS_CREATE_CMD_SET(group_set_b, FIELD_ACCESSOR(group));
94+
TEST_ASSERT_NOT_NULL(handle_set_b);
95+
96+
/* call execute command with the set_a and all command names */
97+
cmd_test_sequence_t test_cmd = {
98+
.cmd_list = {"cmd_a", "cmd_b", "cmd_c", "cmd_d", "cmd_e", "cmd_f", "cmd_g", "cmd_h"},
99+
.expected_ret_val = {0, 0, -1, -1, 0, 0, -1, -1}
100+
};
101+
for (size_t i = 0; i < NB_OF_REGISTERED_CMD; i++) {
102+
cmd_ret = -1;
103+
esp_err_t expected_ret_val = ESP_OK;
104+
if (test_cmd.expected_ret_val[i] != 0) {
105+
expected_ret_val = ESP_ERR_NOT_FOUND;
106+
}
107+
TEST_ASSERT_EQUAL(expected_ret_val, esp_commands_execute(handle_set_a, test_cmd.cmd_list[i], &cmd_ret));
108+
TEST_ASSERT_EQUAL(test_cmd.expected_ret_val[i], cmd_ret);
109+
}
110+
111+
/* call execute command with the set_b and all command names */
112+
memcpy(test_cmd.expected_ret_val, (int[]) {
113+
-1, -1, 0, 0, -1, -1, 0, 0
114+
}, sizeof(int) * NB_OF_REGISTERED_CMD);
115+
for (size_t i = 0; i < NB_OF_REGISTERED_CMD; i++) {
116+
cmd_ret = -1;
117+
esp_err_t expected_ret_val = ESP_OK;
118+
if (test_cmd.expected_ret_val[i] != 0) {
119+
expected_ret_val = ESP_ERR_NOT_FOUND;
120+
}
121+
TEST_ASSERT_EQUAL(expected_ret_val, esp_commands_execute(handle_set_b, test_cmd.cmd_list[i], &cmd_ret));
122+
TEST_ASSERT_EQUAL(test_cmd.expected_ret_val[i], cmd_ret);
123+
}
124+
125+
/* call esp_commands_execute to run help command with both sets */
126+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(handle_set_a, "help", &cmd_ret));
127+
TEST_ASSERT_EQUAL(0, cmd_ret);
128+
129+
TEST_ASSERT_EQUAL(ESP_OK, esp_commands_execute(handle_set_b, "help", &cmd_ret));
130+
TEST_ASSERT_EQUAL(0, cmd_ret);
131+
132+
/* destroy the sets */
133+
esp_commands_destroy_cmd_set(&handle_set_a);
134+
TEST_ASSERT_NULL(handle_set_a);
135+
esp_commands_destroy_cmd_set(&handle_set_b);
136+
TEST_ASSERT_NULL(handle_set_b);
137+
138+
/* create a command set with cmd_a, cmd_b and cmd_c */
139+
const char *cmd_name_set_a[] = {"cmd_a", "cmd_b", "cmd_c"};
140+
handle_set_a = esp_commands_create_cmd_set(cmd_name_set_a, 3, FIELD_ACCESSOR(name));
141+
TEST_ASSERT_NOT_NULL(handle_set_a);
142+
143+
/* create a command set with cmd_f, cmd_g and cmd_h */
144+
const char *cmd_name_set_b[] = {"cmd_f", "cmd_g", "cmd_h"};
145+
handle_set_b = esp_commands_create_cmd_set(cmd_name_set_b, 3, FIELD_ACCESSOR(name));
146+
TEST_ASSERT_NOT_NULL(handle_set_b);
147+
148+
/* call execute command with the set_a and all command names */
149+
memcpy(test_cmd.expected_ret_val, (int[]) {
150+
0, 0, 0, -1, -1, -1, -1, -1
151+
}, sizeof(int) * NB_OF_REGISTERED_CMD);
152+
for (size_t i = 0; i < NB_OF_REGISTERED_CMD; i++) {
153+
cmd_ret = -1;
154+
esp_err_t expected_ret_val = ESP_OK;
155+
if (test_cmd.expected_ret_val[i] != 0) {
156+
expected_ret_val = ESP_ERR_NOT_FOUND;
157+
}
158+
TEST_ASSERT_EQUAL(expected_ret_val, esp_commands_execute(handle_set_a, test_cmd.cmd_list[i], &cmd_ret));
159+
TEST_ASSERT_EQUAL(test_cmd.expected_ret_val[i], cmd_ret);
160+
}
161+
162+
/* call execute command with the set_b and all command names */
163+
memcpy(test_cmd.expected_ret_val, (int[]) {
164+
-1, -1, -1, -1, -1, 0, 0, 0
165+
}, sizeof(int) * NB_OF_REGISTERED_CMD);
166+
for (size_t i = 0; i < NB_OF_REGISTERED_CMD; i++) {
167+
cmd_ret = -1;
168+
esp_err_t expected_ret_val = ESP_OK;
169+
if (test_cmd.expected_ret_val[i] != 0) {
170+
expected_ret_val = ESP_ERR_NOT_FOUND;
171+
}
172+
TEST_ASSERT_EQUAL(expected_ret_val, esp_commands_execute(handle_set_b, test_cmd.cmd_list[i], &cmd_ret));
173+
TEST_ASSERT_EQUAL(test_cmd.expected_ret_val[i], cmd_ret);
174+
}
175+
176+
/* create a command set that concatenates the previous 2 sets */
177+
esp_command_set_handle_t handle_set_c = esp_commands_concat_cmd_set(handle_set_a, handle_set_b);
178+
TEST_ASSERT_NOT_NULL(handle_set_c);
179+
180+
/* call execute command with the set_c and all command names */
181+
memcpy(test_cmd.expected_ret_val, (int[]) {
182+
0, 0, 0, -1, -1, 0, 0, 0
183+
}, sizeof(int) * NB_OF_REGISTERED_CMD);
184+
for (size_t i = 0; i < NB_OF_REGISTERED_CMD; i++) {
185+
cmd_ret = -1;
186+
esp_err_t expected_ret_val = ESP_OK;
187+
if (test_cmd.expected_ret_val[i] != 0) {
188+
expected_ret_val = ESP_ERR_NOT_FOUND;
189+
}
190+
TEST_ASSERT_EQUAL(expected_ret_val, esp_commands_execute(handle_set_c, test_cmd.cmd_list[i], &cmd_ret));
191+
TEST_ASSERT_EQUAL(test_cmd.expected_ret_val[i], cmd_ret);
192+
}
193+
194+
esp_commands_destroy_cmd_set(&handle_set_c);
195+
TEST_ASSERT_NULL(handle_set_c);
196+
197+
test_teardown();
198+
}
199+
200+
TEST_CASE("test command set error handling", "[esp_commands]")
201+
{
202+
test_setup();
203+
204+
/* create a command set with NULL passed as list of command id */
205+
TEST_ASSERT_NULL(esp_commands_create_cmd_set(NULL, 2, FIELD_ACCESSOR(group)));
206+
207+
/* create a command set with 0 as size of list of command id */
208+
const char *group_set_a[] = {"group_2", "group_4"};
209+
TEST_ASSERT_NULL(esp_commands_create_cmd_set(group_set_a, 0, FIELD_ACCESSOR(group)));
210+
211+
/* concatenate 2 NULL sets */
212+
TEST_ASSERT_NULL(esp_commands_concat_cmd_set(NULL, NULL));
213+
214+
/* redefinition of esp_command_set_t so we can access the fields
215+
* and test their values */
216+
typedef struct cmd_set {
217+
esp_command_t **cmd_ptr_set;
218+
size_t cmd_set_size;
219+
} cmd_set_t;
220+
221+
/* pass wrong command name in array, expect a non null command set handle with 0 items in it*/
222+
const char *group_set_b[] = {"group2", "group4"};
223+
esp_command_set_handle_t group_set_handle_b = esp_commands_create_cmd_set(group_set_b, 2, FIELD_ACCESSOR(group));
224+
cmd_set_t *cmd_set = (cmd_set_t *)group_set_handle_b;
225+
TEST_ASSERT_NOT_NULL(group_set_handle_b);
226+
TEST_ASSERT_NULL(cmd_set->cmd_ptr_set);
227+
TEST_ASSERT_EQUAL(0, cmd_set->cmd_set_size);
228+
229+
esp_commands_destroy_cmd_set(&group_set_handle_b);
230+
231+
test_teardown();
232+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "unity.h"
8+
#include "unity_test_runner.h"
9+
#include "esp_heap_caps.h"
10+
#include "unity_test_utils_memory.h"
11+
12+
void setUp(void)
13+
{
14+
unity_utils_record_free_mem();
15+
}
16+
17+
void tearDown(void)
18+
{
19+
unity_utils_evaluate_leaks_direct(0);
20+
}
21+
22+
void app_main(void)
23+
{
24+
printf("Running esp_commands component tests\n");
25+
unity_run_menu();
26+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import pytest
2+
3+
@pytest.mark.generic
4+
def test_esp_commands(dut) -> None:
5+
dut.run_all_single_board_cases()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_ESP_TASK_WDT_EN=n

0 commit comments

Comments
 (0)