1 /*
2  * Copyright (c) 2019 Peter Bigot Consulting, LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/sys/notify.h>
9 
get_extflags(const struct sys_notify * anp)10 static uint32_t get_extflags(const struct sys_notify *anp)
11 {
12 	uint32_t flags = anp->flags & SYS_NOTIFY_EXTENSION_MASK;
13 
14 	return flags >> SYS_NOTIFY_EXTENSION_POS;
15 }
16 
set_extflags(struct sys_notify * anp,uint32_t flags)17 static void set_extflags(struct sys_notify *anp,
18 			 uint32_t flags)
19 {
20 	anp->flags = (anp->flags & ~SYS_NOTIFY_EXTENSION_MASK)
21 		     | (flags << SYS_NOTIFY_EXTENSION_POS);
22 }
23 
callback(struct sys_notify * anp,int * resp)24 static void callback(struct sys_notify *anp,
25 		     int *resp)
26 {
27 	zassert_equal(sys_notify_fetch_result(anp, resp), 0,
28 		      "failed callback fetch");
29 }
30 
ZTEST(sys_notify_api,test_validate)31 ZTEST(sys_notify_api, test_validate)
32 {
33 	struct sys_notify notify = {
34 		.flags = 0,
35 	};
36 
37 	zassert_equal(sys_notify_validate(NULL), -EINVAL,
38 		      "accepted null pointer");
39 	zassert_equal(sys_notify_validate(&notify), -EINVAL,
40 		      "accepted bad method");
41 }
42 
43 
ZTEST(sys_notify_api,test_spinwait)44 ZTEST(sys_notify_api, test_spinwait)
45 {
46 	int rc;
47 	int set_res = 423;
48 	int res = 0;
49 	sys_notify_generic_callback cb;
50 	struct sys_notify notify;
51 	uint32_t xflags = 0x1234;
52 
53 	memset(&notify, 0xac, sizeof(notify));
54 	rc = sys_notify_validate(&notify);
55 	zassert_equal(rc, -EINVAL,
56 		      "invalid not diagnosed");
57 
58 	sys_notify_init_spinwait(&notify);
59 	rc = sys_notify_validate(&notify);
60 	zassert_equal(rc, 0,
61 		      "init_spinwait invalid");
62 
63 	zassert_false(sys_notify_uses_callback(&notify),
64 		      "uses callback");
65 
66 	zassert_equal(notify.flags, SYS_NOTIFY_METHOD_SPINWAIT,
67 		      "flags mismatch");
68 
69 	set_extflags(&notify, xflags);
70 	zassert_equal(sys_notify_get_method(&notify),
71 		      SYS_NOTIFY_METHOD_SPINWAIT,
72 		      "method corrupted");
73 	zassert_equal(get_extflags(&notify), xflags,
74 		      "xflags extract failed");
75 
76 	rc = sys_notify_fetch_result(&notify, &res);
77 	zassert_equal(rc, -EAGAIN,
78 		      "spinwait ready too soon");
79 
80 	zassert_not_equal(notify.flags, 0,
81 			  "flags cleared");
82 
83 	cb = sys_notify_finalize(&notify, set_res);
84 	zassert_equal(cb, (sys_notify_generic_callback)NULL,
85 		      "callback not null");
86 	zassert_equal(notify.flags, 0,
87 		      "flags not cleared");
88 
89 	rc = sys_notify_fetch_result(&notify, &res);
90 	zassert_equal(rc, 0,
91 		      "spinwait not ready");
92 	zassert_equal(res, set_res,
93 		      "result not set");
94 }
95 
ZTEST(sys_notify_api,test_signal)96 ZTEST(sys_notify_api, test_signal)
97 {
98 #ifdef CONFIG_POLL
99 	int rc;
100 	int set_res = 423;
101 	int res;
102 	struct k_poll_signal sig;
103 	sys_notify_generic_callback cb;
104 	struct sys_notify notify;
105 	uint32_t xflags = 0x1234;
106 
107 	memset(&notify, 0xac, sizeof(notify));
108 	rc = sys_notify_validate(&notify);
109 	zassert_equal(rc, -EINVAL,
110 		      "invalid not diagnosed");
111 
112 	k_poll_signal_init(&sig);
113 	k_poll_signal_check(&sig, &rc, &res);
114 	zassert_equal(rc, 0,
115 		      "signal set");
116 
117 	sys_notify_init_signal(&notify, &sig);
118 	notify.method.signal = NULL;
119 	rc = sys_notify_validate(&notify);
120 	zassert_equal(rc, -EINVAL,
121 		      "null signal not invalid");
122 
123 	memset(&notify, 0xac, sizeof(notify));
124 	sys_notify_init_signal(&notify, &sig);
125 	rc = sys_notify_validate(&notify);
126 	zassert_equal(rc, 0,
127 		      "init_spinwait invalid");
128 
129 	zassert_false(sys_notify_uses_callback(&notify),
130 		      "uses callback");
131 
132 	zassert_equal(notify.flags, SYS_NOTIFY_METHOD_SIGNAL,
133 		      "flags mismatch");
134 	zassert_equal(notify.method.signal, &sig,
135 		      "signal pointer mismatch");
136 
137 	set_extflags(&notify, xflags);
138 	zassert_equal(sys_notify_get_method(&notify),
139 		      SYS_NOTIFY_METHOD_SIGNAL,
140 		      "method corrupted");
141 	zassert_equal(get_extflags(&notify), xflags,
142 		      "xflags extract failed");
143 
144 	rc = sys_notify_fetch_result(&notify, &res);
145 	zassert_equal(rc, -EAGAIN,
146 		      "spinwait ready too soon");
147 
148 	zassert_not_equal(notify.flags, 0,
149 			  "flags cleared");
150 
151 	cb = sys_notify_finalize(&notify, set_res);
152 	zassert_equal(cb, (sys_notify_generic_callback)NULL,
153 		      "callback not null");
154 	zassert_equal(notify.flags, 0,
155 		      "flags not cleared");
156 	k_poll_signal_check(&sig, &rc, &res);
157 	zassert_equal(rc, 1,
158 		      "signal not set");
159 	zassert_equal(res, set_res,
160 		      "signal result wrong");
161 
162 	rc = sys_notify_fetch_result(&notify, &res);
163 	zassert_equal(rc, 0,
164 		      "signal not ready");
165 	zassert_equal(res, set_res,
166 		      "result not set");
167 #endif /* CONFIG_POLL */
168 }
169 
ZTEST(sys_notify_api,test_callback)170 ZTEST(sys_notify_api, test_callback)
171 {
172 	int rc;
173 	int set_res = 423;
174 	int res;
175 	sys_notify_generic_callback cb;
176 	struct sys_notify notify;
177 	uint32_t xflags = 0x8765432;
178 
179 	memset(&notify, 0xac, sizeof(notify));
180 	rc = sys_notify_validate(&notify);
181 	zassert_equal(rc, -EINVAL,
182 		      "invalid not diagnosed");
183 
184 	sys_notify_init_callback(&notify, callback);
185 	notify.method.callback = NULL;
186 	rc = sys_notify_validate(&notify);
187 	zassert_equal(rc, -EINVAL,
188 		      "null callback not invalid");
189 
190 	memset(&notify, 0xac, sizeof(notify));
191 	sys_notify_init_callback(&notify, callback);
192 	rc = sys_notify_validate(&notify);
193 	zassert_equal(rc, 0,
194 		      "init_spinwait invalid");
195 
196 	zassert_true(sys_notify_uses_callback(&notify),
197 		     "not using callback");
198 
199 	zassert_equal(notify.flags, SYS_NOTIFY_METHOD_CALLBACK,
200 		      "flags mismatch");
201 	zassert_equal(notify.method.callback,
202 		      (sys_notify_generic_callback)callback,
203 		      "callback mismatch");
204 
205 	set_extflags(&notify, xflags);
206 	zassert_equal(sys_notify_get_method(&notify),
207 		      SYS_NOTIFY_METHOD_CALLBACK,
208 		      "method corrupted");
209 	zassert_equal(get_extflags(&notify), xflags,
210 		      "xflags extract failed");
211 
212 	rc = sys_notify_fetch_result(&notify, &res);
213 	zassert_equal(rc, -EAGAIN,
214 		      "callback ready too soon");
215 
216 	zassert_not_equal(notify.flags, 0,
217 			  "flags cleared");
218 
219 	cb = sys_notify_finalize(&notify, set_res);
220 	zassert_equal(cb, (sys_notify_generic_callback)callback,
221 		      "callback wrong");
222 	zassert_equal(notify.flags, 0,
223 		      "flags not cleared");
224 
225 	res = ~set_res;
226 	((sys_notify_generic_callback)cb)(&notify, &res);
227 	zassert_equal(res, set_res,
228 		      "result not set");
229 }
230 
231 ZTEST_SUITE(sys_notify_api, NULL, NULL, NULL, NULL, NULL);
232