1 /*
2  * Copyright (c) 2022 Rodrigo Peixoto <rodrigopex@gmail.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include "messages.h"
7 
8 #include <zephyr/irq_offload.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/logging/log.h>
11 #include <zephyr/zbus/zbus.h>
12 #include <zephyr/ztest.h>
13 LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL);
14 
hard_msg_validator(const void * msg,size_t msg_size)15 static bool hard_msg_validator(const void *msg, size_t msg_size)
16 {
17 	ARG_UNUSED(msg_size);
18 
19 	const struct hard_msg *ref = (struct hard_msg *)msg;
20 
21 	return (ref->range >= 0) && (ref->range <= 1023) && (ref->binary <= 1) &&
22 	       (ref->pointer != NULL);
23 }
24 
25 ZBUS_CHAN_DEFINE(version_chan,       /* Name */
26 		 struct version_msg, /* Message type */
27 
28 		 NULL,                 /* Validator */
29 		 NULL,                 /* User data */
30 		 ZBUS_OBSERVERS_EMPTY, /* observers */
31 		 ZBUS_MSG_INIT(.major = 0, .minor = 1,
32 			       .build = 1023) /* Initial value major 0, minor 1, build 1023 */
33 );
34 
35 ZBUS_CHAN_DEFINE(aux1_chan,     /* Name */
36 		 struct s1_msg, /* Message type */
37 
38 		 NULL,                     /* Validator */
39 		 NULL,                     /* User data */
40 		 ZBUS_OBSERVERS(fast_lis), /* observers */
41 		 ZBUS_MSG_INIT(0)          /* Initial value major 0, minor 1, build 1023 */
42 );
43 
44 ZBUS_CHAN_DEFINE(aux2_chan,         /* Name */
45 		 struct action_msg, /* Message type */
46 
47 		 NULL,                     /* Validator */
48 		 NULL,                     /* User data */
49 		 ZBUS_OBSERVERS(fast_lis), /* observers */
50 		 ZBUS_MSG_INIT(0)          /* Initial value major 0, minor 1, build 1023 */
51 );
52 
53 ZBUS_CHAN_DEFINE(aux3_on_change_chan, /* Name */
54 		 struct action_msg,   /* Message type */
55 
56 		 NULL,                     /* Validator */
57 		 NULL,                     /* User data */
58 		 ZBUS_OBSERVERS(fast_lis), /* observers */
59 		 ZBUS_MSG_INIT(0)          /* Initial value major 0, minor 1, build 1023 */
60 );
61 
62 ZBUS_CHAN_DEFINE(go_busy_chan,      /* Name */
63 		 struct action_msg, /* Message type */
64 
65 		 NULL,                     /* Validator */
66 		 NULL,                     /* User data */
67 		 ZBUS_OBSERVERS(busy_lis), /* observers */
68 		 ZBUS_MSG_INIT(0)          /* Initial value major 0, minor 1, build 1023 */
69 );
70 
71 ZBUS_CHAN_DEFINE(hard_chan,       /* Name */
72 		 struct hard_msg, /* Message type */
73 
74 		 hard_msg_validator,   /* Validator */
75 		 NULL,                 /* User data */
76 		 ZBUS_OBSERVERS_EMPTY, /* observers */
77 		 ZBUS_MSG_INIT(0)      /* Initial value major 0, minor 1, build 1023 */
78 );
79 
80 ZBUS_CHAN_DEFINE(stuck_chan,      /* Name */
81 		 struct hard_msg, /* Message type */
82 
83 		 hard_msg_validator,   /* Validator */
84 		 NULL,                 /* User data */
85 		 ZBUS_OBSERVERS_EMPTY, /* observers */
86 		 ZBUS_MSG_INIT(0)      /* Initial value major 0, minor 1, build 1023 */
87 );
88 
89 ZBUS_CHAN_DEFINE(msg_sub_fail_chan,                        /* Name */
90 		 int,                                      /* Message type */
91 		 NULL,                                     /* Validator */
92 		 NULL,                                     /* User data */
93 		 ZBUS_OBSERVERS(foo_msg_sub, invalid_obs), /* observers */
94 		 ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */
95 );
96 ZBUS_CHAN_DEFINE(msg_sub_no_pool_chan,                      /* Name */
97 		 int,                                       /* Message type */
98 		 NULL,                                      /* Validator */
99 		 NULL,                                      /* User data */
100 		 ZBUS_OBSERVERS(foo_msg_sub, foo2_msg_sub), /* observers */
101 		 ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */
102 );
103 static int count_fast;
104 
callback(const struct zbus_channel * chan)105 static void callback(const struct zbus_channel *chan)
106 {
107 	++count_fast;
108 }
109 
110 ZBUS_LISTENER_DEFINE(fast_lis, callback);
111 
112 ZBUS_LISTENER_DEFINE(rt_fast_lis, callback);
113 
114 static int isr_return;
115 
116 enum operation {
117 	PUB_ISR_INVAL,
118 	READ_ISR_INVAL,
119 	NOTIFY_ISR_INVAL,
120 	CLAIM_ISR_INVAL,
121 	FINISH_ISR_INVAL,
122 	ADD_OBS_ISR_INVAL,
123 	RM_OBS_ISR_INVAL,
124 	PUB_ISR,
125 	READ_ISR,
126 	NOTIFY_ISR,
127 	CLAIM_ISR,
128 	FINISH_ISR,
129 	ADD_OBS_ISR,
130 	RM_OBS_ISR,
131 	NONE
132 };
133 
134 static enum operation current_isr_operation = NONE;
135 
136 static struct action_msg ga;
137 
isr_handler(const void * operation)138 static void isr_handler(const void *operation)
139 {
140 	enum operation *op = (enum operation *)operation;
141 
142 	switch (*op) {
143 	case PUB_ISR_INVAL:
144 		isr_return = zbus_chan_pub(&aux2_chan, &ga, K_MSEC(500));
145 		break;
146 	case READ_ISR_INVAL:
147 		isr_return = zbus_chan_read(&aux2_chan, &ga, K_MSEC(500));
148 		break;
149 	case NOTIFY_ISR_INVAL:
150 		isr_return = zbus_chan_notify(&aux2_chan, K_MSEC(100));
151 		break;
152 	case CLAIM_ISR_INVAL:
153 		isr_return = zbus_chan_claim(&aux2_chan, K_MSEC(200));
154 		break;
155 	case FINISH_ISR_INVAL:
156 		isr_return = zbus_chan_finish(NULL);
157 		break;
158 	case ADD_OBS_ISR_INVAL:
159 		isr_return = zbus_chan_add_obs(&aux2_chan, &fast_lis, K_MSEC(200));
160 		break;
161 	case RM_OBS_ISR_INVAL:
162 		isr_return = zbus_chan_rm_obs(&aux2_chan, &fast_lis, K_MSEC(200));
163 		break;
164 	case PUB_ISR:
165 		isr_return = zbus_chan_pub(&aux2_chan, &ga, K_NO_WAIT);
166 		break;
167 	case READ_ISR:
168 		isr_return = zbus_chan_read(&aux2_chan, &ga, K_NO_WAIT);
169 		break;
170 	case NOTIFY_ISR:
171 		isr_return = zbus_chan_notify(&aux2_chan, K_NO_WAIT);
172 		break;
173 	case CLAIM_ISR:
174 		isr_return = zbus_chan_claim(&aux2_chan, K_NO_WAIT);
175 		break;
176 	case FINISH_ISR:
177 		isr_return = zbus_chan_finish(&aux2_chan);
178 		break;
179 	case ADD_OBS_ISR:
180 		isr_return = zbus_chan_add_obs(&aux2_chan, NULL, K_MSEC(200));
181 		break;
182 	case RM_OBS_ISR:
183 		isr_return = zbus_chan_rm_obs(&aux2_chan, NULL, K_MSEC(200));
184 		break;
185 	case NONE:
186 		break;
187 	}
188 }
189 
busy_callback(const struct zbus_channel * chan)190 static void busy_callback(const struct zbus_channel *chan)
191 {
192 	zbus_chan_claim(&go_busy_chan, K_NO_WAIT);
193 }
194 
195 ZBUS_LISTENER_DEFINE(busy_lis, busy_callback);
196 
197 #define ISR_OP(_op, _exp)                                                                          \
198 	isr_return = 0;                                                                            \
199 	current_isr_operation = _op;                                                               \
200 	irq_offload(isr_handler, &current_isr_operation);                                          \
201 	zassert_equal(_exp, isr_return, "isr return wrong, it is %d", isr_return);                 \
202 	k_msleep(100);
203 
204 struct aux2_wq_data {
205 	struct k_work work;
206 };
207 
208 static struct aux2_wq_data wq_handler;
209 
wq_dh_cb(struct k_work * item)210 static void wq_dh_cb(struct k_work *item)
211 {
212 	struct action_msg a = {0};
213 
214 	zassert_equal(-EBUSY, zbus_chan_pub(&aux2_chan, &a, K_NO_WAIT), "It must not be invalid");
215 
216 	zassert_equal(-EBUSY, zbus_chan_read(&aux2_chan, &a, K_NO_WAIT), "It must not be invalid");
217 
218 	zassert_equal(-EBUSY, zbus_chan_notify(&aux2_chan, K_NO_WAIT), "It must not be invalid");
219 
220 	zassert_equal(-EFAULT, zbus_chan_finish(NULL), "It must be invalid");
221 }
222 
223 ZBUS_SUBSCRIBER_DEFINE(sub1, 1);
224 ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(foo_msg_sub, false);
225 ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(foo2_msg_sub, false);
226 
227 static K_FIFO_DEFINE(_zbus_observer_fifo_invalid_obs);
228 
229 /* clang-format off */
230 static struct zbus_observer_data _zbus_obs_data_invalid_obs = {
231 	.enabled = false,
232 	IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (
233 		.priority = ATOMIC_INIT(CONFIG_NUM_PREEMPT_PRIORITIES - 1)
234 	))
235 };
236 
237 STRUCT_SECTION_ITERABLE(zbus_observer, invalid_obs) = {
238 	ZBUS_OBSERVER_NAME_INIT(invalid_obs) /* Name field */
239 	.type = ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE + 10,
240 	.data = &_zbus_obs_data_invalid_obs,
241 	.message_fifo = &_zbus_observer_fifo_invalid_obs
242 };
243 /* clang-format on */
244 
ZTEST(basic,test_specification_based__zbus_chan)245 ZTEST(basic, test_specification_based__zbus_chan)
246 {
247 	struct action_msg a = {0};
248 
249 	/* Trying invalid parameters */
250 	zassert_equal(-EFAULT, zbus_chan_pub(NULL, &a, K_NO_WAIT), "It must be -EFAULT");
251 
252 	k_msleep(100);
253 
254 	zassert_equal(-EFAULT, zbus_chan_pub(&aux2_chan, NULL, K_NO_WAIT), "It must be -EFAULT");
255 
256 	k_msleep(100);
257 
258 	zassert_equal(-EFAULT, zbus_chan_read(NULL, &a, K_NO_WAIT), "It must be -EFAULT");
259 
260 	k_msleep(100);
261 
262 	zassert_equal(-EFAULT, zbus_chan_read(&aux2_chan, NULL, K_NO_WAIT), "It must be -EFAULT");
263 
264 	k_msleep(100);
265 
266 	zassert_equal(-EFAULT, zbus_chan_notify(NULL, K_NO_WAIT), "It must be -EFAULT");
267 
268 	zassert_equal(-EFAULT, zbus_chan_claim(NULL, K_NO_WAIT), "It must be -EFAULT");
269 
270 	zassert_equal(-EFAULT, zbus_chan_finish(NULL), "It must be -EFAULT");
271 
272 	zassert_equal(-EFAULT, zbus_chan_add_obs(NULL, &sub1, K_MSEC(200)), NULL);
273 
274 	zassert_equal(-EFAULT, zbus_chan_add_obs(&aux2_chan, NULL, K_MSEC(200)), NULL);
275 
276 	zassert_equal(-EFAULT, zbus_chan_rm_obs(NULL, &sub1, K_MSEC(200)), NULL);
277 
278 	zassert_equal(-EFAULT, zbus_chan_rm_obs(&aux2_chan, NULL, K_MSEC(200)), NULL);
279 	/* Trying valid parameters */
280 	zassert_equal(0, zbus_chan_pub(&aux2_chan, &a, K_NO_WAIT), "It must be valid");
281 
282 	k_msleep(100);
283 
284 	zassert_equal(0, zbus_chan_read(&aux2_chan, &a, K_NO_WAIT), "It must be valid");
285 
286 	k_msleep(100);
287 
288 	zassert_equal(0, zbus_chan_notify(&aux2_chan, K_NO_WAIT), "It must be valid");
289 
290 	zassert_equal(0, zbus_chan_claim(&aux2_chan, K_NO_WAIT), "It must be valid");
291 
292 	k_work_init(&wq_handler.work, wq_dh_cb);
293 	k_work_submit(&wq_handler.work);
294 
295 	k_msleep(100);
296 
297 	zassert_equal(-EBUSY, zbus_chan_pub(&aux2_chan, &a, K_NO_WAIT), "It must not be valid");
298 
299 	zassert_equal(-EBUSY, zbus_chan_read(&aux2_chan, &a, K_NO_WAIT), "It must not be valid");
300 
301 	zassert_equal(-EBUSY, zbus_chan_notify(&aux2_chan, K_NO_WAIT), "It must not be invalid");
302 
303 	zassert_equal(0, zbus_chan_finish(&aux2_chan), "It must finish correctly");
304 
305 	int fail = 10;
306 
307 	zbus_obs_set_enable(&invalid_obs, true);
308 	int err = zbus_chan_pub(&msg_sub_fail_chan, &fail, K_MSEC(200));
309 
310 	zassert_equal(-EFAULT, err, "It must reach the default on the switch. Err %d", err);
311 	zbus_obs_set_enable(&invalid_obs, false);
312 
313 	struct action_msg repeated = {.status = false};
314 
315 	zbus_chan_pub(&aux3_on_change_chan, &repeated, K_NO_WAIT);
316 
317 	k_msleep(100);
318 
319 	zbus_chan_pub(&aux3_on_change_chan, &repeated, K_NO_WAIT);
320 
321 	k_msleep(100);
322 
323 	zassert_equal(0, zbus_chan_pub(&go_busy_chan, &repeated, K_NO_WAIT),
324 		      "It must be ok, but it causes an error inside the event dispatcher telling "
325 		      "the channel is busy.");
326 
327 	k_msleep(100);
328 
329 	zassert_equal(0, zbus_chan_add_obs(&stuck_chan, &sub1, K_MSEC(200)), NULL);
330 
331 	zassert_equal(0, zbus_chan_notify(&stuck_chan, K_MSEC(200)), "It must finish correctly");
332 
333 	zassert_equal(-EAGAIN, zbus_chan_notify(&stuck_chan, K_MSEC(200)),
334 		      "It must get stuck on the stuck_chan since it only has 1 occupied spot at "
335 		      "the msgq");
336 
337 	/* Trying to call the zbus functions in a ISR context. None must work */
338 	ISR_OP(PUB_ISR, 0);
339 	ISR_OP(PUB_ISR_INVAL, 0);
340 	ISR_OP(READ_ISR, 0);
341 	ISR_OP(READ_ISR_INVAL, 0);
342 	ISR_OP(NOTIFY_ISR, 0);
343 	ISR_OP(NOTIFY_ISR_INVAL, 0);
344 	ISR_OP(CLAIM_ISR, 0);
345 	ISR_OP(FINISH_ISR, 0);
346 	ISR_OP(CLAIM_ISR_INVAL, 0);
347 	ISR_OP(FINISH_ISR, 0);
348 	ISR_OP(FINISH_ISR_INVAL, -EFAULT);
349 	ISR_OP(ADD_OBS_ISR, -EFAULT);
350 	ISR_OP(ADD_OBS_ISR_INVAL, -EFAULT);
351 	ISR_OP(RM_OBS_ISR, -EFAULT);
352 	ISR_OP(RM_OBS_ISR_INVAL, -EFAULT);
353 
354 	int msg;
355 	const struct zbus_channel *chan;
356 
357 	zbus_obs_set_enable(&foo_msg_sub, true);
358 	zbus_obs_set_enable(&foo2_msg_sub, true);
359 	zassert_equal(-ENOMEM, zbus_chan_notify(&msg_sub_no_pool_chan, K_MSEC(200)),
360 		      "It must return an error, the pool only have 2 slots. For publishing to "
361 		      "MSG_SUBSCRIBERS it is necessary at least one per each and a spare one.");
362 
363 	zassert_equal(0, zbus_sub_wait_msg(&foo_msg_sub, &chan, &msg, K_MSEC(500)), NULL);
364 	zbus_obs_set_enable(&foo_msg_sub, false);
365 	zbus_obs_set_enable(&foo2_msg_sub, false);
366 }
367 
always_true_chan_iterator(const struct zbus_channel * chan)368 static bool always_true_chan_iterator(const struct zbus_channel *chan)
369 {
370 	return true;
371 }
372 
always_true_obs_iterator(const struct zbus_observer * obs)373 static bool always_true_obs_iterator(const struct zbus_observer *obs)
374 {
375 	return true;
376 }
377 
always_false_chan_iterator(const struct zbus_channel * chan)378 static bool always_false_chan_iterator(const struct zbus_channel *chan)
379 {
380 	return false;
381 }
382 
always_false_obs_iterator(const struct zbus_observer * obs)383 static bool always_false_obs_iterator(const struct zbus_observer *obs)
384 {
385 	return false;
386 }
387 
check_chan_iterator(const struct zbus_channel * chan,void * user_data)388 static bool check_chan_iterator(const struct zbus_channel *chan, void *user_data)
389 {
390 	int *chan_idx = user_data;
391 
392 	LOG_DBG("Idx %d - Channel %s", *chan_idx, chan->name);
393 
394 	switch (*chan_idx) {
395 	case 0:
396 		zassert_mem_equal__(zbus_chan_name(chan), "aux1_chan", 9, "Must be equal");
397 		break;
398 	case 1:
399 		zassert_mem_equal__(zbus_chan_name(chan), "aux2_chan", 9, "Must be equal");
400 		break;
401 	case 2:
402 		zassert_mem_equal__(zbus_chan_name(chan), "aux3_on_change_chan", 19,
403 				    "Must be equal");
404 		break;
405 	case 3:
406 		zassert_mem_equal__(zbus_chan_name(chan), "go_busy_chan", 12, "Must be equal");
407 		break;
408 	case 4:
409 		zassert_mem_equal__(zbus_chan_name(chan), "hard_chan", 9, "Must be equal");
410 		break;
411 	case 5:
412 		zassert_mem_equal__(zbus_chan_name(chan), "msg_sub_fail_chan",
413 				    sizeof("msg_sub_fail_chan"), "Must be equal");
414 		break;
415 	case 6:
416 		zassert_mem_equal__(zbus_chan_name(chan), "msg_sub_no_pool_chan",
417 				    sizeof("msg_sub_no_pool_chan"), "Must be equal");
418 		break;
419 	case 7:
420 		zassert_mem_equal__(zbus_chan_name(chan), "stuck_chan", 10, "Must be equal");
421 		break;
422 	case 8:
423 		zassert_mem_equal__(zbus_chan_name(chan), "version_chan", 12, "Must be equal");
424 		break;
425 	default:
426 		zassert_unreachable(NULL);
427 	}
428 	++(*chan_idx);
429 
430 	return true;
431 }
432 
check_obs_iterator(const struct zbus_observer * obs,void * user_data)433 static bool check_obs_iterator(const struct zbus_observer *obs, void *user_data)
434 {
435 	int *obs_idx = user_data;
436 
437 	LOG_DBG("Idx %d - Observer %s", *obs_idx, obs->name);
438 
439 	switch (*obs_idx) {
440 	case 0:
441 		zassert_mem_equal__(zbus_obs_name(obs), "busy_lis", 8, "Must be equal");
442 		break;
443 	case 1:
444 		zassert_mem_equal__(zbus_obs_name(obs), "fast_lis", 8, "Must be equal");
445 		break;
446 	case 2:
447 		zassert_mem_equal__(zbus_obs_name(obs), "foo2_msg_sub", sizeof("foo2_msg_sub"),
448 				    "Must be equal");
449 		break;
450 	case 3:
451 		zassert_mem_equal__(zbus_obs_name(obs), "foo_msg_sub", 11, "Must be equal");
452 		break;
453 	case 4:
454 		zassert_mem_equal__(zbus_obs_name(obs), "foo_sub", 7, "Must be equal");
455 		break;
456 	case 5:
457 		zassert_mem_equal__(zbus_obs_name(obs), "invalid_obs", strlen("invalid_obs"),
458 				    "Must be equal");
459 		break;
460 	case 6:
461 		zassert_mem_equal__(zbus_obs_name(obs), "invalid_sub", strlen("invalid_sub"),
462 				    "Must be equal");
463 		break;
464 	case 7:
465 		zassert_mem_equal__(zbus_obs_name(obs), "not_observing_sub",
466 				    strlen("not_observing_sub"), "Must be equal");
467 		break;
468 	case 8:
469 		zassert_mem_equal__(zbus_obs_name(obs), "rt_fast_lis", 11, "Must be equal");
470 		break;
471 	case 9:
472 		zassert_mem_equal__(zbus_obs_name(obs), "sub1", 4, "Must be equal");
473 		break;
474 	default:
475 		zassert_unreachable(NULL);
476 	}
477 	++(*obs_idx);
478 
479 	return true;
480 }
481 
482 static int oracle;
483 
count_false_chan_iterator(const struct zbus_channel * chan,void * user_data)484 static bool count_false_chan_iterator(const struct zbus_channel *chan, void *user_data)
485 {
486 	int *idx = user_data;
487 
488 	++(*idx);
489 
490 	LOG_DBG("chan_idx %d, oracle %d", *idx, oracle);
491 
492 	return (bool)(*idx != oracle);
493 }
494 
count_false_obs_iterator(const struct zbus_observer * obs,void * user_data)495 static bool count_false_obs_iterator(const struct zbus_observer *obs, void *user_data)
496 {
497 	int *idx = user_data;
498 
499 	++(*idx);
500 
501 	LOG_DBG("obs_idx %d, oracle %d", *idx, oracle);
502 
503 	return (bool)(*idx != oracle);
504 }
505 
ZTEST(basic,test_iterators)506 ZTEST(basic, test_iterators)
507 {
508 
509 	zassert_equal(true, zbus_iterate_over_channels(always_true_chan_iterator), "Must be true");
510 
511 	zassert_equal(true, zbus_iterate_over_observers(always_true_obs_iterator), "Must be true");
512 
513 	zassert_equal(false, zbus_iterate_over_channels(always_false_chan_iterator),
514 		      "Must be false");
515 
516 	zassert_equal(false, zbus_iterate_over_observers(always_false_obs_iterator),
517 		      "Must be false");
518 
519 	int chan_idx = 0;
520 
521 	zassert_equal(true,
522 		      zbus_iterate_over_channels_with_user_data(check_chan_iterator, &chan_idx),
523 		      "Must be true");
524 
525 	int obs_idx = 0;
526 
527 	zassert_equal(true,
528 		      zbus_iterate_over_observers_with_user_data(check_obs_iterator, &obs_idx),
529 		      "Must be true");
530 
531 	int chan_count = 0;
532 
533 	STRUCT_SECTION_COUNT(zbus_channel, &chan_count);
534 
535 	chan_count -= 1;
536 
537 	int idx = -1;
538 
539 	for (int i = 0; i < chan_count; ++i) {
540 		oracle = i;
541 
542 		zassert_equal(
543 			false,
544 			zbus_iterate_over_channels_with_user_data(count_false_chan_iterator, &idx),
545 			"Must be false");
546 
547 		k_msleep(100);
548 
549 		idx = -1;
550 	}
551 	int obs_count = 0;
552 
553 	STRUCT_SECTION_COUNT(zbus_observer, &obs_count);
554 
555 	obs_count -= 1;
556 
557 	idx = -1;
558 	LOG_DBG("Counts obs %d, chan %d", obs_count, chan_count);
559 
560 	for (int i = 0; i < obs_count; ++i) {
561 		oracle = i;
562 
563 		zassert_equal(
564 			false,
565 			zbus_iterate_over_observers_with_user_data(count_false_obs_iterator, &idx),
566 			"Must be false");
567 
568 		idx = -1;
569 	}
570 }
571 
ZTEST(basic,test_hard_channel)572 ZTEST(basic, test_hard_channel)
573 {
574 	struct hard_msg valid = {.range = 10, .binary = 1, .pointer = &valid.range};
575 
576 	zbus_chan_pub(&hard_chan, &valid, K_NO_WAIT);
577 
578 	struct hard_msg current;
579 
580 	zbus_chan_read(&hard_chan, &current, K_NO_WAIT);
581 
582 	zassert_equal(valid.range, current.range, "Range must be equal");
583 	zassert_equal(valid.binary, current.binary, "Binary must be equal");
584 	zassert_equal(valid.pointer, current.pointer, "Pointer must be equal");
585 
586 	struct hard_msg invalid = {.range = 10000, .binary = 1, .pointer = &valid.range};
587 	int err = zbus_chan_pub(&hard_chan, &invalid, K_NO_WAIT);
588 
589 	zassert_equal(err, -ENOMSG, "Err must be -ENOMSG, the channel message is invalid");
590 
591 	invalid = (struct hard_msg){.range = 1, .binary = 3, .pointer = &invalid.range};
592 	err = zbus_chan_pub(&hard_chan, &invalid, K_NO_WAIT);
593 	zassert_equal(err, -ENOMSG, "Err must be -ENOMSG, the channel message is invalid");
594 
595 	invalid = (struct hard_msg){.range = 1, .binary = 0, .pointer = NULL};
596 	err = zbus_chan_pub(&hard_chan, &invalid, K_NO_WAIT);
597 	zassert_equal(err, -ENOMSG, "Err must be -ENOMSG, the channel message is invalid");
598 }
599 
ZTEST(basic,test_specification_based__zbus_obs_set_enable)600 ZTEST(basic, test_specification_based__zbus_obs_set_enable)
601 {
602 	bool enable;
603 
604 	count_fast = 0;
605 
606 	zassert_equal(-EFAULT, zbus_obs_set_enable(NULL, false), NULL);
607 
608 	zassert_equal(-EFAULT, zbus_obs_is_enabled(NULL, NULL));
609 
610 	zassert_equal(-EFAULT, zbus_obs_is_enabled(NULL, &enable));
611 
612 	zassert_equal(-EFAULT, zbus_obs_is_enabled(&rt_fast_lis, NULL));
613 
614 	zassert_equal(0, zbus_obs_set_enable(&rt_fast_lis, false),
615 		      "Must be zero. The observer must be disabled");
616 
617 	zbus_obs_is_enabled(&rt_fast_lis, &enable);
618 	zassert_equal(false, enable);
619 
620 	zassert_equal(0, zbus_chan_add_obs(&aux1_chan, &rt_fast_lis, K_MSEC(200)), NULL);
621 
622 	zassert_equal(0, zbus_obs_set_enable(&fast_lis, false),
623 		      "Must be zero. The observer must be disabled");
624 
625 	zbus_obs_is_enabled(&fast_lis, &enable);
626 	zassert_equal(false, enable);
627 
628 	zbus_chan_notify(&aux1_chan, K_NO_WAIT);
629 
630 	k_msleep(300);
631 
632 	zassert_equal(count_fast, 0, "Must be zero. No callback called");
633 
634 	zassert_equal(0, zbus_obs_set_enable(&fast_lis, true),
635 		      "Must be zero. The observer must be enabled");
636 
637 	zbus_obs_is_enabled(&fast_lis, &enable);
638 	zassert_equal(true, enable);
639 
640 	zassert_equal(0, zbus_obs_set_enable(&rt_fast_lis, true),
641 		      "Must be zero. The observer must be enabled");
642 
643 	zbus_obs_is_enabled(&rt_fast_lis, &enable);
644 	zassert_equal(true, enable);
645 
646 	zbus_chan_notify(&aux1_chan, K_NO_WAIT);
647 
648 	k_msleep(300);
649 
650 	zassert_equal(count_fast, 2, "Must be 2. Callback must be called once it is %d",
651 		      count_fast);
652 
653 	zassert_equal(0, zbus_chan_rm_obs(&aux1_chan, &rt_fast_lis, K_MSEC(200)), NULL);
654 }
655 
656 ZBUS_SUBSCRIBER_DEFINE(not_observing_sub, 0);
657 
ZTEST(basic,test_specification_based__zbus_obs_set_chan_notification_mask)658 ZTEST(basic, test_specification_based__zbus_obs_set_chan_notification_mask)
659 {
660 	bool enabled = false;
661 	bool masked = false;
662 
663 	count_fast = 0;
664 
665 	zassert_equal(-EFAULT, zbus_obs_set_chan_notification_mask(NULL, NULL, false), NULL);
666 
667 	zassert_equal(-EFAULT, zbus_obs_set_chan_notification_mask(NULL, NULL, true), NULL);
668 
669 	zassert_equal(-EFAULT, zbus_obs_set_chan_notification_mask(&fast_lis, NULL, true), NULL);
670 
671 	zassert_equal(-EFAULT, zbus_obs_set_chan_notification_mask(NULL, &aux1_chan, true), NULL);
672 
673 	zassert_equal(-ESRCH,
674 		      zbus_obs_set_chan_notification_mask(&not_observing_sub, &aux1_chan, true),
675 		      NULL);
676 
677 	zassert_equal(-EFAULT, zbus_obs_is_chan_notification_masked(NULL, NULL, NULL), NULL);
678 
679 	zassert_equal(-EFAULT, zbus_obs_is_chan_notification_masked(NULL, NULL, &masked), NULL);
680 
681 	zassert_equal(-EFAULT, zbus_obs_is_chan_notification_masked(&fast_lis, NULL, &masked),
682 		      NULL);
683 
684 	zassert_equal(-EFAULT, zbus_obs_is_chan_notification_masked(NULL, &aux1_chan, &masked),
685 		      NULL);
686 
687 	zassert_equal(-ESRCH,
688 		      zbus_obs_is_chan_notification_masked(&not_observing_sub, &aux1_chan, &masked),
689 		      NULL);
690 
691 	zbus_obs_set_chan_notification_mask(&fast_lis, &aux1_chan, true);
692 
693 	zbus_obs_is_chan_notification_masked(&fast_lis, &aux1_chan, &enabled);
694 	zassert_equal(true, enabled);
695 
696 	zbus_chan_notify(&aux1_chan, K_NO_WAIT);
697 
698 	zassert_equal(count_fast, 0, "Count must 0, since the channel notification is masked");
699 
700 	zbus_obs_set_chan_notification_mask(&fast_lis, &aux1_chan, false);
701 
702 	zbus_obs_is_chan_notification_masked(&fast_lis, &aux1_chan, &enabled);
703 	zassert_equal(false, enabled);
704 
705 	zbus_chan_notify(&aux1_chan, K_NO_WAIT);
706 	zbus_chan_notify(&aux1_chan, K_NO_WAIT);
707 	zbus_chan_notify(&aux1_chan, K_NO_WAIT);
708 
709 	zassert_equal(count_fast, 3, "Must be 3. The channel notification was masked %d",
710 		      count_fast);
711 }
712 
713 ZBUS_SUBSCRIBER_DEFINE(foo_sub, 1);
714 
715 /* clang-format off */
716 static struct zbus_observer_data _zbus_obs_data_invalid_sub = {
717 	.enabled = false,
718 	IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (
719 		.priority = ATOMIC_INIT(CONFIG_NUM_PREEMPT_PRIORITIES - 1)
720 	))
721 };
722 
723 STRUCT_SECTION_ITERABLE(zbus_observer, invalid_sub) = {
724 	ZBUS_OBSERVER_NAME_INIT(invalid_sub) /* Name field */
725 	.type = ZBUS_OBSERVER_SUBSCRIBER_TYPE,
726 	.data = &_zbus_obs_data_invalid_sub,
727 	.queue = NULL
728 };
729 /* clang-format on */
730 
isr_sub_wait(const void * operation)731 static void isr_sub_wait(const void *operation)
732 {
733 	const struct zbus_channel *chan;
734 
735 	/* All the calls must not work. Zbus cannot work in IRSs */
736 	zassert_equal(-EFAULT, zbus_sub_wait(NULL, NULL, K_NO_WAIT), NULL);
737 	zassert_equal(-EFAULT, zbus_sub_wait(&foo_sub, NULL, K_NO_WAIT), NULL);
738 	zassert_equal(-EFAULT, zbus_sub_wait(&foo_sub, &chan, K_NO_WAIT), NULL);
739 	zassert_equal(-EFAULT, zbus_sub_wait(&invalid_sub, &chan, K_NO_WAIT), NULL);
740 }
741 
ZTEST(basic,test_specification_based__zbus_sub_wait)742 ZTEST(basic, test_specification_based__zbus_sub_wait)
743 {
744 	count_fast = 0;
745 	const struct zbus_channel *chan;
746 
747 	zassert_equal(-EFAULT, zbus_sub_wait(NULL, NULL, K_NO_WAIT), NULL);
748 	zassert_equal(-EFAULT, zbus_sub_wait(&foo_sub, NULL, K_NO_WAIT), NULL);
749 	zassert_equal(-EFAULT, zbus_sub_wait(&foo_msg_sub, NULL, K_NO_WAIT), NULL);
750 
751 	/* It must run but return a -ENOMSG because of the K_NO_WAIT */
752 	zassert_equal(-ENOMSG, zbus_sub_wait(&foo_sub, &chan, K_NO_WAIT), NULL);
753 	zassert_equal(-EAGAIN, zbus_sub_wait(&foo_sub, &chan, K_MSEC(200)), NULL);
754 
755 	irq_offload(isr_sub_wait, NULL);
756 }
757 
isr_sub_wait_msg(const void * operation)758 static void isr_sub_wait_msg(const void *operation)
759 {
760 	const struct zbus_channel *chan;
761 
762 	/* All the calls must not work. Zbus cannot work in IRSs */
763 	zassert_equal(-EFAULT, zbus_sub_wait_msg(NULL, NULL, NULL, K_NO_WAIT), NULL);
764 	zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_sub, NULL, NULL, K_NO_WAIT), NULL);
765 	zassert_equal(-EFAULT, zbus_sub_wait(&foo_msg_sub, NULL, K_NO_WAIT), NULL);
766 	int a = 0;
767 
768 	zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_msg_sub, &chan, &a, K_NO_WAIT), NULL);
769 }
ZTEST(basic,test_specification_based__zbus_sub_wait_msg)770 ZTEST(basic, test_specification_based__zbus_sub_wait_msg)
771 {
772 	count_fast = 0;
773 	const struct zbus_channel *chan;
774 
775 	zassert_equal(-EFAULT, zbus_sub_wait_msg(NULL, NULL, NULL, K_NO_WAIT), NULL);
776 	zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_sub, NULL, NULL, K_NO_WAIT), NULL);
777 	zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_msg_sub, NULL, NULL, K_NO_WAIT), NULL);
778 	zassert_equal(-EFAULT, zbus_sub_wait_msg(&foo_msg_sub, &chan, NULL, K_NO_WAIT), NULL);
779 	int a = 0;
780 
781 	zassert_equal(-ENOMSG, zbus_sub_wait_msg(&foo_msg_sub, &chan, &a, K_NO_WAIT), NULL);
782 	zassert_equal(-ENOMSG, zbus_sub_wait_msg(&foo_msg_sub, &chan, &a, K_MSEC(200)), NULL);
783 
784 	irq_offload(isr_sub_wait_msg, NULL);
785 }
786 
787 #if defined(CONFIG_ZBUS_PRIORITY_BOOST)
isr_obs_attach_detach(const void * operation)788 static void isr_obs_attach_detach(const void *operation)
789 {
790 	zassert_equal(-EFAULT, zbus_obs_attach_to_thread(NULL), NULL);
791 	zassert_equal(-EFAULT, zbus_obs_attach_to_thread(&foo_sub), NULL);
792 	zassert_equal(-EFAULT, zbus_obs_attach_to_thread(&invalid_sub), NULL);
793 
794 	zassert_equal(-EFAULT, zbus_obs_detach_from_thread(NULL), NULL);
795 	zassert_equal(-EFAULT, zbus_obs_detach_from_thread(&foo_sub), NULL);
796 	zassert_equal(-EFAULT, zbus_obs_detach_from_thread(&invalid_sub), NULL);
797 }
798 
ZTEST(basic,test_specification_based__zbus_obs_attach_detach)799 ZTEST(basic, test_specification_based__zbus_obs_attach_detach)
800 {
801 	zassert_equal(-EFAULT, zbus_obs_attach_to_thread(NULL), NULL);
802 	zassert_equal(0, zbus_obs_attach_to_thread(&foo_sub), NULL);
803 	zassert_equal(0, zbus_obs_detach_from_thread(&foo_sub), NULL);
804 	zassert_equal(0, zbus_obs_attach_to_thread(&invalid_sub), NULL);
805 	zassert_equal(0, zbus_obs_detach_from_thread(&invalid_sub), NULL);
806 	zassert_equal(-EFAULT, zbus_obs_detach_from_thread(NULL), NULL);
807 
808 	irq_offload(isr_obs_attach_detach, NULL);
809 }
810 #else
ZTEST(basic,test_specification_based__zbus_obs_attach_detach)811 ZTEST(basic, test_specification_based__zbus_obs_attach_detach)
812 {
813 	ztest_test_skip();
814 }
815 #endif
816 
817 ZTEST_SUITE(basic, NULL, NULL, NULL, NULL, NULL);
818