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