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/kernel.h>
9 #include <zephyr/logging/log.h>
10 #include <zephyr/zbus/zbus.h>
11 #include <zephyr/ztest.h>
12 LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL);
13 
14 ZBUS_CHAN_DEFINE(version_chan,	     /* Name */
15 		 struct version_msg, /* Message type */
16 
17 		 NULL,		       /* Validator */
18 		 NULL,		       /* User data */
19 		 ZBUS_OBSERVERS_EMPTY, /* observers */
20 		 ZBUS_MSG_INIT(.major = 0, .minor = 1,
21 			       .build = 2) /* Initial value major 0, minor 1, build 1023 */
22 );
23 
24 static int my_user_data;
25 
26 ZBUS_CHAN_DEFINE(regular_chan,	 /* Name */
27 		 struct foo_msg, /* Message type */
28 
29 		 NULL,					       /* Validator */
30 		 &my_user_data,				       /* User data */
31 		 ZBUS_OBSERVERS(foo_listener, foo_subscriber), /* observers */
32 		 ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */
33 );
34 
ZTEST(user_data,test_channel_user_data)35 ZTEST(user_data, test_channel_user_data)
36 {
37 	zassert_true(sizeof(my_user_data) > 0, NULL);
38 
39 	zassert_equal_ptr(version_chan.user_data, NULL, NULL);
40 
41 	zassert_equal_ptr(regular_chan.user_data, &my_user_data, NULL);
42 
43 	int *counter = regular_chan.user_data;
44 	*counter = -2;
45 
46 	zassert_equal(zbus_chan_user_data(&regular_chan), counter, NULL);
47 	zassert_equal(*(int *)zbus_chan_user_data(&regular_chan), -2, NULL);
48 
49 	memset(regular_chan.user_data, 0, sizeof(my_user_data));
50 }
51 
urgent_callback(const struct zbus_channel * chan)52 static void urgent_callback(const struct zbus_channel *chan)
53 {
54 	if (chan == &(regular_chan)) {
55 		int *count = zbus_chan_user_data(&regular_chan);
56 
57 		*count += 1;
58 	}
59 }
60 
61 ZBUS_LISTENER_DEFINE(foo_listener, urgent_callback);
62 
63 ZBUS_SUBSCRIBER_DEFINE(foo_subscriber, 1);
64 
foo_subscriber_thread(void)65 static void foo_subscriber_thread(void)
66 {
67 	struct zbus_channel *chan = NULL;
68 
69 	while (1) {
70 		if (!k_msgq_get(foo_subscriber.queue, &chan, K_FOREVER)) {
71 			if (chan == &(regular_chan)) {
72 				if (!zbus_chan_claim(&regular_chan, K_FOREVER)) {
73 					int *count = zbus_chan_user_data(&regular_chan);
74 
75 					*count += 1;
76 
77 					zbus_chan_finish(&regular_chan);
78 				}
79 			}
80 		}
81 	}
82 }
83 
84 K_THREAD_DEFINE(foo_subscriber_thread_id, 1024, foo_subscriber_thread, NULL, NULL, NULL, 3, 0, 0);
85 
ZTEST(user_data,test_user_data_regression)86 ZTEST(user_data, test_user_data_regression)
87 {
88 	/* To ensure the pub/sub behavior is kept */
89 	struct foo_msg sent = {.a = 10, .b = 1000};
90 
91 	zbus_chan_pub(&regular_chan, &sent, K_MSEC(100));
92 
93 	struct foo_msg received;
94 
95 	zbus_chan_read(&regular_chan, &received, K_MSEC(100));
96 
97 	zassert_equal(sent.a, received.a, NULL);
98 
99 	zassert_equal(sent.b, received.b, NULL);
100 
101 	k_msleep(1000);
102 
103 	if (!zbus_chan_claim(&regular_chan, K_FOREVER)) {
104 		int *count = zbus_chan_user_data(&regular_chan);
105 
106 		zassert_equal(*count, 2, NULL);
107 
108 		zbus_chan_finish(&regular_chan);
109 	}
110 }
111 
112 ZTEST_SUITE(user_data, NULL, NULL, NULL, NULL, NULL);
113