1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/types.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <zephyr/sys/printk.h>
13 #include <zephyr/linker/sections.h>
14
15 #include <zephyr/ztest.h>
16 #include <zephyr/net/net_if.h>
17 #include <zephyr/net/conn_mgr_monitor.h>
18 #include <zephyr/net/conn_mgr_connectivity.h>
19 #include <zephyr/net/conn_mgr_connectivity_impl.h>
20 #include "test_conn_impl.h"
21 #include "test_ifaces.h"
22
conn_mgr_if_get_data(struct net_if * iface)23 static inline struct test_conn_data *conn_mgr_if_get_data(struct net_if *iface)
24 {
25 struct conn_mgr_conn_binding *binding = conn_mgr_if_get_binding(iface);
26
27 if (!binding) {
28 return NULL;
29 }
30 return binding->ctx;
31 }
32
33 /**
34 * @brief Reset the network state of the provided iface.
35 *
36 * @param iface - iface to reset.
37 */
reset_test_iface_networking(struct net_if * iface)38 static void reset_test_iface_networking(struct net_if *iface)
39 {
40 if (net_if_is_admin_up(iface)) {
41 (void)net_if_down(iface);
42 }
43
44 /* Some tests can leave the iface in a bad state where it is admin-down but not dormant */
45 net_if_dormant_on(iface);
46 }
47
48 /**
49 * @brief Reset testing state for the provided iface.
50 *
51 * @param iface - iface to reset.
52 */
reset_test_iface_state(struct net_if * iface)53 static void reset_test_iface_state(struct net_if *iface)
54 {
55 struct conn_mgr_conn_binding *iface_binding = conn_mgr_if_get_binding(iface);
56 struct test_conn_data *iface_data = conn_mgr_if_get_data(iface);
57
58 /* Some tests mark ifaces as ignored, this must be reset between each test. */
59 conn_mgr_watch_iface(iface);
60
61 if (iface_binding) {
62 /* Reset all flags and settings for the binding */
63 iface_binding->flags = 0;
64 iface_binding->timeout = CONN_MGR_IF_NO_TIMEOUT;
65
66 /* Disable auto-connect and auto-down */
67 conn_mgr_if_set_flag(iface, CONN_MGR_IF_NO_AUTO_CONNECT, true);
68 conn_mgr_if_set_flag(iface, CONN_MGR_IF_NO_AUTO_DOWN, true);
69 }
70
71 if (iface_data) {
72 iface_data->call_cnt_a = 0;
73 iface_data->call_cnt_b = 0;
74 iface_data->conn_bal = 0;
75 iface_data->api_err = 0;
76 iface_data->fatal_error = 0;
77 iface_data->timeout = false;
78 memset(iface_data->data_x, 0, sizeof(iface_data->data_x));
79 memset(iface_data->data_y, 0, sizeof(iface_data->data_y));
80 }
81 }
82
83
84 /* NET_MGMT event tracking */
85
86 static K_MUTEX_DEFINE(event_mutex);
87 static struct event_stats {
88 int timeout_count;
89 int fatal_error_count;
90 int event_count;
91 int event_info;
92 struct net_if *event_iface;
93 } test_event_stats;
94
95 struct net_mgmt_event_callback conn_mgr_conn_callback;
96
conn_mgr_conn_handler(struct net_mgmt_event_callback * cb,uint32_t event,struct net_if * iface)97 static void conn_mgr_conn_handler(struct net_mgmt_event_callback *cb,
98 uint32_t event, struct net_if *iface)
99 {
100 k_mutex_lock(&event_mutex, K_FOREVER);
101
102 if (event == NET_EVENT_CONN_IF_TIMEOUT) {
103 test_event_stats.timeout_count += 1;
104 } else if (event == NET_EVENT_CONN_IF_FATAL_ERROR) {
105 test_event_stats.fatal_error_count += 1;
106 }
107
108 test_event_stats.event_count += 1;
109 test_event_stats.event_iface = iface;
110
111 if (cb->info) {
112 test_event_stats.event_info = *((int *)cb->info);
113 } else {
114 test_event_stats.event_info = 0;
115 }
116
117 k_mutex_unlock(&event_mutex);
118 }
119
conn_mgr_conn_before(void * data)120 static void conn_mgr_conn_before(void *data)
121 {
122 ARG_UNUSED(data);
123 reset_test_iface_networking(ifa1);
124 reset_test_iface_networking(ifa2);
125 reset_test_iface_networking(ifb);
126 reset_test_iface_networking(ifni);
127 reset_test_iface_networking(ifnone);
128 reset_test_iface_networking(ifnull);
129
130 /* Allow any triggered events to shake out */
131 k_sleep(SIMULATED_EVENT_WAIT_TIME);
132
133 reset_test_iface_state(ifa1);
134 reset_test_iface_state(ifa2);
135 reset_test_iface_state(ifb);
136 reset_test_iface_state(ifni);
137 reset_test_iface_state(ifnone);
138 reset_test_iface_state(ifnull);
139
140 k_mutex_lock(&event_mutex, K_FOREVER);
141
142 test_event_stats.event_count = 0;
143 test_event_stats.timeout_count = 0;
144 test_event_stats.fatal_error_count = 0;
145 test_event_stats.event_iface = NULL;
146 test_event_stats.event_info = 0;
147
148 k_mutex_unlock(&event_mutex);
149 }
150
conn_mgr_conn_setup(void)151 static void *conn_mgr_conn_setup(void)
152 {
153 net_mgmt_init_event_callback(&conn_mgr_conn_callback, conn_mgr_conn_handler,
154 NET_EVENT_CONN_IF_TIMEOUT | NET_EVENT_CONN_IF_FATAL_ERROR);
155 net_mgmt_add_event_callback(&conn_mgr_conn_callback);
156 return NULL;
157 }
158
159 /* This suite uses k_sleep(K_MSEC(1)) to allow Zephyr to perform event propagation.
160 * This is not guaranteed to execute in the fastest possible time, nor is it technically guaranteed
161 * that Zephyr will finish its operations in less than a millisecond, but for this test suite,
162 * event propagation times longer than a millisecond would be a sign of a problem,
163 * a few milliseconds of delay are miniscule compared to the time it takes to build the suite,
164 * and using k_sleep has the advantage of being completely agnostic to the underlying operation
165 * of the events.
166 */
167
168 /* Verify that the correct init APIs were called. */
ZTEST(conn_mgr_conn,test_inspect_init)169 ZTEST(conn_mgr_conn, test_inspect_init)
170 {
171 /* This isn't a proper test in that it only verifies the result of an exterior operation,
172 * but it increases coverage and costs next to nothing to add.
173 */
174 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
175 struct test_conn_data *ifa2_data = conn_mgr_if_get_data(ifa2);
176 struct test_conn_data *ifb_data = conn_mgr_if_get_data(ifb);
177 struct test_conn_data *ifni_data = conn_mgr_if_get_data(ifni);
178
179
180 zassert_equal(ifa1_data->init_calls_a, 1, "ifa1->init should be called exactly once.");
181 zassert_equal(ifa1_data->init_calls_b, 0, "ifa1 should use implementation A");
182
183 zassert_equal(ifa2_data->init_calls_a, 1, "ifa2->init should be called exactly once.");
184 zassert_equal(ifa2_data->init_calls_b, 0, "ifa2 should use implementation A");
185
186 zassert_equal(ifb_data->init_calls_b, 1, "ifb->init should be called exactly once.");
187 zassert_equal(ifb_data->init_calls_a, 0, "ifb should use implementation B");
188
189 zassert_equal(ifni_data->init_calls_a, 0, "ifni->init should not be called.");
190 zassert_equal(ifni_data->init_calls_b, 0, "ifni->init should not be called.");
191 }
192
193 /* Verify that conn_mgr_if_connect and conn_mgr_if_disconnect perform the
194 * correct API calls to the correct interfaces and connectivity implementations
195 */
ZTEST(conn_mgr_conn,test_connect_disconnect)196 ZTEST(conn_mgr_conn, test_connect_disconnect)
197 {
198 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
199 struct test_conn_data *ifa2_data = conn_mgr_if_get_data(ifa2);
200 struct test_conn_data *ifb_data = conn_mgr_if_get_data(ifb);
201
202 /* Take all ifaces up */
203 zassert_equal(net_if_up(ifa1), 0, "net_if_up should not fail");
204 zassert_equal(net_if_up(ifa2), 0, "net_if_up should not fail");
205 zassert_equal(net_if_up(ifb), 0, "net_if_up should not fail");
206 k_sleep(K_MSEC(1));
207
208 /* Verify ifaces are still disconnected */
209 zassert_false(net_if_is_up(ifa1), "Ifaces must be disconnected before test");
210 zassert_false(net_if_is_up(ifa2), "Ifaces must be disconnected before test");
211 zassert_false(net_if_is_up(ifb), "Ifaces must be disconnected before test");
212
213 /* Connect one of the A ifaces */
214 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should not fail");
215 k_sleep(K_MSEC(1));
216
217 /* Verify success, and that only the target iface/conn impl were affected/invoked */
218 zassert_true(net_if_is_up(ifa1), "ifa1 should be oper-up after conn_mgr_if_connect");
219 zassert_false(net_if_is_up(ifa2), "ifa2 should not be affected by ifa1");
220 zassert_false(net_if_is_up(ifb), "ifb should not be affected by ifa1");
221
222 /* Verify that all ifaces have the expected call counts and types */
223 zassert_equal(ifa1_data->conn_bal, 1, "ifa1->connect should be called once");
224 zassert_equal(ifa1_data->call_cnt_a, 1, "Implementation A should be used for ifa1");
225 zassert_equal(ifa1_data->call_cnt_b, 0, "Implementation A should be used for ifa1");
226
227 zassert_equal(ifa2_data->conn_bal, 0, "ifa2 should not be affected by ifa1");
228 zassert_equal(ifa2_data->call_cnt_a, 0, "ifa2 should not be affected by ifa1");
229 zassert_equal(ifa2_data->call_cnt_b, 0, "ifa2 should not be affected by ifa1");
230
231 zassert_equal(ifb_data->conn_bal, 0, "ifb should not be affected by ifa1");
232 zassert_equal(ifb_data->call_cnt_a, 0, "ifb should not be affected by ifa1");
233 zassert_equal(ifb_data->call_cnt_b, 0, "ifb should not be affected by ifa1");
234
235 /* Now connect the B iface */
236 zassert_equal(conn_mgr_if_connect(ifb), 0, "conn_mgr_if_connect should not fail");
237 k_sleep(K_MSEC(1));
238
239 /* Verify success, and that only the target iface/conn impl were affected/invoked */
240 zassert_true(net_if_is_up(ifa1), "ifa1 should still be connected");
241 zassert_false(net_if_is_up(ifa2), "ifa2 should not be affected by ifb");
242 zassert_true(net_if_is_up(ifb), "ifb should be oper-up after conn_mgr_if_connect");
243
244 /* Verify that all ifaces have the expected call counts and types */
245 zassert_equal(ifa1_data->conn_bal, 1, "ifa1 should not be affected by ifb");
246 zassert_equal(ifa1_data->call_cnt_a, 1, "ifa1 should not be affected by ifb");
247 zassert_equal(ifa1_data->call_cnt_b, 0, "ifa1 should not be affected by ifb");
248
249 zassert_equal(ifa2_data->conn_bal, 0, "ifa2 should not be affected by ifb");
250 zassert_equal(ifa2_data->call_cnt_a, 0, "ifa2 should not be affected by ifb");
251 zassert_equal(ifa2_data->call_cnt_b, 0, "ifa2 should not be affected by ifb");
252
253 zassert_equal(ifb_data->conn_bal, 1, "ifb->connect should be called once");
254 zassert_equal(ifb_data->call_cnt_a, 0, "Implementation B should be used for ifb");
255 zassert_equal(ifb_data->call_cnt_b, 1, "Implementation B should be used for ifb");
256
257 /* Now connect the other A iface */
258 zassert_equal(conn_mgr_if_connect(ifa2), 0, "conn_mgr_if_connect should not fail");
259 k_sleep(K_MSEC(1));
260
261 /* Verify success, and that only the target iface/conn impl were affected/invoked */
262 zassert_true(net_if_is_up(ifa1), "ifa1 should still be connected");
263 zassert_true(net_if_is_up(ifa2), "ifa2 should be oper-up after conn_mgr_if_connect");
264 zassert_true(net_if_is_up(ifb), "ifb should still be connected");
265
266 /* Verify that all ifaces have the expected call counts and types */
267 zassert_equal(ifa1_data->conn_bal, 1, "ifa1 should not be affected by ifa2");
268 zassert_equal(ifa1_data->call_cnt_a, 1, "ifa1 should not be affected by ifa2");
269 zassert_equal(ifa1_data->call_cnt_b, 0, "ifa1 should not be affected by ifa2");
270
271 zassert_equal(ifa2_data->conn_bal, 1, "ifa2->connect should be called once");
272 zassert_equal(ifa2_data->call_cnt_a, 1, "Implementation A should be used for ifa2");
273 zassert_equal(ifa2_data->call_cnt_b, 0, "Implementation A should be used for ifa2");
274
275 zassert_equal(ifb_data->conn_bal, 1, "ifb should not be affected by ifa2");
276 zassert_equal(ifb_data->call_cnt_a, 0, "ifb should not be affected by ifa2");
277 zassert_equal(ifb_data->call_cnt_b, 1, "ifb should not be affected by ifa2");
278
279 /* Now disconnect the original A iface */
280 zassert_equal(conn_mgr_if_disconnect(ifa1), 0, "conn_mgr_if_disconnect should not fail");
281 k_sleep(K_MSEC(1));
282
283
284 /* Verify success, and that only the target iface/conn impl were affected/invoked */
285 zassert_false(net_if_is_up(ifa1), "ifa1 should be oper-down after conn_mgr_if_disconnect");
286 zassert_true(net_if_is_up(ifa2), "ifa2 should not be affected by ifa1");
287 zassert_true(net_if_is_up(ifb), "ifb should not be affected by ifa1");
288
289 /* Verify that all ifaces have the expected call counts and types */
290 zassert_equal(ifa1_data->conn_bal, 0, "ifa1->disconnect should be called once");
291 zassert_equal(ifa1_data->call_cnt_a, 2, "Implementation A should be used for ifa1");
292 zassert_equal(ifa1_data->call_cnt_b, 0, "Implementation A should be used for ifa1");
293
294 zassert_equal(ifa2_data->conn_bal, 1, "ifa2 should not be affected by ifa1");
295 zassert_equal(ifa2_data->call_cnt_a, 1, "ifa2 should not be affected by ifa1");
296 zassert_equal(ifa2_data->call_cnt_b, 0, "ifa2 should not be affected by ifa1");
297
298 zassert_equal(ifb_data->conn_bal, 1, "ifb should not be affected by ifa1");
299 zassert_equal(ifb_data->call_cnt_a, 0, "ifb should not be affected by ifa1");
300 zassert_equal(ifb_data->call_cnt_b, 1, "ifb should not be affected by ifa1");
301
302 /* Now disconnect the B iface */
303 zassert_equal(conn_mgr_if_disconnect(ifb), 0, "conn_mgr_if_disconnect should not fail");
304 k_sleep(K_MSEC(1));
305
306
307 /* Verify success, and that only the target iface/conn impl were affected/invoked */
308 zassert_false(net_if_is_up(ifa1), "ifa1 should still be disconnected");
309 zassert_true(net_if_is_up(ifa2), "ifa2 should not be affected by ifb");
310 zassert_false(net_if_is_up(ifb), "ifb should be oper-down after conn_mgr_if_disconnect");
311
312 /* Verify that all ifaces have the expected call counts and types */
313 zassert_equal(ifa1_data->conn_bal, 0, "ifa1 should not be affected by ifb");
314 zassert_equal(ifa1_data->call_cnt_a, 2, "ifa1 should not be affected by ifb");
315 zassert_equal(ifa1_data->call_cnt_b, 0, "ifa1 should not be affected by ifb");
316
317 zassert_equal(ifa2_data->conn_bal, 1, "ifa1 should not be affected by ifb");
318 zassert_equal(ifa2_data->call_cnt_a, 1, "ifa1 should not be affected by ifb");
319 zassert_equal(ifa2_data->call_cnt_b, 0, "ifa1 should not be affected by ifb");
320
321 zassert_equal(ifb_data->conn_bal, 0, "ifa1->disconnect should be called once");
322 zassert_equal(ifb_data->call_cnt_a, 0, "Implementation B should be used for ifb");
323 zassert_equal(ifb_data->call_cnt_b, 2, "Implementation B should be used for ifb");
324
325 /* Finally, disconnect the last A iface */
326 zassert_equal(conn_mgr_if_disconnect(ifa2), 0, "conn_mgr_if_disconnect should not fail");
327 k_sleep(K_MSEC(1));
328
329
330 /* Verify success, and that only the target iface/conn impl were affected/invoked */
331 zassert_false(net_if_is_up(ifa1), "ifa1 should still be disconnected");
332 zassert_false(net_if_is_up(ifa2), "ifa2 should be oper-down after conn_mgr_if_disconnect");
333 zassert_false(net_if_is_up(ifb), "ifb should still be disconnected");
334
335 /* Verify that all ifaces have the expected call counts and types */
336 zassert_equal(ifa1_data->conn_bal, 0, "ifa1 should not be affected by ifa2");
337 zassert_equal(ifa1_data->call_cnt_a, 2, "ifa1 should not be affected by ifa2");
338 zassert_equal(ifa1_data->call_cnt_b, 0, "ifa1 should not be affected by ifa2");
339
340 zassert_equal(ifa2_data->conn_bal, 0, "ifa2->disconnect should be called once");
341 zassert_equal(ifa2_data->call_cnt_a, 2, "Implementation A should be used for ifa2");
342 zassert_equal(ifa2_data->call_cnt_b, 0, "Implementation A should be used for ifa2");
343
344 zassert_equal(ifb_data->conn_bal, 0, "ifb should not be affected by ifa2");
345 zassert_equal(ifb_data->call_cnt_a, 0, "ifb should not be affected by ifa2");
346 zassert_equal(ifb_data->call_cnt_b, 2, "ifb should not be affected by ifa2");
347 }
348
349 /* Verify that double calls to conn_mgr_if_connect and conn_mgr_if_disconnect cause no problems */
ZTEST(conn_mgr_conn,test_connect_disconnect_double_delayed)350 ZTEST(conn_mgr_conn, test_connect_disconnect_double_delayed)
351 {
352 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
353
354 /* Take iface up */
355 zassert_equal(net_if_up(ifa1), 0, "net_if_up should not fail");
356
357 /* Connect iface */
358 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should not fail");
359 k_sleep(K_MSEC(1));
360
361 /* Verify success */
362 zassert_true(net_if_is_up(ifa1), "ifa1 should be oper-up after conn_mgr_if_connect");
363 zassert_equal(ifa1_data->conn_bal, 1, "ifa1->connect should have been called once.");
364 zassert_equal(ifa1_data->call_cnt_a, 1, "ifa1->connect should have been called once.");
365
366 /* Connect iface again */
367 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should not fail");
368 k_sleep(K_MSEC(1));
369
370 /* Verify success
371 * To be clear: Yes, ifa1->connect should be called twice. It is up to the L2
372 * connectivity implementation to either handle idempotence
373 */
374 zassert_true(net_if_is_up(ifa1), "ifa1 should still be connected");
375 zassert_equal(ifa1_data->conn_bal, 2, "ifa1->connect should have been called again.");
376 zassert_equal(ifa1_data->call_cnt_a, 2, "ifa1->connect should have been called again.");
377
378 /* Now disconnect the iface */
379 zassert_equal(conn_mgr_if_disconnect(ifa1), 0, "conn_mgr_if_disconnect should not fail");
380 k_sleep(K_MSEC(1));
381
382 /* Verify success */
383 zassert_false(net_if_is_up(ifa1), "ifa1 should be oper-down after conn_mgr_if_disconnect");
384 zassert_equal(ifa1_data->conn_bal, 1, "ifa1->disconnect should have been called once.");
385 zassert_equal(ifa1_data->call_cnt_a, 3, "ifa1->disconnect should have been called once.");
386
387 /* Disconnect again! */
388 zassert_equal(conn_mgr_if_disconnect(ifa1), 0, "conn_mgr_if_disconnect should not fail");
389 k_sleep(K_MSEC(1));
390
391 /* Verify success */
392 zassert_false(net_if_is_up(ifa1), "ifa1 should be oper-down after conn_mgr_if_disconnect");
393 zassert_equal(ifa1_data->conn_bal, 0, "ifa1->disconnect should have been called again.");
394 zassert_equal(ifa1_data->call_cnt_a, 4, "ifa1->disconnect should have been called again.");
395 }
396
397 /* Verify that fast double calls to conn_mgr_if_connect and conn_mgr_if_disconnect
398 * do not fail
399 */
ZTEST(conn_mgr_conn,test_connect_disconnect_double_instant)400 ZTEST(conn_mgr_conn, test_connect_disconnect_double_instant)
401 {
402 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
403
404 /* Take iface up */
405 zassert_equal(net_if_up(ifa1), 0, "net_if_up should not fail");
406
407 /* Connect twice */
408 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should not fail");
409 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should not fail");
410 k_sleep(K_MSEC(1));
411
412 /* Verify success */
413 zassert_true(net_if_is_up(ifa1), "ifa1 should be oper-up after conn_mgr_if_connect");
414 zassert_equal(ifa1_data->conn_bal, 2, "ifa1->connect should have been called once.");
415 zassert_equal(ifa1_data->call_cnt_a, 2, "ifa1->connect should have been called once.");
416
417 /* Now disconnect twice */
418 zassert_equal(conn_mgr_if_disconnect(ifa1), 0, "conn_mgr_if_disconnect should not fail");
419 zassert_equal(conn_mgr_if_disconnect(ifa1), 0, "conn_mgr_if_disconnect should not fail");
420 k_sleep(K_MSEC(1));
421
422 /* Verify success */
423 zassert_false(net_if_is_up(ifa1), "ifa1 should be oper-down after conn_mgr_if_disconnect");
424 zassert_equal(ifa1_data->conn_bal, 0, "ifa1->disconnect should have been called once.");
425 zassert_equal(ifa1_data->call_cnt_a, 4, "ifa1->disconnect should have been called once.");
426 }
427
428 /* Verify that calling connect on a down iface automatically takes the iface up. */
ZTEST(conn_mgr_conn,test_connect_autoup)429 ZTEST(conn_mgr_conn, test_connect_autoup)
430 {
431 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
432
433 /* Connect iface */
434 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should not fail");
435 k_sleep(K_MSEC(1));
436
437 /* Verify net_if_up was called */
438 zassert_true(net_if_is_admin_up(ifa1), "ifa1 should be admin-up after conn_mgr_if_connect");
439
440 /* Verify that connection succeeds */
441 zassert_true(net_if_is_up(ifa1), "ifa1 should be oper-up after conn_mgr_if_connect");
442 zassert_equal(ifa1_data->conn_bal, 1, "ifa1->connect should have been called once.");
443 zassert_equal(ifa1_data->call_cnt_a, 1, "ifa1->connect should have been called once.");
444 }
445
446 /* Verify that calling disconnect on a down iface has no effect and raises no error. */
ZTEST(conn_mgr_conn,test_disconnect_down)447 ZTEST(conn_mgr_conn, test_disconnect_down)
448 {
449 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
450
451 /* Disconnect iface */
452 zassert_equal(conn_mgr_if_disconnect(ifa1), 0, "conn_mgr_if_disconnect should not fail.");
453 k_sleep(K_MSEC(1));
454
455 /* Verify iface is still down */
456 zassert_false(net_if_is_admin_up(ifa1), "ifa1 should be still be admin-down.");
457
458 /* Verify that no callbacks were fired */
459 zassert_equal(ifa1_data->conn_bal, 0, "No callbacks should have been fired.");
460 zassert_equal(ifa1_data->call_cnt_a, 0, "No callbacks should have been fired.");
461 }
462
463 /**
464 * Verify that invalid bound ifaces are treated as though they are not bound at all.
465 */
ZTEST(conn_mgr_conn,test_invalid_ignored)466 ZTEST(conn_mgr_conn, test_invalid_ignored)
467 {
468 zassert_is_null(conn_mgr_if_get_binding(ifnull));
469 zassert_is_null(conn_mgr_if_get_binding(ifnone));
470 zassert_false(conn_mgr_if_is_bound(ifnull));
471 zassert_false(conn_mgr_if_is_bound(ifnone));
472 }
473
474 /* Verify that connecting an iface that isn't up, missing an API,
475 * or isn't connectivity-bound raises an error.
476 */
ZTEST(conn_mgr_conn,test_connect_invalid)477 ZTEST(conn_mgr_conn, test_connect_invalid)
478 {
479 /* Bring ifnull and ifnone up */
480 zassert_equal(net_if_up(ifnull), 0, "net_if_up should succeed for ifnull");
481 zassert_equal(net_if_up(ifnone), 0, "net_if_up should succeed for ifnone");
482
483 /* Attempts to connect ifnull should fail, even if it is up */
484 zassert_equal(conn_mgr_if_connect(ifnull), -ENOTSUP,
485 "conn_mgr_if_connect should give -ENOTSUP for ifnull");
486
487 /* Attempts to connect ifnone should fail, even if it is up */
488 zassert_equal(conn_mgr_if_connect(ifnone), -ENOTSUP,
489 "conn_mgr_if_connect should give -ENOTSUP for ifnone");
490 }
491
492 /* Verify that disconnecting an iface that isn't up, missing an API,
493 * or isn't connectivity-bound raises an error.
494 */
ZTEST(conn_mgr_conn,test_disconnect_invalid)495 ZTEST(conn_mgr_conn, test_disconnect_invalid)
496 {
497 /* Bring ifnull and ifnone up */
498 zassert_equal(net_if_up(ifnull), 0, "net_if_up should succeed for ifnull");
499 zassert_equal(net_if_up(ifnone), 0, "net_if_up should succeed for ifnone");
500
501 /* Attempts to disconnect ifnull should fail, even if it is up */
502 zassert_equal(conn_mgr_if_disconnect(ifnull), -ENOTSUP,
503 "conn_mgr_if_disconnect should give -ENOTSUP for ifnull");
504
505 /* Attempts to disconnect ifnone should fail, even if it is up */
506 zassert_equal(conn_mgr_if_disconnect(ifnone), -ENOTSUP,
507 "conn_mgr_if_disconnect should give -ENOTSUP for ifnone");
508 }
509
510 /* Verify that conn_mgr_if_connect forwards error codes from API */
ZTEST(conn_mgr_conn,test_connect_fail)511 ZTEST(conn_mgr_conn, test_connect_fail)
512 {
513 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
514
515 /* Instruct ifa1 to fail on connect attempt */
516 ifa1_data->api_err = -ECHILD;
517
518 /* Take ifa1 up before attempting to connect */
519 zassert_equal(net_if_up(ifa1), 0,
520 "conn_mgr_if_connect should succeed");
521
522 /* Attempts to connect ifa1 should return the expected error*/
523 zassert_equal(conn_mgr_if_connect(ifa1), -ECHILD,
524 "conn_mgr_if_connect should give -ECHILD");
525 }
526
527 /* Verify that conn_mgr_if_disconnect forwards error codes from API */
ZTEST(conn_mgr_conn,test_disconnect_fail)528 ZTEST(conn_mgr_conn, test_disconnect_fail)
529 {
530 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
531
532 /* Take up and connect iface first */
533 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed");
534 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should succeed");
535
536 /* Instruct ifa1 to fail on disconnect attempt */
537 ifa1_data->api_err = -EDOM;
538
539 /* Attempts to disconnect ifa1 should return the expected error*/
540 zassert_equal(conn_mgr_if_disconnect(ifa1), -EDOM,
541 "conn_mgr_if_disconnect should give -EDOM");
542 }
543
544 /* Verify that the NET_EVENT_CONN_IF_TIMEOUT event works as expected. */
ZTEST(conn_mgr_conn,test_connect_timeout)545 ZTEST(conn_mgr_conn, test_connect_timeout)
546 {
547 struct event_stats stats;
548 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
549
550 /* instruct ifa1 to timeout on connect */
551 ifa1_data->timeout = true;
552
553 /* Take up and attempt to connect iface */
554 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed");
555
556 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should succeed");
557
558 /* Confirm iface is not immediately connected */
559 zassert_false(net_if_is_up(ifa1), "ifa1 should not be up if instructed to time out");
560
561 /* Ensure timeout event is fired */
562 k_sleep(SIMULATED_EVENT_WAIT_TIME);
563
564 k_mutex_lock(&event_mutex, K_FOREVER);
565 stats = test_event_stats;
566 k_mutex_unlock(&event_mutex);
567
568 zassert_equal(stats.timeout_count, 1,
569 "NET_EVENT_CONN_IF_TIMEOUT should have been fired");
570 zassert_equal(stats.event_count, 1,
571 "only NET_EVENT_CONN_IF_TIMEOUT should have been fired");
572 zassert_equal(stats.event_iface, ifa1,
573 "Timeout event should be raised on ifa1");
574 }
575
576 /* Verify that the NET_EVENT_CONN_IF_FATAL_ERROR event works as expected. */
ZTEST(conn_mgr_conn,test_connect_fatal_error)577 ZTEST(conn_mgr_conn, test_connect_fatal_error)
578 {
579 struct event_stats stats;
580 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
581
582 /* instruct ifa1 to have fatal error on connect. */
583 ifa1_data->fatal_error = -EADDRINUSE;
584
585 /* Take up and attempt to connect iface */
586 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed");
587 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should succeed");
588
589 /* Confirm iface is not immediately connected */
590 zassert_false(net_if_is_up(ifa1), "ifa1 should not be up if instructed to time out");
591
592 /* Ensure fatal_error event is fired */
593 k_sleep(SIMULATED_EVENT_WAIT_TIME);
594
595 k_mutex_lock(&event_mutex, K_FOREVER);
596 stats = test_event_stats;
597 k_mutex_unlock(&event_mutex);
598
599 zassert_equal(stats.fatal_error_count, 1,
600 "NET_EVENT_CONN_IF_FATAL_ERROR should have been fired");
601 zassert_equal(stats.event_count, 1,
602 "only NET_EVENT_CONN_IF_FATAL_ERROR should have been fired");
603 zassert_equal(stats.event_iface, ifa1,
604 "Fatal error event should be raised on ifa1");
605 zassert_equal(stats.event_info, -EADDRINUSE,
606 "Fatal error info should be -EADDRINUSE");
607 }
608
609
610
611 /* Verify that conn_mgr_if_is_bound gives correct results */
ZTEST(conn_mgr_conn,test_supports_connectivity)612 ZTEST(conn_mgr_conn, test_supports_connectivity)
613 {
614 zassert_true(conn_mgr_if_is_bound(ifa1));
615 zassert_true(conn_mgr_if_is_bound(ifa2));
616 zassert_true(conn_mgr_if_is_bound(ifb));
617 zassert_false(conn_mgr_if_is_bound(ifnull));
618 zassert_false(conn_mgr_if_is_bound(ifnone));
619 }
620
621 /* 60 characters long */
622 #define TEST_STR_LONG "AAAAAaaaaaBBBBBbbbbbCCCCCcccccDDDDDdddddEEEEEeeeeeFFFFFfffff"
623
624 /* Verify that conn_opt get/set functions operate correctly and affect only the target iface */
ZTEST(conn_mgr_conn,test_conn_opt)625 ZTEST(conn_mgr_conn, test_conn_opt)
626 {
627 char buf[100];
628 size_t buf_len = 0;
629
630 /* Set ifa1->X to "A" */
631 strcpy(buf, "A");
632 zassert_equal(conn_mgr_if_set_opt(ifa1, TEST_CONN_OPT_X, &buf, strlen(buf) + 1), 0,
633 "conn_mgr_if_set_opt should succeed for valid parameters");
634
635 /* Verify success */
636 memset(buf, 0, sizeof(buf));
637 buf_len = sizeof(buf);
638 zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_X, &buf, &buf_len),
639 0, "conn_mgr_if_get_opt should succeed for valid parameters");
640 printk("%d, %d", buf_len, strlen(buf) + 1);
641 zassert_equal(buf_len, strlen(buf) + 1, "conn_mgr_if_get_opt should return valid optlen");
642 zassert_str_equal(buf, "A",
643 "conn_mgr_if_get_opt should retrieve \"A\"");
644
645 /* Verify that ifa1->Y was not affected */
646 memset(buf, 0, sizeof(buf));
647 buf_len = sizeof(buf);
648 zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_Y, &buf, &buf_len),
649 0, "conn_mgr_if_get_opt should succeed for valid parameters");
650 zassert_equal(buf_len, 1, "conn_mgr_if_get_opt should yield nothing for ifa1->Y");
651 zassert_equal(buf[0], 0, "conn_mgr_if_get_opt should yield nothing for ifa1->Y");
652
653 /* Verify that ifa2->X was not affected */
654 memset(buf, 0, sizeof(buf));
655 buf_len = sizeof(buf);
656 zassert_equal(conn_mgr_if_get_opt(ifa2, TEST_CONN_OPT_X, &buf, &buf_len),
657 0, "conn_mgr_if_get_opt should succeed for valid parameters");
658 zassert_equal(buf_len, 1, "conn_mgr_if_get_opt should yield nothing for ifa2->X");
659 zassert_equal(buf[0], 0, "conn_mgr_if_get_opt should yield nothing for ifa2->X");
660
661 /* Now, set ifa->Y to "ABC" */
662 strcpy(buf, "ABC");
663 zassert_equal(conn_mgr_if_set_opt(ifa1, TEST_CONN_OPT_Y, &buf, strlen(buf) + 1), 0,
664 "conn_mgr_if_set_opt should succeed for valid parameters");
665
666 /* Verify success */
667 memset(buf, 0, sizeof(buf));
668 buf_len = sizeof(buf);
669 zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_Y, &buf, &buf_len),
670 0, "conn_mgr_if_get_opt should succeed for valid parameters");
671 zassert_equal(buf_len, strlen(buf) + 1, "conn_mgr_if_get_opt should return valid optlen");
672 zassert_str_equal(buf, "ABC",
673 "conn_mgr_if_get_opt should retrieve \"ABC\"");
674
675 /* Verify that ifa1->X was not affected */
676 memset(buf, 0, sizeof(buf));
677 buf_len = sizeof(buf);
678 zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_X, &buf, &buf_len),
679 0, "conn_mgr_if_get_opt should succeed for valid parameters");
680 zassert_equal(buf_len, strlen(buf) + 1, "conn_mgr_if_get_opt should return valid optlen");
681 zassert_str_equal(buf, "A",
682 "conn_mgr_if_get_opt should retrieve \"A\"");
683
684 /* Next, we pass some buffers that are too large or too small.
685 * This is an indirect way of verifying that buf_len is passed correctly.
686 */
687
688 /* Try writing a string that is too large to ifa1->X */
689 strcpy(buf, TEST_STR_LONG);
690 zassert_equal(conn_mgr_if_set_opt(ifa1, TEST_CONN_OPT_X, &buf, strlen(buf) + 1), 0,
691 "conn_mgr_if_set_opt should succeed for valid parameters");
692
693 /* Verify partial success */
694 memset(buf, 0, sizeof(buf));
695 buf_len = sizeof(buf);
696 zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_X, &buf, &buf_len), 0,
697 "conn_mgr_if_get_opt should succeed for valid parameters");
698 zassert_equal(buf_len, strlen(buf) + 1,
699 "conn_mgr_if_get_opt should return valid optlen");
700
701 /* This does, technically, test the test harness, but this test will fail if
702 * the unit under test (conn_mgr_if_set_opt) fails to pass along the optlen
703 */
704 zassert_true(strlen(buf) < strlen(TEST_STR_LONG),
705 "test_set_opt_a should truncate long values");
706
707 /* For the same reason, verify that get_opt truncates given a small destination buffer */
708 memset(buf, 0, sizeof(buf));
709 buf_len = 10;
710 zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_X, &buf, &buf_len), 0,
711 "conn_mgr_if_get_opt should succeed for valid parameters");
712 zassert_equal(buf_len, strlen(buf) + 1,
713 "conn_mgr_if_get_opt should return valid optlen");
714 zassert_equal(buf_len, 10,
715 "test_get_opt_a should truncate if dest. buffer is too small.");
716 }
717
718 /* Verify that conn_mgr_if_get_opt and conn_mgr_if_set_opt behave as expected when given invalid
719 * arguments.
720 */
ZTEST(conn_mgr_conn,test_conn_opt_invalid)721 ZTEST(conn_mgr_conn, test_conn_opt_invalid)
722 {
723 char buf[100];
724 size_t buf_len;
725
726 /* Verify that getting/setting non-existent option on ifa1 fails */
727 zassert_equal(conn_mgr_if_set_opt(ifa1, -1, "A", strlen("A")), -ENOPROTOOPT,
728 "conn_mgr_if_set_opt should fail with invalid optname");
729 buf_len = sizeof(buf_len);
730 zassert_equal(conn_mgr_if_get_opt(ifa1, -1, buf, &buf_len), -ENOPROTOOPT,
731 "conn_mgr_if_get_opt should fail with invalid optname");
732 zassert_equal(buf_len, 0, "failed conn_mgr_if_get_opt should always set buf_len to zero.");
733
734 /* Verify that getting/setting with NULL buffer on ifa1 fails */
735 zassert_equal(conn_mgr_if_set_opt(ifa1, TEST_CONN_OPT_X, NULL, 100), -EINVAL,
736 "conn_mgr_if_set_opt should fail with invalid buffer");
737 buf_len = sizeof(buf_len);
738 zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_X, NULL, &buf_len), -EINVAL,
739 "conn_mgr_if_get_opt should fail with invalid buffer");
740 zassert_equal(buf_len, 0, "failed conn_mgr_if_get_opt should always set buf_len to zero.");
741
742 /* Verify that getting with NULL buffer length on ifa1 fails */
743 zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_X, buf, NULL), -EINVAL,
744 "conn_mgr_if_get_opt should fail with invalid buffer length");
745
746 /* Verify that getting/setting with ifnull fails */
747 zassert_equal(conn_mgr_if_set_opt(ifnull, TEST_CONN_OPT_X, "A", strlen("A")), -ENOTSUP,
748 "conn_mgr_if_set_opt should fail for ifnull");
749 buf_len = sizeof(buf_len);
750 zassert_equal(conn_mgr_if_get_opt(ifnull, TEST_CONN_OPT_X, buf, &buf_len), -ENOTSUP,
751 "conn_mgr_if_get_opt should fail for ifnull");
752 zassert_equal(buf_len, 0, "failed conn_mgr_if_get_opt should always set buf_len to zero.");
753
754 /* Verify that getting/setting with ifnone fails */
755 zassert_equal(conn_mgr_if_set_opt(ifnone, TEST_CONN_OPT_X, "A", strlen("A")), -ENOTSUP,
756 "conn_mgr_if_set_opt should fail for ifnull");
757 buf_len = sizeof(buf_len);
758 zassert_equal(conn_mgr_if_get_opt(ifnone, TEST_CONN_OPT_X, buf, &buf_len), -ENOTSUP,
759 "conn_mgr_if_get_opt should fail for ifnull");
760 zassert_equal(buf_len, 0, "failed conn_mgr_if_get_opt should always set buf_len to zero.");
761
762 /* Verify that getting/setting with ifb fails (since implementation B doesn't support it) */
763 zassert_equal(conn_mgr_if_set_opt(ifb, TEST_CONN_OPT_X, "A", strlen("A")), -ENOTSUP,
764 "conn_mgr_if_set_opt should fail for ifb");
765 buf_len = sizeof(buf_len);
766 zassert_equal(conn_mgr_if_get_opt(ifb, TEST_CONN_OPT_X, buf, &buf_len), -ENOTSUP,
767 "conn_mgr_if_get_opt should fail for ifb");
768 zassert_equal(buf_len, 0, "failed conn_mgr_if_get_opt should always set buf_len to zero.");
769 }
770
771 /* Verify that flag get/set functions operate correctly */
ZTEST(conn_mgr_conn,test_flags)772 ZTEST(conn_mgr_conn, test_flags)
773 {
774 struct conn_mgr_conn_binding *ifa1_binding = conn_mgr_if_get_binding(ifa1);
775
776 /* Firstly, clear all flags (some are automatically enabled before each test) */
777 ifa1_binding->flags = 0;
778
779 /* Try setting persistence flag */
780 zassert_equal(conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, true), 0,
781 "Setting persistence flag should succeed for ifa1");
782
783 /* Verify success */
784 zassert_true(conn_mgr_if_get_flag(ifa1, CONN_MGR_IF_PERSISTENT),
785 "Persistence should be set for ifa1");
786
787 /* Verify that the conn struct agrees, since this is what implementations may use */
788 zassert_equal(ifa1_binding->flags, BIT(CONN_MGR_IF_PERSISTENT),
789 "Persistence flag set should affect conn struct");
790
791 /* Try setting no-autoconnect flag */
792 zassert_equal(conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT, true), 0,
793 "Setting no-autoconnect flag should succeed for ifa1");
794
795 /* Verify success */
796 zassert_true(conn_mgr_if_get_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT),
797 "No-autoconnect should be set for ifa1");
798
799 /* Verify that the conn struct agrees, since this is what implementations may use */
800 zassert_equal(ifa1_binding->flags,
801 BIT(CONN_MGR_IF_PERSISTENT) | BIT(CONN_MGR_IF_NO_AUTO_CONNECT),
802 "Persistence flag set should affect conn struct");
803
804 /* Try unsetting persistence flag */
805 zassert_equal(conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, false), 0,
806 "Unsetting persistence flag should succeed for ifa1");
807
808 /* Verify success */
809 zassert_false(conn_mgr_if_get_flag(ifa1, CONN_MGR_IF_PERSISTENT),
810 "Persistence should be unset for ifa1");
811
812 /* Verify that the conn struct agrees, since this is what implementations may use */
813 zassert_equal(ifa1_binding->flags, BIT(CONN_MGR_IF_NO_AUTO_CONNECT),
814 "Persistence flag unset should affect conn struct");
815
816 /* Try unsetting no-autoconnect flag */
817 zassert_equal(conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT, false), 0,
818 "Clearing no-autoconnect flag should succeed for ifa1");
819
820 /* Verify success */
821 zassert_false(conn_mgr_if_get_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT),
822 "No-autoconnect should be set for ifa1");
823
824 /* Verify that the conn struct agrees, since this is what implementations may use */
825 zassert_equal(ifa1_binding->flags, 0,
826 "No-autoconnect flag set should affect conn struct");
827 }
828
829 /* Verify that flag get/set fail and behave as expected respectively for invalid ifaces and
830 * invalid flags.
831 */
ZTEST(conn_mgr_conn,test_flags_invalid)832 ZTEST(conn_mgr_conn, test_flags_invalid)
833 {
834 int invalid_flag = CONN_MGR_NUM_IF_FLAGS;
835
836 /* Verify set failure for invalid ifaces / flags */
837 zassert_equal(conn_mgr_if_set_flag(ifnull, CONN_MGR_IF_PERSISTENT, true), -ENOTSUP,
838 "Setting persistence flag should fail for ifnull");
839 zassert_equal(conn_mgr_if_set_flag(ifnone, CONN_MGR_IF_PERSISTENT, true), -ENOTSUP,
840 "Setting persistence flag should fail for ifnone");
841 zassert_equal(conn_mgr_if_set_flag(ifa1, invalid_flag, true), -EINVAL,
842 "Setting invalid flag should fail for ifa1");
843
844 /* Verify get graceful behavior for invalid ifaces / flags */
845 zassert_false(conn_mgr_if_get_flag(ifnull, CONN_MGR_IF_PERSISTENT),
846 "Getting persistence flag should yield false for ifnull");
847 zassert_false(conn_mgr_if_get_flag(ifnone, CONN_MGR_IF_PERSISTENT),
848 "Getting persistence flag should yield false for ifnone");
849 zassert_false(conn_mgr_if_get_flag(ifa1, invalid_flag),
850 "Getting invalid flag should yield false for ifa1");
851 }
852
853
854 /* Verify that timeout get/set functions operate correctly (A/B) */
ZTEST(conn_mgr_conn,test_timeout)855 ZTEST(conn_mgr_conn, test_timeout)
856 {
857 struct conn_mgr_conn_binding *ifa1_binding = conn_mgr_if_get_binding(ifa1);
858
859 /* Try setting timeout */
860 zassert_equal(conn_mgr_if_set_timeout(ifa1, 99), 0,
861 "Setting timeout should succeed for ifa1");
862
863 /* Verify success */
864 zassert_equal(conn_mgr_if_get_timeout(ifa1), 99,
865 "Timeout should be set to 99 for ifa1");
866
867 /* Verify that the conn struct agrees, since this is what implementations may use */
868 zassert_equal(ifa1_binding->timeout, 99,
869 "Timeout set should affect conn struct");
870
871 /* Try unsetting timeout */
872 zassert_equal(conn_mgr_if_set_timeout(ifa1, CONN_MGR_IF_NO_TIMEOUT), 0,
873 "Unsetting timeout should succeed for ifa1");
874
875 /* Verify success */
876 zassert_equal(conn_mgr_if_get_timeout(ifa1), CONN_MGR_IF_NO_TIMEOUT,
877 "Timeout should be unset for ifa1");
878
879 /* Verify that the conn struct agrees, since this is what implementations may use */
880 zassert_equal(ifa1_binding->timeout, CONN_MGR_IF_NO_TIMEOUT,
881 "Timeout unset should affect conn struct");
882 }
883
884 /* Verify that timeout get/set fail and behave as expected respectively for invalid ifaces */
ZTEST(conn_mgr_conn,test_timeout_invalid)885 ZTEST(conn_mgr_conn, test_timeout_invalid)
886 {
887 /* Verify set failure */
888 zassert_equal(conn_mgr_if_set_timeout(ifnull, 99), -ENOTSUP,
889 "Setting timeout should fail for ifnull");
890 zassert_equal(conn_mgr_if_set_timeout(ifnone, 99), -ENOTSUP,
891 "Setting timeout should fail for ifnone");
892
893 /* Verify get graceful behavior */
894 zassert_equal(conn_mgr_if_get_timeout(ifnull), CONN_MGR_IF_NO_TIMEOUT,
895 "Getting timeout should yield CONN_MGR_IF_NO_TIMEOUT for ifnull");
896 zassert_equal(conn_mgr_if_get_timeout(ifnone), CONN_MGR_IF_NO_TIMEOUT,
897 "Getting timeout should yield CONN_MGR_IF_NO_TIMEOUT for ifnone");
898 }
899
900 /* Verify that auto-connect works as expected. */
ZTEST(conn_mgr_conn,test_auto_connect)901 ZTEST(conn_mgr_conn, test_auto_connect)
902 {
903 /* Disable auto-connect.
904 * Not strictly necessary, since this is the default for this suite, but do it anyways
905 * since this test case specifically focuses on auto-connect.
906 */
907 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT, true);
908
909 /* Take the iface up */
910 zassert_equal(net_if_up(ifa1), 0, "net_if_up should not fail.");
911
912 /* Verify no connection */
913 k_sleep(K_MSEC(1));
914 zassert_false(net_if_is_up(ifa1), "Auto-connect should not trigger if disabled.");
915
916 /* Take the iface down */
917 zassert_equal(net_if_down(ifa1), 0, "net_if_down should not fail.");
918
919 /* Enable auto-connect */
920 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT, false);
921
922 /* Take the iface up */
923 zassert_equal(net_if_up(ifa1), 0, "net_if_up should not fail.");
924
925 /* Verify connection */
926 k_sleep(K_MSEC(1));
927 zassert_true(net_if_is_up(ifa1), "Auto-connect should succeed if enabled.");
928 }
929
930 /* Verify that if auto-down is enabled, disconnecting an iface also takes it down,
931 * regardless of whether persistence is enabled, but only if auto-down is disabled.
932 */
ZTEST(conn_mgr_conn,test_auto_down_disconnect)933 ZTEST(conn_mgr_conn, test_auto_down_disconnect)
934 {
935 /* For convenience, use auto-connect for this test. */
936 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT, false);
937
938 /* Enable auto-down, disable persistence */
939 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, false);
940 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_DOWN, false);
941
942 /* Take iface up */
943 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
944
945 /* Verify connected */
946 k_sleep(K_MSEC(1));
947 zassert_true(net_if_is_up(ifa1), "Connection should succeed.");
948
949 /* Disconnect iface */
950 zassert_equal(conn_mgr_if_disconnect(ifa1), 0,
951 "conn_mgr_if_disconnect should succeed.");
952
953 /* Verify down */
954 k_sleep(K_MSEC(1));
955 zassert_false(net_if_is_admin_up(ifa1),
956 "Auto-down should trigger on direct disconnect.");
957
958
959
960 /* Enable persistence */
961 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, true);
962
963 /* Take iface up */
964 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
965
966 /* Verify connected */
967 k_sleep(K_MSEC(1));
968 zassert_true(net_if_is_up(ifa1), "Connection should succeed.");
969
970 /* Disconnect iface */
971 zassert_equal(conn_mgr_if_disconnect(ifa1), 0,
972 "conn_mgr_if_disconnect should succeed.");
973
974 /* Verify down */
975 k_sleep(K_MSEC(1));
976 zassert_false(net_if_is_admin_up(ifa1),
977 "Auto-down should trigger on direct disconnect, even if persistence is enabled.");
978
979
980
981 /* Disable auto-down */
982 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_DOWN, true);
983
984 /* Take iface up */
985 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
986
987 /* Verify connected */
988 k_sleep(K_MSEC(1));
989 zassert_true(net_if_is_up(ifa1), "Connection should succeed.");
990
991 /* Disconnect iface */
992 zassert_equal(conn_mgr_if_disconnect(ifa1), 0,
993 "conn_mgr_if_disconnect should succeed.");
994
995 /* Verify up */
996 zassert_true(net_if_is_admin_up(ifa1),
997 "Auto-down should not trigger if it is disabled.");
998 }
999
1000 /* Verify that auto-down takes an iface down if connection is lost, but only if persistence is not
1001 * enabled, and only if auto-down is enabled.
1002 */
ZTEST(conn_mgr_conn,test_auto_down_conn_loss)1003 ZTEST(conn_mgr_conn, test_auto_down_conn_loss)
1004 {
1005 /* For convenience, use auto-connect for this test. */
1006 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT, false);
1007
1008 /* Enable auto-down, disable persistence */
1009 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, false);
1010 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_DOWN, false);
1011
1012 /* Take iface up */
1013 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
1014
1015 /* Verify connected */
1016 k_sleep(K_MSEC(1));
1017 zassert_true(net_if_is_up(ifa1), "Connection should succeed.");
1018
1019 /* Simulate connection loss */
1020 simulate_connection_loss(ifa1);
1021
1022 /* Verify down */
1023 k_sleep(K_MSEC(1));
1024 zassert_false(net_if_is_admin_up(ifa1),
1025 "Auto-down should trigger on connection loss if persistence is disabled.");
1026
1027 /* Enable persistence */
1028 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, true);
1029
1030 /* Take iface up */
1031 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
1032
1033 /* Verify connected */
1034 k_sleep(K_MSEC(1));
1035 zassert_true(net_if_is_up(ifa1), "Connection should succeed.");
1036
1037 /* Simulate connection loss */
1038 simulate_connection_loss(ifa1);
1039
1040 /* Verify up */
1041 k_sleep(K_MSEC(1));
1042 zassert_true(net_if_is_admin_up(ifa1),
1043 "Auto-down should not trigger on connection loss if persistence is enabled.");
1044
1045 /* Disable persistence and disable auto-down*/
1046 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, false);
1047 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_DOWN, true);
1048
1049 /* Reconnect iface */
1050 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should succeed.");
1051
1052 /* Verify connected */
1053 k_sleep(K_MSEC(1));
1054 zassert_true(net_if_is_up(ifa1), "Connection should succeed.");
1055
1056 /* Simulate connection loss */
1057 simulate_connection_loss(ifa1);
1058
1059 /* Verify up */
1060 k_sleep(K_MSEC(1));
1061 zassert_true(net_if_is_admin_up(ifa1),
1062 "Auto-down should not trigger on connection loss if it is disabled.");
1063 }
1064
1065 /* Verify that timeout takes the iface down, even if
1066 * persistence is enabled, but only if auto-down is enabled.
1067 */
ZTEST(conn_mgr_conn,test_auto_down_timeout)1068 ZTEST(conn_mgr_conn, test_auto_down_timeout)
1069 {
1070 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
1071
1072 /* For convenience, use auto-connect for this test. */
1073 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT, false);
1074
1075 /* Enable auto-down and persistence*/
1076 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, true);
1077 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_DOWN, false);
1078
1079 /* Schedule timeout */
1080 ifa1_data->timeout = true;
1081
1082 /* Take iface up */
1083 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
1084
1085 /* Verify iface down after timeout */
1086 k_sleep(SIMULATED_EVENT_WAIT_TIME);
1087 zassert_false(net_if_is_admin_up(ifa1),
1088 "Auto-down should trigger on connection timeout, even if persistence is enabled.");
1089
1090 /* Disable auto-down */
1091 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_DOWN, true);
1092
1093 /* Take iface up (timing out again) */
1094 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
1095
1096 /* Verify iface up after timeout */
1097 k_sleep(SIMULATED_EVENT_WAIT_TIME);
1098 zassert_true(net_if_is_admin_up(ifa1),
1099 "Auto-down should not trigger on connection timeout if it is disabled.");
1100 }
1101
1102
1103 /* Verify that fatal error takes the iface down, even if
1104 * persistence is enabled, but only if auto-down is enabled.
1105 */
ZTEST(conn_mgr_conn,test_auto_down_fatal)1106 ZTEST(conn_mgr_conn, test_auto_down_fatal)
1107 {
1108 /* For convenience, use auto-connect for this test. */
1109 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_CONNECT, false);
1110
1111 /* Enable auto-down and persistence */
1112 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_PERSISTENT, true);
1113 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_DOWN, false);
1114
1115 /* Take iface up */
1116 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
1117
1118 /* Verify connected */
1119 k_sleep(K_MSEC(1));
1120 zassert_true(net_if_is_up(ifa1), "Connection should succeed.");
1121
1122 /* Raise fatal error */
1123 simulate_fatal_error(ifa1, -EAGAIN);
1124
1125 /* Verify iface down after fatal error */
1126 k_sleep(SIMULATED_EVENT_WAIT_TIME);
1127 zassert_false(net_if_is_admin_up(ifa1),
1128 "Auto-down should trigger on fatal error, even if persistence is enabled.");
1129
1130 /* Disable auto-down */
1131 conn_mgr_if_set_flag(ifa1, CONN_MGR_IF_NO_AUTO_DOWN, true);
1132
1133 /* Take iface up */
1134 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed.");
1135
1136 /* Verify connected */
1137 k_sleep(K_MSEC(1));
1138 zassert_true(net_if_is_up(ifa1), "Connection should succeed.");
1139
1140 /* Raise fatal error */
1141 simulate_fatal_error(ifa1, -EAGAIN);
1142
1143 /* Verify iface still up after fatal error */
1144 k_sleep(SIMULATED_EVENT_WAIT_TIME);
1145 zassert_true(net_if_is_admin_up(ifa1),
1146 "Auto-down should not trigger on fatal error if it is disabled.");
1147 }
1148
1149 /* Verify that all_if_up brings all ifaces up, but only if they are not ignored or
1150 * skip_ignored is false
1151 */
ZTEST(conn_mgr_conn,test_all_if_up)1152 ZTEST(conn_mgr_conn, test_all_if_up)
1153 {
1154 /* Ignore an iface */
1155 conn_mgr_ignore_iface(ifa1);
1156
1157 /* Take all ifaces up (do not skip ignored) */
1158 zassert_equal(conn_mgr_all_if_up(false), 0, "conn_mgr_all_if_up should succeed.");
1159 k_sleep(K_MSEC(1));
1160
1161 /* Verify all ifaces are up */
1162 zassert_true(net_if_is_admin_up(ifa1), "All ifaces should be admin-up.");
1163 zassert_true(net_if_is_admin_up(ifa2), "All ifaces should be admin-up.");
1164 zassert_true(net_if_is_admin_up(ifb), "All ifaces should be admin-up.");
1165 zassert_true(net_if_is_admin_up(ifni), "All ifaces should be admin-up.");
1166 zassert_true(net_if_is_admin_up(ifnull), "All ifaces should be admin-up.");
1167 zassert_true(net_if_is_admin_up(ifnone), "All ifaces should be admin-up.");
1168
1169
1170 /* Manually take all ifaces down */
1171 zassert_equal(net_if_down(ifa1), 0, "net_if_down should succeed for all ifaces.");
1172 zassert_equal(net_if_down(ifa2), 0, "net_if_down should succeed for all ifaces.");
1173 zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for all ifaces.");
1174 zassert_equal(net_if_down(ifni), 0, "net_if_down should succeed for all ifaces.");
1175 zassert_equal(net_if_down(ifnull), 0, "net_if_down should succeed for all ifaces.");
1176 zassert_equal(net_if_down(ifnone), 0, "net_if_down should succeed for all ifaces.");
1177 k_sleep(K_MSEC(1));
1178
1179 /* Take all ifaces up (skip ignored) */
1180 zassert_equal(conn_mgr_all_if_up(true), 0, "conn_mgr_all_if_up should succeed.");
1181 k_sleep(K_MSEC(1));
1182
1183 /* Verify all except ignored are up */
1184 zassert_true(net_if_is_admin_up(ifa2), "All non-ignored ifaces should be admin-up.");
1185 zassert_true(net_if_is_admin_up(ifb), "All non-ignored ifaces should be admin-up.");
1186 zassert_true(net_if_is_admin_up(ifni), "All non-ignored ifaces should be admin-up.");
1187 zassert_true(net_if_is_admin_up(ifnull), "All non-ignored ifaces should be admin-up.");
1188 zassert_true(net_if_is_admin_up(ifnone), "All non-ignored ifaces should be admin-up.");
1189
1190 zassert_false(net_if_is_admin_up(ifa1), "Ignored iface should not be admin-up.");
1191 }
1192
1193 /* Verify that all_if_connect brings all ifaces up, and connects all bound ifaces, but only those
1194 * that are not ignored, or all of them if skip_ignored is false
1195 */
ZTEST(conn_mgr_conn,test_all_if_connect)1196 ZTEST(conn_mgr_conn, test_all_if_connect)
1197 {
1198 /* Ignore a bound and an unbound iface */
1199 conn_mgr_ignore_iface(ifa1);
1200 conn_mgr_ignore_iface(ifnone);
1201
1202 /* Connect all ifaces (do not skip ignored) */
1203 zassert_equal(conn_mgr_all_if_connect(false), 0, "conn_mgr_all_if_connect should succeed.");
1204 k_sleep(K_MSEC(1));
1205
1206 /* Verify all ifaces are up */
1207 zassert_true(net_if_is_admin_up(ifa1), "All ifaces should be admin-up.");
1208 zassert_true(net_if_is_admin_up(ifa2), "All ifaces should be admin-up.");
1209 zassert_true(net_if_is_admin_up(ifb), "All ifaces should be admin-up.");
1210 zassert_true(net_if_is_admin_up(ifni), "All ifaces should be admin-up.");
1211 zassert_true(net_if_is_admin_up(ifnull), "All ifaces should be admin-up.");
1212 zassert_true(net_if_is_admin_up(ifnone), "All ifaces should be admin-up.");
1213
1214 /* Verify bound ifaces are connected */
1215 zassert_true(net_if_is_up(ifa1), "All bound ifaces should be connected.");
1216 zassert_true(net_if_is_up(ifa2), "All bound ifaces should be connected.");
1217 zassert_true(net_if_is_up(ifb), "All bound ifaces should be connected.");
1218 zassert_true(net_if_is_up(ifni), "All bound ifaces should be connected.");
1219
1220 /* Manually take all ifaces down */
1221 zassert_equal(conn_mgr_if_disconnect(ifa1), 0, "net_if_disconnect should succeed.");
1222 zassert_equal(conn_mgr_if_disconnect(ifa2), 0, "net_if_disconnect should succeed.");
1223 zassert_equal(conn_mgr_if_disconnect(ifb), 0, "net_if_disconnect should succeed.");
1224 zassert_equal(conn_mgr_if_disconnect(ifni), 0, "net_if_disconnect should succeed.");
1225
1226 zassert_equal(net_if_down(ifa1), 0, "net_if_down should succeed for all ifaces.");
1227 zassert_equal(net_if_down(ifa2), 0, "net_if_down should succeed for all ifaces.");
1228 zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for all ifaces.");
1229 zassert_equal(net_if_down(ifni), 0, "net_if_down should succeed for all ifaces.");
1230 zassert_equal(net_if_down(ifnull), 0, "net_if_down should succeed for all ifaces.");
1231 zassert_equal(net_if_down(ifnone), 0, "net_if_down should succeed for all ifaces.");
1232 k_sleep(K_MSEC(1));
1233
1234 /* Connect all ifaces (skip ignored) */
1235 zassert_equal(conn_mgr_all_if_connect(true), 0, "conn_mgr_all_if_connect should succeed.");
1236 k_sleep(K_MSEC(1));
1237
1238 /* Verify all except ignored are up */
1239 zassert_true(net_if_is_admin_up(ifa2), "All non-ignored ifaces should be admin-up.");
1240 zassert_true(net_if_is_admin_up(ifb), "All non-ignored ifaces should be admin-up.");
1241 zassert_true(net_if_is_admin_up(ifni), "All non-ignored ifaces should be admin-up.");
1242 zassert_true(net_if_is_admin_up(ifnull), "All non-ignored ifaces should be admin-up.");
1243
1244 zassert_false(net_if_is_admin_up(ifa1), "All ignored ifaces should be admin-down.");
1245 zassert_false(net_if_is_admin_up(ifnone), "All ignored ifaces should be admin-down.");
1246
1247 /* Verify bound ifaces are connected, except for ignored */
1248 zassert_true(net_if_is_up(ifa2), "All non-ignored bound ifaces should be connected.");
1249 zassert_true(net_if_is_up(ifb), "All non-ignored bound ifaces should be connected.");
1250 zassert_true(net_if_is_up(ifni), "All non-ignored bound ifaces should be connected.");
1251
1252 zassert_false(net_if_is_up(ifa1), "Ignored iface should not be connected.");
1253 }
1254
1255 /* Verify that all_if_down takes all ifaces down, but only if they are not ignored,
1256 * or skip_ignored is false
1257 */
ZTEST(conn_mgr_conn,test_all_if_down)1258 ZTEST(conn_mgr_conn, test_all_if_down)
1259 {
1260 /* Ignore an iface */
1261 conn_mgr_ignore_iface(ifa1);
1262
1263 /* Manually take all ifaces up */
1264 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed for all ifaces.");
1265 zassert_equal(net_if_up(ifa2), 0, "net_if_up should succeed for all ifaces.");
1266 zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for all ifaces.");
1267 zassert_equal(net_if_up(ifni), 0, "net_if_up should succeed for all ifaces.");
1268 zassert_equal(net_if_up(ifnull), 0, "net_if_up should succeed for all ifaces.");
1269 zassert_equal(net_if_up(ifnone), 0, "net_if_up should succeed for all ifaces.");
1270 k_sleep(K_MSEC(1));
1271
1272 /* Take all ifaces down (do not skip ignored) */
1273 zassert_equal(conn_mgr_all_if_down(false), 0, "conn_mgr_all_if_down should succeed.");
1274 k_sleep(K_MSEC(1));
1275
1276 /* Verify all ifaces are down */
1277 zassert_false(net_if_is_admin_up(ifa1), "All ifaces should be admin-down.");
1278 zassert_false(net_if_is_admin_up(ifa2), "All ifaces should be admin-down.");
1279 zassert_false(net_if_is_admin_up(ifb), "All ifaces should be admin-down.");
1280 zassert_false(net_if_is_admin_up(ifni), "All ifaces should be admin-down.");
1281 zassert_false(net_if_is_admin_up(ifnull), "All ifaces should be admin-down.");
1282 zassert_false(net_if_is_admin_up(ifnone), "All ifaces should be admin-down.");
1283
1284 /* Manually take all ifaces up */
1285 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed for all ifaces.");
1286 zassert_equal(net_if_up(ifa2), 0, "net_if_up should succeed for all ifaces.");
1287 zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for all ifaces.");
1288 zassert_equal(net_if_up(ifni), 0, "net_if_up should succeed for all ifaces.");
1289 zassert_equal(net_if_up(ifnull), 0, "net_if_up should succeed for all ifaces.");
1290 zassert_equal(net_if_up(ifnone), 0, "net_if_up should succeed for all ifaces.");
1291 k_sleep(K_MSEC(1));
1292
1293 /* Take all ifaces down (skip ignored) */
1294 zassert_equal(conn_mgr_all_if_down(true), 0, "conn_mgr_all_if_down should succeed.");
1295 k_sleep(K_MSEC(1));
1296
1297 /* Verify that all except the ignored iface is down */
1298 zassert_false(net_if_is_admin_up(ifa2), "All non-ignored ifaces should be admin-down.");
1299 zassert_false(net_if_is_admin_up(ifb), "All non-ignored ifaces should be admin-down.");
1300 zassert_false(net_if_is_admin_up(ifni), "All non-ignored ifaces should be admin-down.");
1301 zassert_false(net_if_is_admin_up(ifnull), "All non-ignored ifaces should be admin-down.");
1302 zassert_false(net_if_is_admin_up(ifnone), "All non-ignored ifaces should be admin-down.");
1303
1304 zassert_true(net_if_is_admin_up(ifa1), "Ignored iface should be admin-up.");
1305 }
1306
1307 /* Verify that all_if_disconnect disconnects all bound ifaces, but only if they are not ignored,
1308 * or skip_ignored is false
1309 */
ZTEST(conn_mgr_conn,test_all_if_disconnect)1310 ZTEST(conn_mgr_conn, test_all_if_disconnect)
1311 {
1312 /* Ignore a bound iface */
1313 conn_mgr_ignore_iface(ifa1);
1314
1315 /* Manually take all ifaces up */
1316 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed for all ifaces.");
1317 zassert_equal(net_if_up(ifa2), 0, "net_if_up should succeed for all ifaces.");
1318 zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for all ifaces.");
1319 zassert_equal(net_if_up(ifni), 0, "net_if_up should succeed for all ifaces.");
1320 zassert_equal(net_if_up(ifnull), 0, "net_if_up should succeed for all ifaces.");
1321 zassert_equal(net_if_up(ifnone), 0, "net_if_up should succeed for all ifaces.");
1322 k_sleep(K_MSEC(1));
1323
1324 /* Manually connect all bound ifaces */
1325 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should succeed.");
1326 zassert_equal(conn_mgr_if_connect(ifa2), 0, "conn_mgr_if_connect should succeed.");
1327 zassert_equal(conn_mgr_if_connect(ifb), 0, "conn_mgr_if_connect should succeed.");
1328 zassert_equal(conn_mgr_if_connect(ifni), 0, "conn_mgr_if_connect should succeed.");
1329 k_sleep(K_MSEC(1));
1330
1331 /* Disconnect all ifaces (do not skip ignored) */
1332 zassert_equal(conn_mgr_all_if_disconnect(false), 0,
1333 "conn_mgr_all_if_disconnect should succeed.");
1334 k_sleep(K_MSEC(1));
1335
1336 /* Verify that all bound ifaces are disconnected */
1337 zassert_false(net_if_is_up(ifa1), "All bound ifaces should be disconnected.");
1338 zassert_false(net_if_is_up(ifa2), "All bound ifaces should be disconnected.");
1339 zassert_false(net_if_is_up(ifb), "All bound ifaces should be disconnected.");
1340 zassert_false(net_if_is_up(ifni), "All bound ifaces should be disconnected.");
1341
1342 /* Verify that all ifaces are still up, even if disconnected */
1343 zassert_true(net_if_is_admin_up(ifa1), "All ifaces should be admin-up.");
1344 zassert_true(net_if_is_admin_up(ifa2), "All ifaces should be admin-up.");
1345 zassert_true(net_if_is_admin_up(ifb), "All ifaces should be admin-up.");
1346 zassert_true(net_if_is_admin_up(ifni), "All ifaces should be admin-up.");
1347 zassert_true(net_if_is_admin_up(ifnull), "All ifaces should be admin-up.");
1348 zassert_true(net_if_is_admin_up(ifnone), "All ifaces should be admin-up.");
1349
1350 /* Manually reconnect bound ifaces */
1351 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should succeed.");
1352 zassert_equal(conn_mgr_if_connect(ifa2), 0, "conn_mgr_if_connect should succeed.");
1353 zassert_equal(conn_mgr_if_connect(ifb), 0, "conn_mgr_if_connect should succeed.");
1354 zassert_equal(conn_mgr_if_connect(ifni), 0, "conn_mgr_if_connect should succeed.");
1355 k_sleep(K_MSEC(1));
1356
1357 /* Disconnect all ifaces (skip ignored) */
1358 zassert_equal(conn_mgr_all_if_disconnect(true), 0,
1359 "conn_mgr_all_if_disconnect should succeed.");
1360 k_sleep(K_MSEC(1));
1361
1362 /* Verify that all bound ifaces are disconnected, except the ignored iface */
1363 zassert_false(net_if_is_up(ifa2), "All non-ignored bound ifaces should be disconnected.");
1364 zassert_false(net_if_is_up(ifb), "All non-ignored bound ifaces should be disconnected.");
1365 zassert_false(net_if_is_up(ifni), "All non-ignored bound ifaces should be disconnected.");
1366
1367 zassert_true(net_if_is_up(ifa1), "Ignored iface should still be connected");
1368 }
1369
1370
1371 /* Verify that double calls to all_if_up do not raise errors */
ZTEST(conn_mgr_conn,test_all_if_up_double)1372 ZTEST(conn_mgr_conn, test_all_if_up_double)
1373 {
1374 /* Take all ifaces up twice in a row */
1375 zassert_equal(conn_mgr_all_if_up(false), 0,
1376 "conn_mgr_all_if_up should succeed.");
1377 zassert_equal(conn_mgr_all_if_up(false), 0,
1378 "conn_mgr_all_if_up should succeed twice in a row.");
1379
1380 /* One more time, after a delay, to be sure */
1381 k_sleep(K_MSEC(1));
1382 zassert_equal(conn_mgr_all_if_up(false), 0,
1383 "conn_mgr_all_if_up should succeed twice in a row.");
1384 k_sleep(K_MSEC(1));
1385
1386 /* Verify all ifaces are up */
1387 zassert_true(net_if_is_admin_up(ifa1), "All ifaces should be admin-up.");
1388 zassert_true(net_if_is_admin_up(ifa2), "All ifaces should be admin-up.");
1389 zassert_true(net_if_is_admin_up(ifb), "All ifaces should be admin-up.");
1390 zassert_true(net_if_is_admin_up(ifni), "All ifaces should be admin-up.");
1391 zassert_true(net_if_is_admin_up(ifnull), "All ifaces should be admin-up.");
1392 zassert_true(net_if_is_admin_up(ifnone), "All ifaces should be admin-up.");
1393 }
1394
1395 /* Verify that double calls to all_if_down do not raise errors */
ZTEST(conn_mgr_conn,test_all_if_down_double)1396 ZTEST(conn_mgr_conn, test_all_if_down_double)
1397 {
1398 /* Manually take all ifaces up */
1399 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed for all ifaces.");
1400 zassert_equal(net_if_up(ifa2), 0, "net_if_up should succeed for all ifaces.");
1401 zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for all ifaces.");
1402 zassert_equal(net_if_up(ifni), 0, "net_if_up should succeed for all ifaces.");
1403 zassert_equal(net_if_up(ifnull), 0, "net_if_up should succeed for all ifaces.");
1404 zassert_equal(net_if_up(ifnone), 0, "net_if_up should succeed for all ifaces.");
1405 k_sleep(K_MSEC(1));
1406
1407 /* Take all ifaces down twice in a row */
1408 zassert_equal(conn_mgr_all_if_down(false), 0,
1409 "conn_mgr_all_if_down should succeed.");
1410 zassert_equal(conn_mgr_all_if_down(false), 0,
1411 "conn_mgr_all_if_down should succeed twice in a row.");
1412
1413 /* One more time, after a delay, to be sure */
1414 k_sleep(K_MSEC(1));
1415 zassert_equal(conn_mgr_all_if_down(false), 0,
1416 "conn_mgr_all_if_down should succeed twice in a row.");
1417 k_sleep(K_MSEC(1));
1418
1419 /* Verify all ifaces are down */
1420 zassert_false(net_if_is_admin_up(ifa1), "All ifaces should be admin-down.");
1421 zassert_false(net_if_is_admin_up(ifa2), "All ifaces should be admin-down.");
1422 zassert_false(net_if_is_admin_up(ifb), "All ifaces should be admin-down.");
1423 zassert_false(net_if_is_admin_up(ifni), "All ifaces should be admin-down.");
1424 zassert_false(net_if_is_admin_up(ifnull), "All ifaces should be admin-down.");
1425 zassert_false(net_if_is_admin_up(ifnone), "All ifaces should be admin-down.");
1426 }
1427
1428 /* Verify that double calls to all_if_connect do not raise errors */
ZTEST(conn_mgr_conn,test_all_if_connect_double)1429 ZTEST(conn_mgr_conn, test_all_if_connect_double)
1430 {
1431 /* Connect all ifaces twice in a row */
1432 zassert_equal(conn_mgr_all_if_connect(false), 0,
1433 "conn_mgr_all_if_connect should succeed.");
1434 zassert_equal(conn_mgr_all_if_connect(false), 0,
1435 "conn_mgr_all_if_connect should succeed twice in a row.");
1436
1437 /* One more time, after a delay, to be sure */
1438 k_sleep(K_MSEC(1));
1439 zassert_equal(conn_mgr_all_if_connect(false), 0,
1440 "conn_mgr_all_if_connect should succeed twice in a row.");
1441 k_sleep(K_MSEC(1));
1442
1443 /* Verify all ifaces are up */
1444 zassert_true(net_if_is_admin_up(ifa1), "All ifaces should be admin-up.");
1445 zassert_true(net_if_is_admin_up(ifa2), "All ifaces should be admin-up.");
1446 zassert_true(net_if_is_admin_up(ifb), "All ifaces should be admin-up.");
1447 zassert_true(net_if_is_admin_up(ifni), "All ifaces should be admin-up.");
1448 zassert_true(net_if_is_admin_up(ifnull), "All ifaces should be admin-up.");
1449 zassert_true(net_if_is_admin_up(ifnone), "All ifaces should be admin-up.");
1450
1451 /* Verify all bound ifaces are connected */
1452 }
1453
1454 /* Verify that double calls to all_if_disconnect do not raise errors */
ZTEST(conn_mgr_conn,test_all_if_disconnect_double)1455 ZTEST(conn_mgr_conn, test_all_if_disconnect_double)
1456 {
1457 /* Manually take all ifaces up */
1458 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed for all ifaces.");
1459 zassert_equal(net_if_up(ifa2), 0, "net_if_up should succeed for all ifaces.");
1460 zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for all ifaces.");
1461 zassert_equal(net_if_up(ifni), 0, "net_if_up should succeed for all ifaces.");
1462 zassert_equal(net_if_up(ifnull), 0, "net_if_up should succeed for all ifaces.");
1463 zassert_equal(net_if_up(ifnone), 0, "net_if_up should succeed for all ifaces.");
1464 k_sleep(K_MSEC(1));
1465
1466 /* Manually connect all bound ifaces */
1467 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should succeed.");
1468 zassert_equal(conn_mgr_if_connect(ifa2), 0, "conn_mgr_if_connect should succeed.");
1469 zassert_equal(conn_mgr_if_connect(ifb), 0, "conn_mgr_if_connect should succeed.");
1470 zassert_equal(conn_mgr_if_connect(ifni), 0, "conn_mgr_if_connect should succeed.");
1471 k_sleep(K_MSEC(1));
1472
1473 /* Connect all ifaces twice in a row */
1474 zassert_equal(conn_mgr_all_if_disconnect(false), 0,
1475 "conn_mgr_all_if_disconnect should succeed.");
1476 zassert_equal(conn_mgr_all_if_disconnect(false), 0,
1477 "conn_mgr_all_if_disconnect should succeed twice in a row.");
1478
1479 /* One more time, after a delay, to be sure */
1480 k_sleep(K_MSEC(1));
1481 zassert_equal(conn_mgr_all_if_disconnect(false), 0,
1482 "conn_mgr_all_if_disconnect should succeed twice in a row.");
1483 k_sleep(K_MSEC(1));
1484
1485 /* Verify all bound ifaces are disconnected */
1486 zassert_false(net_if_is_up(ifa1), "All bound ifaces should be disconnected.");
1487 zassert_false(net_if_is_up(ifa2), "All bound ifaces should be disconnected.");
1488 zassert_false(net_if_is_up(ifb), "All bound ifaces should be disconnected.");
1489 zassert_false(net_if_is_up(ifni), "All bound ifaces should be disconnected.");
1490
1491 /* Verify all ifaces are up */
1492 zassert_true(net_if_is_admin_up(ifa1), "All ifaces should be admin-up.");
1493 zassert_true(net_if_is_admin_up(ifa2), "All ifaces should be admin-up.");
1494 zassert_true(net_if_is_admin_up(ifb), "All ifaces should be admin-up.");
1495 zassert_true(net_if_is_admin_up(ifni), "All ifaces should be admin-up.");
1496 zassert_true(net_if_is_admin_up(ifnull), "All ifaces should be admin-up.");
1497 zassert_true(net_if_is_admin_up(ifnone), "All ifaces should be admin-up.");
1498 }
1499
1500
1501
1502 /* Testing error passing for all_if_up/all_if_down is not possible without using an L2 other than
1503 * Dummy, since the dummy L2 is not capable of erroring in response to either of these.
1504 *
1505 * However, since all bulk convenience functions share a single implementation, testing
1506 * connect and disconnect is sufficient to gain acceptable coverage of this behavior for all of
1507 * them.
1508 */
1509
1510 /* Verify that all_if_connect successfully forwards errors encountered on individual ifaces */
ZTEST(conn_mgr_conn,test_all_if_connect_err)1511 ZTEST(conn_mgr_conn, test_all_if_connect_err)
1512 {
1513 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
1514
1515 /* Schedule a connect error on one of the ifaces */
1516 ifa1_data->api_err = -ECHILD;
1517
1518 /* Verify that this error is passed to all_if_connect */
1519 zassert_equal(conn_mgr_all_if_connect(false), -ECHILD,
1520 "conn_mgr_all_if_connect should fail with the requested error.");
1521 k_sleep(K_MSEC(1));
1522
1523 /* Verify that all ifaces went admin-up */
1524 zassert_true(net_if_is_admin_up(ifa1), "All ifaces should be admin-up.");
1525 zassert_true(net_if_is_admin_up(ifa2), "All ifaces should be admin-up.");
1526 zassert_true(net_if_is_admin_up(ifb), "All ifaces should be admin-up.");
1527 zassert_true(net_if_is_admin_up(ifni), "All ifaces should be admin-up.");
1528 zassert_true(net_if_is_admin_up(ifnull), "All ifaces should be admin-up.");
1529 zassert_true(net_if_is_admin_up(ifnone), "All ifaces should be admin-up.");
1530
1531 /* Verify that all the non-error ifaces are connected */
1532 zassert_true(net_if_is_up(ifa2), "All non-failing ifaces should be connected.");
1533 zassert_true(net_if_is_up(ifb), "All non-failing ifaces should be connected.");
1534 zassert_true(net_if_is_up(ifni), "All non-failing ifaces should be connected.");
1535
1536 /* Verify that the error iface is not connected */
1537 zassert_false(net_if_is_up(ifa1), "The failing iface should not be connected.");
1538 }
1539
1540 /* Verify that all_if_disconnect successfully forwards errors encountered on individual ifaces */
ZTEST(conn_mgr_conn,test_all_if_disconnect_err)1541 ZTEST(conn_mgr_conn, test_all_if_disconnect_err)
1542 {
1543 struct test_conn_data *ifa1_data = conn_mgr_if_get_data(ifa1);
1544
1545 /* Manually take all ifaces up */
1546 zassert_equal(net_if_up(ifa1), 0, "net_if_up should succeed for all ifaces.");
1547 zassert_equal(net_if_up(ifa2), 0, "net_if_up should succeed for all ifaces.");
1548 zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for all ifaces.");
1549 zassert_equal(net_if_up(ifni), 0, "net_if_up should succeed for all ifaces.");
1550 zassert_equal(net_if_up(ifnull), 0, "net_if_up should succeed for all ifaces.");
1551 zassert_equal(net_if_up(ifnone), 0, "net_if_up should succeed for all ifaces.");
1552 k_sleep(K_MSEC(1));
1553
1554 /* Manually connect all bound ifaces */
1555 zassert_equal(conn_mgr_if_connect(ifa1), 0, "conn_mgr_if_connect should succeed.");
1556 zassert_equal(conn_mgr_if_connect(ifa2), 0, "conn_mgr_if_connect should succeed.");
1557 zassert_equal(conn_mgr_if_connect(ifb), 0, "conn_mgr_if_connect should succeed.");
1558 zassert_equal(conn_mgr_if_connect(ifni), 0, "conn_mgr_if_connect should succeed.");
1559 k_sleep(K_MSEC(1));
1560
1561 /* Schedule a disconnect error on one of the ifaces */
1562 ifa1_data->api_err = -ECHILD;
1563
1564 /* Verify that this error is passed to all_if_disconnect */
1565 zassert_equal(conn_mgr_all_if_disconnect(false), -ECHILD,
1566 "conn_mgr_all_if_disconnect should fail with the requested error.");
1567
1568 /* Verify that all ifaces are still admin-up */
1569 zassert_true(net_if_is_admin_up(ifa1), "All ifaces should be admin-up.");
1570 zassert_true(net_if_is_admin_up(ifa2), "All ifaces should be admin-up.");
1571 zassert_true(net_if_is_admin_up(ifb), "All ifaces should be admin-up.");
1572 zassert_true(net_if_is_admin_up(ifni), "All ifaces should be admin-up.");
1573 zassert_true(net_if_is_admin_up(ifnull), "All ifaces should be admin-up.");
1574 zassert_true(net_if_is_admin_up(ifnone), "All ifaces should be admin-up.");
1575
1576 /* Verify that all the non-error ifaces are disconnected */
1577 zassert_false(net_if_is_up(ifa2), "All non-failing ifaces should be disconnected.");
1578 zassert_false(net_if_is_up(ifb), "All non-failing ifaces should be disconnected.");
1579 zassert_false(net_if_is_up(ifni), "All non-failing ifaces should be disconnected.");
1580
1581 /* Verify that the error iface is not connected */
1582 zassert_true(net_if_is_up(ifa1), "The failing iface should not be disconnected.");
1583 }
1584
1585 ZTEST_SUITE(conn_mgr_conn, NULL, conn_mgr_conn_setup, conn_mgr_conn_before, NULL, NULL);
1586