Skip to content

Commit 5211944

Browse files
committed
test(net_connect): add unit tests for net_get_netif_from_desc()
Add comprehensive unit test suite for net_get_netif_from_desc() function with 11 test cases covering: - Successful lookup for different netif types (STA, ETH, Thread, PPP, custom) - Error handling for NULL, empty string, and non-existent descriptions - Edge cases including case-sensitive matching, exact match requirements, and consistency across multiple calls The test suite uses Unity test framework with proper setup/teardown for netif creation and memory leak detection. Includes CMakeLists.txt files for build configuration and pytest integration for CI/CD.
1 parent 2fb9c98 commit 5211944

File tree

6 files changed

+343
-0
lines changed

6 files changed

+343
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# This is the project CMakeLists.txt file for the test subproject
2+
cmake_minimum_required(VERSION 3.16)
3+
4+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
5+
6+
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "6.0")
7+
set(test_component_dir $ENV{IDF_PATH}/tools/test_apps/components)
8+
else()
9+
set(test_component_dir $ENV{IDF_PATH}/tools/unit-test-app/components)
10+
endif()
11+
12+
set(EXTRA_COMPONENT_DIRS ../..
13+
${test_component_dir})
14+
15+
project(net_connect_test)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
idf_component_register(SRCS "test_net_connect.c"
3+
REQUIRES test_utils esp_netif esp_event
4+
INCLUDE_DIRS "."
5+
PRIV_REQUIRES unity net_connect)
Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
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 "net_connect.h"
9+
#include "esp_event.h"
10+
#include "esp_netif.h"
11+
#include "esp_netif_defaults.h"
12+
#include "unity.h"
13+
#include "test_utils.h"
14+
#include "unity_fixture.h"
15+
#include "memory_checks.h"
16+
17+
#define TEST_NETIF_DESC_STA "net_connect_netif_sta"
18+
#define TEST_NETIF_DESC_ETH "net_connect_netif_eth"
19+
#define TEST_NETIF_DESC_THREAD "net_connect_netif_thread"
20+
#define TEST_NETIF_DESC_PPP "net_connect_netif_ppp"
21+
#define TEST_NETIF_DESC_OTHER "other_netif_desc"
22+
23+
TEST_GROUP(net_connect);
24+
25+
static esp_netif_t *test_netif_sta = NULL;
26+
static esp_netif_t *test_netif_eth = NULL;
27+
static esp_netif_t *test_netif_thread = NULL;
28+
static esp_netif_t *test_netif_ppp = NULL;
29+
static esp_netif_t *test_netif_other = NULL;
30+
31+
TEST_SETUP(net_connect)
32+
{
33+
test_utils_record_free_mem();
34+
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
35+
36+
// Create default event loop for netif operations
37+
esp_event_loop_create_default();
38+
39+
// Create test netifs with different descriptions
40+
// Using WiFi STA config for all as it's the simplest and most reliable for unit tests
41+
// Set unique if_key and description in the inherent config before creating the netif
42+
// Note: if_key must be unique for each interface, while if_desc is what we search by
43+
esp_netif_inherent_config_t base_cfg_sta = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
44+
base_cfg_sta.if_key = "WIFI_STA_TEST_STA";
45+
base_cfg_sta.if_desc = TEST_NETIF_DESC_STA;
46+
esp_netif_config_t cfg_sta = {
47+
.base = &base_cfg_sta,
48+
.driver = NULL,
49+
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA,
50+
};
51+
test_netif_sta = esp_netif_new(&cfg_sta);
52+
TEST_ASSERT_NOT_NULL(test_netif_sta);
53+
54+
esp_netif_inherent_config_t base_cfg_eth = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
55+
base_cfg_eth.if_key = "WIFI_STA_TEST_ETH";
56+
base_cfg_eth.if_desc = TEST_NETIF_DESC_ETH;
57+
esp_netif_config_t cfg_eth = {
58+
.base = &base_cfg_eth,
59+
.driver = NULL,
60+
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA,
61+
};
62+
test_netif_eth = esp_netif_new(&cfg_eth);
63+
TEST_ASSERT_NOT_NULL(test_netif_eth);
64+
65+
esp_netif_inherent_config_t base_cfg_thread = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
66+
base_cfg_thread.if_key = "WIFI_STA_TEST_THREAD";
67+
base_cfg_thread.if_desc = TEST_NETIF_DESC_THREAD;
68+
esp_netif_config_t cfg_thread = {
69+
.base = &base_cfg_thread,
70+
.driver = NULL,
71+
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA,
72+
};
73+
test_netif_thread = esp_netif_new(&cfg_thread);
74+
TEST_ASSERT_NOT_NULL(test_netif_thread);
75+
76+
esp_netif_inherent_config_t base_cfg_ppp = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
77+
base_cfg_ppp.if_key = "WIFI_STA_TEST_PPP";
78+
base_cfg_ppp.if_desc = TEST_NETIF_DESC_PPP;
79+
esp_netif_config_t cfg_ppp = {
80+
.base = &base_cfg_ppp,
81+
.driver = NULL,
82+
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA,
83+
};
84+
test_netif_ppp = esp_netif_new(&cfg_ppp);
85+
TEST_ASSERT_NOT_NULL(test_netif_ppp);
86+
87+
esp_netif_inherent_config_t base_cfg_other = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
88+
base_cfg_other.if_key = "WIFI_STA_TEST_OTHER";
89+
base_cfg_other.if_desc = TEST_NETIF_DESC_OTHER;
90+
esp_netif_config_t cfg_other = {
91+
.base = &base_cfg_other,
92+
.driver = NULL,
93+
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA,
94+
};
95+
test_netif_other = esp_netif_new(&cfg_other);
96+
TEST_ASSERT_NOT_NULL(test_netif_other);
97+
}
98+
99+
TEST_TEAR_DOWN(net_connect)
100+
{
101+
// Clean up test netifs
102+
if (test_netif_sta) {
103+
esp_netif_destroy(test_netif_sta);
104+
test_netif_sta = NULL;
105+
}
106+
if (test_netif_eth) {
107+
esp_netif_destroy(test_netif_eth);
108+
test_netif_eth = NULL;
109+
}
110+
if (test_netif_thread) {
111+
esp_netif_destroy(test_netif_thread);
112+
test_netif_thread = NULL;
113+
}
114+
if (test_netif_ppp) {
115+
esp_netif_destroy(test_netif_ppp);
116+
test_netif_ppp = NULL;
117+
}
118+
if (test_netif_other) {
119+
esp_netif_destroy(test_netif_other);
120+
test_netif_other = NULL;
121+
}
122+
123+
esp_event_loop_delete_default();
124+
test_utils_finish_and_evaluate_leaks(0, 0);
125+
}
126+
127+
/**
128+
* @brief Test that net_get_netif_from_desc() can successfully find a WiFi STA netif by its description
129+
*
130+
* Objective: Verify that the function correctly locates a network interface with description
131+
* "net_connect_netif_sta" and returns the correct netif pointer. This ensures basic lookup
132+
* functionality works for STA interfaces.
133+
*/
134+
TEST(net_connect, net_get_netif_from_desc_finds_sta)
135+
{
136+
esp_netif_t *found = net_get_netif_from_desc(TEST_NETIF_DESC_STA);
137+
TEST_ASSERT_NOT_NULL(found);
138+
TEST_ASSERT_EQUAL(test_netif_sta, found);
139+
TEST_ASSERT_EQUAL_STRING(TEST_NETIF_DESC_STA, esp_netif_get_desc(found));
140+
}
141+
142+
/**
143+
* @brief Test that net_get_netif_from_desc() can successfully find an Ethernet netif by its description
144+
*
145+
* Objective: Verify that the function correctly locates a network interface with description
146+
* "net_connect_netif_eth" and returns the correct netif pointer. This ensures lookup functionality
147+
* works for Ethernet interfaces.
148+
*/
149+
TEST(net_connect, net_get_netif_from_desc_finds_eth)
150+
{
151+
esp_netif_t *found = net_get_netif_from_desc(TEST_NETIF_DESC_ETH);
152+
TEST_ASSERT_NOT_NULL(found);
153+
TEST_ASSERT_EQUAL(test_netif_eth, found);
154+
TEST_ASSERT_EQUAL_STRING(TEST_NETIF_DESC_ETH, esp_netif_get_desc(found));
155+
}
156+
157+
/**
158+
* @brief Test that net_get_netif_from_desc() can successfully find a Thread netif by its description
159+
*
160+
* Objective: Verify that the function correctly locates a network interface with description
161+
* "net_connect_netif_thread" and returns the correct netif pointer. This ensures lookup functionality
162+
* works for Thread interfaces.
163+
*/
164+
TEST(net_connect, net_get_netif_from_desc_finds_thread)
165+
{
166+
esp_netif_t *found = net_get_netif_from_desc(TEST_NETIF_DESC_THREAD);
167+
TEST_ASSERT_NOT_NULL(found);
168+
TEST_ASSERT_EQUAL(test_netif_thread, found);
169+
TEST_ASSERT_EQUAL_STRING(TEST_NETIF_DESC_THREAD, esp_netif_get_desc(found));
170+
}
171+
172+
/**
173+
* @brief Test that net_get_netif_from_desc() can successfully find a PPP netif by its description
174+
*
175+
* Objective: Verify that the function correctly locates a network interface with description
176+
* "net_connect_netif_ppp" and returns the correct netif pointer. This ensures lookup functionality
177+
* works for PPP interfaces.
178+
*/
179+
TEST(net_connect, net_get_netif_from_desc_finds_ppp)
180+
{
181+
esp_netif_t *found = net_get_netif_from_desc(TEST_NETIF_DESC_PPP);
182+
TEST_ASSERT_NOT_NULL(found);
183+
TEST_ASSERT_EQUAL(test_netif_ppp, found);
184+
TEST_ASSERT_EQUAL_STRING(TEST_NETIF_DESC_PPP, esp_netif_get_desc(found));
185+
}
186+
187+
/**
188+
* @brief Test that net_get_netif_from_desc() can successfully find a netif with a custom description
189+
*
190+
* Objective: Verify that the function correctly locates a network interface with a custom description
191+
* "other_netif_desc" and returns the correct netif pointer. This ensures lookup functionality works
192+
* for interfaces with non-standard descriptions.
193+
*/
194+
TEST(net_connect, net_get_netif_from_desc_finds_other)
195+
{
196+
esp_netif_t *found = net_get_netif_from_desc(TEST_NETIF_DESC_OTHER);
197+
TEST_ASSERT_NOT_NULL(found);
198+
TEST_ASSERT_EQUAL(test_netif_other, found);
199+
TEST_ASSERT_EQUAL_STRING(TEST_NETIF_DESC_OTHER, esp_netif_get_desc(found));
200+
}
201+
202+
/**
203+
* @brief Test that net_get_netif_from_desc() returns NULL when searching for a non-existent netif description
204+
*
205+
* Objective: Verify that the function correctly handles the case where no network interface matches
206+
* the provided description. This ensures proper error handling when a netif doesn't exist.
207+
*/
208+
TEST(net_connect, net_get_netif_from_desc_returns_null_for_nonexistent)
209+
{
210+
esp_netif_t *found = net_get_netif_from_desc("nonexistent_netif_desc");
211+
TEST_ASSERT_NULL(found);
212+
}
213+
214+
/**
215+
* @brief Test that net_get_netif_from_desc() returns NULL when passed a NULL description pointer
216+
*
217+
* Objective: Verify that the function safely handles NULL input and returns NULL instead of
218+
* crashing or dereferencing a NULL pointer. This ensures robust error handling for invalid inputs.
219+
*/
220+
TEST(net_connect, net_get_netif_from_desc_returns_null_for_null_desc)
221+
{
222+
esp_netif_t *found = net_get_netif_from_desc(NULL);
223+
TEST_ASSERT_NULL(found);
224+
}
225+
226+
/**
227+
* @brief Test that net_get_netif_from_desc() returns NULL when passed an empty string description
228+
*
229+
* Objective: Verify that the function correctly handles empty string input and returns NULL.
230+
* This ensures that empty descriptions are treated as invalid and don't match any netif.
231+
*/
232+
TEST(net_connect, net_get_netif_from_desc_returns_null_for_empty_desc)
233+
{
234+
esp_netif_t *found = net_get_netif_from_desc("");
235+
TEST_ASSERT_NULL(found);
236+
}
237+
238+
/**
239+
* @brief Test that net_get_netif_from_desc() performs case-sensitive matching
240+
*
241+
* Objective: Verify that description matching is case-sensitive. An uppercase version of a valid
242+
* description should not match, while the exact case-sensitive description should match. This ensures
243+
* that the function requires exact string matches including case.
244+
*/
245+
TEST(net_connect, net_get_netif_from_desc_case_sensitive)
246+
{
247+
// Test that description matching is case-sensitive
248+
esp_netif_t *found_upper = net_get_netif_from_desc("NET_CONNECT_NETIF_STA");
249+
TEST_ASSERT_NULL(found_upper);
250+
251+
esp_netif_t *found_lower = net_get_netif_from_desc(TEST_NETIF_DESC_STA);
252+
TEST_ASSERT_NOT_NULL(found_lower);
253+
}
254+
255+
/**
256+
* @brief Test that net_get_netif_from_desc() requires exact string matches (no partial matching)
257+
*
258+
* Objective: Verify that the function only matches exact descriptions and rejects partial matches.
259+
* Both a prefix substring and a string with extra characters should fail to match. This ensures
260+
* that the lookup requires precise description strings.
261+
*/
262+
TEST(net_connect, net_get_netif_from_desc_partial_match_fails)
263+
{
264+
// Test that partial matches don't work (must be exact match)
265+
esp_netif_t *found = net_get_netif_from_desc("net_connect_netif_st");
266+
TEST_ASSERT_NULL(found);
267+
268+
found = net_get_netif_from_desc("net_connect_netif_sta_extra");
269+
TEST_ASSERT_NULL(found);
270+
}
271+
272+
/**
273+
* @brief Test that net_get_netif_from_desc() returns consistent results across multiple calls
274+
*
275+
* Objective: Verify that calling the function multiple times with the same description returns
276+
* the same netif pointer each time. This ensures the function's behavior is deterministic and
277+
* consistent, which is important for reliability in production code.
278+
*/
279+
TEST(net_connect, net_get_netif_from_desc_multiple_calls_same_result)
280+
{
281+
// Test that multiple calls return the same result
282+
esp_netif_t *found1 = net_get_netif_from_desc(TEST_NETIF_DESC_STA);
283+
esp_netif_t *found2 = net_get_netif_from_desc(TEST_NETIF_DESC_STA);
284+
esp_netif_t *found3 = net_get_netif_from_desc(TEST_NETIF_DESC_STA);
285+
286+
TEST_ASSERT_NOT_NULL(found1);
287+
TEST_ASSERT_EQUAL(found1, found2);
288+
TEST_ASSERT_EQUAL(found2, found3);
289+
TEST_ASSERT_EQUAL(test_netif_sta, found1);
290+
}
291+
292+
TEST_GROUP_RUNNER(net_connect)
293+
{
294+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_finds_sta);
295+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_finds_eth);
296+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_finds_thread);
297+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_finds_ppp);
298+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_finds_other);
299+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_returns_null_for_nonexistent);
300+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_returns_null_for_null_desc);
301+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_returns_null_for_empty_desc);
302+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_case_sensitive);
303+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_partial_match_fails);
304+
RUN_TEST_CASE(net_connect, net_get_netif_from_desc_multiple_calls_same_result);
305+
}
306+
307+
void app_main(void)
308+
{
309+
UNITY_MAIN(net_connect);
310+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
from pytest_embedded import Dut
5+
6+
7+
def test_net_connect(dut: Dut) -> None:
8+
dut.expect_unity_test_output()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CONFIG_IDF_TARGET="esp32"
2+
CONFIG_UNITY_ENABLE_FIXTURE=y
3+
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CONFIG_UNITY_ENABLE_FIXTURE=y
2+
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n

0 commit comments

Comments
 (0)