1 /*
2  * Copyright 2021 The Chromium OS Authors
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/smf.h>
9 
10 /*
11  * Hierarchical 5 Ancestor State Test Transition:
12  *
13  *	P05_ENTRY --> P04_ENTRY --> P03_ENTRY --> P02_ENTRY ---------|
14  *                                                                   |
15  *      |------------------------------------------------------------|
16  *      |
17  *      |--> P01_ENTRY --> A_ENTRY --> A_RUN --> A_EXIT -------------|
18  *                                                                   |
19  *      |------------------------------------------------------------|
20  *      |
21  *      |--> B_ENTRY --> B_RUN --> P01_RUN --> P02_RUN --> P03_RUN --|
22  *                                                                   |
23  *      |------------------------------------------------------------|
24  *      |
25  *      |--> P04_RUN --> P05_RUN --> B_EXIT --> P01_EXIT ------------|
26  *                                                                   |
27  *      |------------------------------------------------------------|
28  *      |
29  *      |--> P02_EXIT --> P03_EXIT --> P04_EXIT --> P05_EXIT --------|
30  *                                                                   |
31  *      |------------------------------------------------------------|
32  *      |
33  *      |--> C_ENTRY --> C_RUN --> C_EXIT --> D_ENTRY
34  */
35 
36 #define TEST_OBJECT(o) ((struct test_object *)o)
37 
38 #define SMF_RUN                         3
39 
40 #define P05_ENTRY_BIT    (1 << 0)
41 #define P04_ENTRY_BIT    (1 << 1)
42 #define P03_ENTRY_BIT    (1 << 2)
43 #define P02_ENTRY_BIT    (1 << 3)
44 #define P01_ENTRY_BIT    (1 << 4)
45 #define A_ENTRY_BIT      (1 << 5)
46 #define A_RUN_BIT        (1 << 6)
47 #define A_EXIT_BIT       (1 << 7)
48 #define B_ENTRY_BIT      (1 << 8)
49 #define B_RUN_BIT        (1 << 9)
50 #define P01_RUN_BIT      (1 << 10)
51 #define P02_RUN_BIT      (1 << 11)
52 #define P03_RUN_BIT      (1 << 12)
53 #define P04_RUN_BIT      (1 << 13)
54 #define P05_RUN_BIT      (1 << 14)
55 #define B_EXIT_BIT       (1 << 15)
56 #define P01_EXIT_BIT     (1 << 16)
57 #define P02_EXIT_BIT     (1 << 17)
58 #define P03_EXIT_BIT     (1 << 18)
59 #define P04_EXIT_BIT     (1 << 19)
60 #define P05_EXIT_BIT     (1 << 20)
61 #define C_ENTRY_BIT      (1 << 21)
62 #define C_RUN_BIT        (1 << 22)
63 #define C_EXIT_BIT       (1 << 23)
64 
65 #define TEST_VALUE_NUM              24
66 static uint32_t test_value[] = {
67 	0x00000000, /* P05_ENTRY */
68 	0x00000001, /* P04_ENTRY */
69 	0x00000003, /* P03_ENTRY */
70 	0x00000007, /* P02_ENTRY */
71 	0x0000000f, /* P01_ENTRY */
72 	0x0000001f, /*   A_ENTRY */
73 	0x0000003f, /*   A_RUN   */
74 	0x0000007f, /*   A_EXIT  */
75 	0x000000ff, /*   B_ENTRY */
76 	0x000001ff, /*   B_RUN   */
77 	0x000003ff, /* P01_RUN   */
78 	0x000007ff, /* P02_RUN   */
79 	0x00000fff, /* P03_RUN   */
80 	0x00001fff, /* P04_RUN   */
81 	0x00003fff, /* P05_RUN   */
82 	0x00007fff, /*   B_EXIT  */
83 	0x0000ffff, /* P01_EXIT  */
84 	0x0001ffff, /* P02_EXIT  */
85 	0x0003ffff, /* P03_EXIT  */
86 	0x0007ffff, /* P04_EXIT  */
87 	0x000fffff, /* P05_EXIT  */
88 	0x001fffff, /*   C_ENTRY */
89 	0x003fffff, /*   C_RUN   */
90 	0x007fffff, /*   C_EXIT  */
91 	0x00ffffff, /*   D_ENTRY */
92 };
93 
94 /* Forward declaration of test_states */
95 static const struct smf_state test_states[];
96 
97 /* List of all TypeC-level states */
98 enum test_state {
99 	P05,
100 	P04,
101 	P03,
102 	P02,
103 	P01,
104 	A,
105 	B,
106 	C,
107 	D,
108 };
109 
110 static struct test_object {
111 	struct smf_ctx ctx;
112 	uint32_t transition_bits;
113 	uint32_t tv_idx;
114 } test_obj;
115 
p05_entry(void * obj)116 static void p05_entry(void *obj)
117 {
118 	struct test_object *o = TEST_OBJECT(obj);
119 
120 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
121 		      "Test Parent 05 entry failed");
122 
123 	o->transition_bits |= P05_ENTRY_BIT;
124 }
125 
p05_run(void * obj)126 static void p05_run(void *obj)
127 {
128 	struct test_object *o = TEST_OBJECT(obj);
129 
130 	o->tv_idx++;
131 
132 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
133 		      "Test Parent 05 run failed");
134 
135 	o->transition_bits |= P05_RUN_BIT;
136 
137 	smf_set_state(SMF_CTX(obj), &test_states[C]);
138 }
139 
p05_exit(void * obj)140 static void p05_exit(void *obj)
141 {
142 	struct test_object *o = TEST_OBJECT(obj);
143 
144 	o->tv_idx++;
145 
146 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
147 		      "Test Parent 05 exit failed");
148 
149 	o->transition_bits |= P05_EXIT_BIT;
150 }
151 
p04_entry(void * obj)152 static void p04_entry(void *obj)
153 {
154 	struct test_object *o = TEST_OBJECT(obj);
155 
156 	o->tv_idx++;
157 
158 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
159 		      "Test Parent 04 entry failed");
160 
161 	o->transition_bits |= P04_ENTRY_BIT;
162 }
163 
p04_run(void * obj)164 static void p04_run(void *obj)
165 {
166 	struct test_object *o = TEST_OBJECT(obj);
167 
168 	o->tv_idx++;
169 
170 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
171 		      "Test Parent 04 run failed");
172 
173 	o->transition_bits |= P04_RUN_BIT;
174 }
175 
p04_exit(void * obj)176 static void p04_exit(void *obj)
177 {
178 	struct test_object *o = TEST_OBJECT(obj);
179 
180 	o->tv_idx++;
181 
182 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
183 		      "Test Parent 04 exit failed");
184 
185 	o->transition_bits |= P04_EXIT_BIT;
186 }
187 
p03_entry(void * obj)188 static void p03_entry(void *obj)
189 {
190 	struct test_object *o = TEST_OBJECT(obj);
191 
192 	o->tv_idx++;
193 
194 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
195 		      "Test Parent 03 entry failed");
196 
197 	o->transition_bits |= P03_ENTRY_BIT;
198 }
199 
p03_run(void * obj)200 static void p03_run(void *obj)
201 {
202 	struct test_object *o = TEST_OBJECT(obj);
203 
204 	o->tv_idx++;
205 
206 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
207 		      "Test Parent 03 run failed");
208 
209 	o->transition_bits |= P03_RUN_BIT;
210 }
211 
p03_exit(void * obj)212 static void p03_exit(void *obj)
213 {
214 	struct test_object *o = TEST_OBJECT(obj);
215 
216 	o->tv_idx++;
217 
218 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
219 		      "Test Parent 03 exit failed");
220 
221 	o->transition_bits |= P03_EXIT_BIT;
222 }
223 
p02_entry(void * obj)224 static void p02_entry(void *obj)
225 {
226 	struct test_object *o = TEST_OBJECT(obj);
227 
228 	o->tv_idx++;
229 
230 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
231 		      "Test Parent 02 entry failed");
232 
233 	o->transition_bits |= P02_ENTRY_BIT;
234 }
235 
p02_run(void * obj)236 static void p02_run(void *obj)
237 {
238 	struct test_object *o = TEST_OBJECT(obj);
239 
240 	o->tv_idx++;
241 
242 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
243 		      "Test Parent 02 run failed");
244 
245 	o->transition_bits |= P02_RUN_BIT;
246 }
247 
p02_exit(void * obj)248 static void p02_exit(void *obj)
249 {
250 	struct test_object *o = TEST_OBJECT(obj);
251 
252 	o->tv_idx++;
253 
254 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
255 		      "Test Parent 02 exit failed");
256 
257 	o->transition_bits |= P02_EXIT_BIT;
258 }
259 
p01_entry(void * obj)260 static void p01_entry(void *obj)
261 {
262 	struct test_object *o = TEST_OBJECT(obj);
263 
264 	o->tv_idx++;
265 
266 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
267 		      "Test Parent 01 entry failed");
268 
269 	o->transition_bits |= P01_ENTRY_BIT;
270 }
271 
p01_run(void * obj)272 static void p01_run(void *obj)
273 {
274 	struct test_object *o = TEST_OBJECT(obj);
275 
276 	o->tv_idx++;
277 
278 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
279 		      "Test Parent 01 run failed");
280 
281 	o->transition_bits |= P01_RUN_BIT;
282 }
283 
p01_exit(void * obj)284 static void p01_exit(void *obj)
285 {
286 	struct test_object *o = TEST_OBJECT(obj);
287 
288 	o->tv_idx++;
289 
290 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
291 		      "Test Parent 01 exit failed");
292 
293 	o->transition_bits |= P01_EXIT_BIT;
294 }
295 
a_entry(void * obj)296 static void a_entry(void *obj)
297 {
298 	struct test_object *o = TEST_OBJECT(obj);
299 
300 	o->tv_idx++;
301 
302 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
303 		      "Test State A entry failed");
304 
305 	o->transition_bits |= A_ENTRY_BIT;
306 }
307 
a_run(void * obj)308 static void a_run(void *obj)
309 {
310 	struct test_object *o = TEST_OBJECT(obj);
311 
312 	o->tv_idx++;
313 
314 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
315 		      "Test State A run failed");
316 
317 	o->transition_bits |= A_RUN_BIT;
318 
319 	smf_set_state(SMF_CTX(obj), &test_states[B]);
320 }
321 
a_exit(void * obj)322 static void a_exit(void *obj)
323 {
324 	struct test_object *o = TEST_OBJECT(obj);
325 
326 	o->tv_idx++;
327 
328 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
329 		      "Test State A exit failed");
330 
331 	o->transition_bits |= A_EXIT_BIT;
332 }
333 
b_entry(void * obj)334 static void b_entry(void *obj)
335 {
336 	struct test_object *o = TEST_OBJECT(obj);
337 
338 	o->tv_idx++;
339 
340 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
341 		      "Test State B entry failed");
342 
343 	o->transition_bits |= B_ENTRY_BIT;
344 }
345 
b_run(void * obj)346 static void b_run(void *obj)
347 {
348 	struct test_object *o = TEST_OBJECT(obj);
349 
350 	o->tv_idx++;
351 
352 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
353 		      "Test State B run failed");
354 
355 	o->transition_bits |= B_RUN_BIT;
356 }
357 
b_exit(void * obj)358 static void b_exit(void *obj)
359 {
360 	struct test_object *o = TEST_OBJECT(obj);
361 
362 	o->tv_idx++;
363 
364 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
365 		      "Test State B exit failed");
366 
367 	o->transition_bits |= B_EXIT_BIT;
368 }
369 
c_entry(void * obj)370 static void c_entry(void *obj)
371 {
372 	struct test_object *o = TEST_OBJECT(obj);
373 
374 	o->tv_idx++;
375 
376 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
377 		      "Test State C entry failed");
378 
379 	o->transition_bits |= C_ENTRY_BIT;
380 }
381 
c_run(void * obj)382 static void c_run(void *obj)
383 {
384 	struct test_object *o = TEST_OBJECT(obj);
385 
386 	o->tv_idx++;
387 
388 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
389 		      "Test State C run failed");
390 	o->transition_bits |= C_RUN_BIT;
391 
392 	smf_set_state(SMF_CTX(obj), &test_states[D]);
393 }
394 
c_exit(void * obj)395 static void c_exit(void *obj)
396 {
397 	struct test_object *o = TEST_OBJECT(obj);
398 
399 	o->tv_idx++;
400 
401 	zassert_equal(o->transition_bits, test_value[o->tv_idx],
402 		      "Test State C exit failed");
403 
404 	o->transition_bits |= C_EXIT_BIT;
405 }
406 
d_entry(void * obj)407 static void d_entry(void *obj)
408 {
409 	struct test_object *o = TEST_OBJECT(obj);
410 
411 	o->tv_idx++;
412 }
413 
414 static const struct smf_state test_states[] = {
415 	[P05] SMF_CREATE_STATE(p05_entry, p05_run, p05_exit, NULL, NULL),
416 	[P04] SMF_CREATE_STATE(p04_entry, p04_run, p04_exit, &test_states[P05], NULL),
417 	[P03] SMF_CREATE_STATE(p03_entry, p03_run, p03_exit, &test_states[P04], NULL),
418 	[P02] SMF_CREATE_STATE(p02_entry, p02_run, p02_exit, &test_states[P03], NULL),
419 	[P01] SMF_CREATE_STATE(p01_entry, p01_run, p01_exit, &test_states[P02], NULL),
420 	[A] = SMF_CREATE_STATE(a_entry, a_run, a_exit, &test_states[P01], NULL),
421 	[B] = SMF_CREATE_STATE(b_entry, b_run, b_exit, &test_states[P01], NULL),
422 	[C] = SMF_CREATE_STATE(c_entry, c_run, c_exit, NULL, NULL),
423 	[D] = SMF_CREATE_STATE(d_entry, NULL, NULL, NULL, NULL),
424 };
425 
ZTEST(smf_tests,test_smf_hierarchical_5_ancestors)426 ZTEST(smf_tests, test_smf_hierarchical_5_ancestors)
427 {
428 	test_obj.tv_idx = 0;
429 	test_obj.transition_bits = 0;
430 	smf_set_initial((struct smf_ctx *)&test_obj, &test_states[A]);
431 
432 	for (int i = 0; i < SMF_RUN; i++) {
433 		if (smf_run_state((struct smf_ctx *)&test_obj) < 0) {
434 			break;
435 		}
436 	}
437 
438 	zassert_equal(TEST_VALUE_NUM, test_obj.tv_idx,
439 		      "Incorrect test value index");
440 	zassert_equal(test_obj.transition_bits, test_value[test_obj.tv_idx],
441 		      "Final state not reached");
442 }
443