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, ¤t_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, ¤t, 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(¬_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(¬_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