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