blob: 3b839412431285e2771d6b98cda62d09f5592573 [file] [log] [blame]
Harald Welte136e7372016-05-29 10:53:17 +09001#include <stdlib.h>
2#include <stdio.h>
3#include <stdarg.h>
4#include <unistd.h>
5#include <string.h>
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +02006#include <errno.h>
Harald Welte136e7372016-05-29 10:53:17 +09007
8#include <osmocom/core/utils.h>
9#include <osmocom/core/select.h>
10#include <osmocom/core/logging.h>
11#include <osmocom/core/fsm.h>
Harald Welte31c0fef2017-04-16 17:26:30 +020012#include <osmocom/ctrl/control_if.h>
Harald Welte136e7372016-05-29 10:53:17 +090013
14enum {
15 DMAIN,
16};
17
18static void *g_ctx;
19
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +020020static int safe_strcmp(const char *a, const char *b)
21{
22 if (!a || !b)
23 return a == b ? 0 : 1;
24 return strcmp(a, b);
25}
Harald Welte136e7372016-05-29 10:53:17 +090026
27enum test_fsm_states {
28 ST_NULL = 0,
29 ST_ONE,
30 ST_TWO,
31};
32
33enum test_fsm_evt {
34 EV_A,
35 EV_B,
36};
37
Stefan Sperling888dc7d2018-02-26 19:17:02 +010038static const struct value_string test_fsm_event_names[] = {
39 OSMO_VALUE_STRING(EV_A),
40 OSMO_VALUE_STRING(EV_B),
41 { 0, NULL }
42};
43
Vadim Yanitskiy477d99f2023-12-27 04:46:51 +070044static void test_fsm_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
45{
46 LOGPFSM(fi, "%s() prev_state=%s\n",
47 __func__, osmo_fsm_state_name(fi->fsm, prev_state));
48}
49
50static void test_fsm_onleave(struct osmo_fsm_inst *fi, uint32_t next_state)
51{
52 LOGPFSM(fi, "%s() next_state=%s\n",
53 __func__, osmo_fsm_state_name(fi->fsm, next_state));
54}
55
Harald Welte136e7372016-05-29 10:53:17 +090056static void test_fsm_null(struct osmo_fsm_inst *fi, uint32_t event, void *data)
57{
58 switch (event) {
59 case EV_A:
60 OSMO_ASSERT(data == (void *) 23);
61 osmo_fsm_inst_state_chg(fi, ST_ONE, 0, 0);
62 break;
63 default:
64 OSMO_ASSERT(0);
65 break;
66 }
67}
68
69static void test_fsm_one(struct osmo_fsm_inst *fi, uint32_t event, void *data)
70{
71 switch (event) {
72 case EV_B:
73 OSMO_ASSERT(data == (void *) 42);
74 osmo_fsm_inst_state_chg(fi,ST_TWO, 1, 2342);
75 break;
76 default:
77 OSMO_ASSERT(0);
78 break;
79 }
80}
81
Neels Hofmeyrd8f175c2018-04-09 00:42:22 +020082static bool main_loop_run = true;
83
Neels Hofmeyrcba8eb92016-12-23 04:32:09 +010084static int test_fsm_tmr_cb(struct osmo_fsm_inst *fi)
Harald Welte136e7372016-05-29 10:53:17 +090085{
86 OSMO_ASSERT(fi->T == 2342);
87 OSMO_ASSERT(fi->state == ST_TWO);
88 LOGP(DMAIN, LOGL_INFO, "Timer\n");
89
Neels Hofmeyrd8f175c2018-04-09 00:42:22 +020090 main_loop_run = false;
91
92 return 0;
Harald Welte136e7372016-05-29 10:53:17 +090093}
94
95static struct osmo_fsm_state test_fsm_states[] = {
96 [ST_NULL] = {
97 .in_event_mask = (1 << EV_A),
98 .out_state_mask = (1 << ST_ONE),
99 .name = "NULL",
100 .action = test_fsm_null,
Vadim Yanitskiy477d99f2023-12-27 04:46:51 +0700101 .onenter = test_fsm_onenter,
102 .onleave = test_fsm_onleave,
Harald Welte136e7372016-05-29 10:53:17 +0900103 },
104 [ST_ONE]= {
105 .in_event_mask = (1 << EV_B),
106 .out_state_mask = (1 << ST_TWO),
107 .name = "ONE",
108 .action= test_fsm_one,
Vadim Yanitskiy477d99f2023-12-27 04:46:51 +0700109 .onenter = test_fsm_onenter,
110 .onleave = test_fsm_onleave,
Harald Welte136e7372016-05-29 10:53:17 +0900111 },
112 [ST_TWO]= {
113 .in_event_mask = 0,
114 .name = "TWO",
115 .action = NULL,
Vadim Yanitskiy477d99f2023-12-27 04:46:51 +0700116 .onenter = test_fsm_onenter,
117 .onleave = test_fsm_onleave,
Harald Welte136e7372016-05-29 10:53:17 +0900118 },
119};
120
121static struct osmo_fsm fsm = {
Harald Welte31c0fef2017-04-16 17:26:30 +0200122 .name = "Test_FSM",
Harald Welte136e7372016-05-29 10:53:17 +0900123 .states = test_fsm_states,
124 .num_states = ARRAY_SIZE(test_fsm_states),
125 .log_subsys = DMAIN,
Stefan Sperling888dc7d2018-02-26 19:17:02 +0100126 .event_names = test_fsm_event_names,
Harald Welte136e7372016-05-29 10:53:17 +0900127};
128
Harald Welte31c0fef2017-04-16 17:26:30 +0200129static struct ctrl_handle *g_ctrl;
130
131static struct ctrl_cmd *exec_ctrl_cmd(const char *cmdstr)
132{
133 struct ctrl_cmd *cmd;
Vadim Yanitskiy35b54d12017-05-14 20:38:44 +0300134
135 cmd = ctrl_cmd_exec_from_string(g_ctrl, cmdstr);
Harald Welte31c0fef2017-04-16 17:26:30 +0200136 OSMO_ASSERT(cmd);
Vadim Yanitskiy35b54d12017-05-14 20:38:44 +0300137
Harald Welte31c0fef2017-04-16 17:26:30 +0200138 return cmd;
139}
140
141static void assert_cmd_reply(const char *cmdstr, const char *expres)
142{
143 struct ctrl_cmd *cmd;
144
145 cmd = exec_ctrl_cmd(cmdstr);
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +0200146 if (safe_strcmp(cmd->reply, expres)) {
Harald Welte31c0fef2017-04-16 17:26:30 +0200147 fprintf(stderr, "Reply '%s' doesn't match expected '%s'\n", cmd->reply, expres);
148 OSMO_ASSERT(0);
149 }
150 talloc_free(cmd);
151}
152
Max3de97e12016-11-02 10:37:58 +0100153static struct osmo_fsm_inst *foo(void)
Harald Welte136e7372016-05-29 10:53:17 +0900154{
155 struct osmo_fsm_inst *fi;
Harald Welte31c0fef2017-04-16 17:26:30 +0200156 struct ctrl_cmd *cmd;
Harald Welte136e7372016-05-29 10:53:17 +0900157
158 LOGP(DMAIN, LOGL_INFO, "Checking FSM allocation\n");
Harald Welte4585e672017-04-16 17:23:56 +0200159 fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, "my_id");
Harald Welte136e7372016-05-29 10:53:17 +0900160 OSMO_ASSERT(fi);
161 OSMO_ASSERT(fi->fsm == &fsm);
162 OSMO_ASSERT(!strncmp(osmo_fsm_inst_name(fi), fsm.name, strlen(fsm.name)));
163 OSMO_ASSERT(fi->state == ST_NULL);
164 OSMO_ASSERT(fi->log_level == LOGL_DEBUG);
Harald Welte31c0fef2017-04-16 17:26:30 +0200165 assert_cmd_reply("GET 1 fsm.Test_FSM.id.my_id.state", "NULL");
166 assert_cmd_reply("GET 1 fsm.Test_FSM.id.my_id.timer", "0,0,0");
Harald Welte136e7372016-05-29 10:53:17 +0900167
168 /* Try invalid state transition */
169 osmo_fsm_inst_dispatch(fi, EV_B, (void *) 42);
170 OSMO_ASSERT(fi->state == ST_NULL);
Harald Welte31c0fef2017-04-16 17:26:30 +0200171 assert_cmd_reply("GET 1 fsm.Test_FSM.id.my_id.state", "NULL");
172
Harald Welte136e7372016-05-29 10:53:17 +0900173
174 /* Legitimate state transition */
175 osmo_fsm_inst_dispatch(fi, EV_A, (void *) 23);
176 OSMO_ASSERT(fi->state == ST_ONE);
Harald Welte31c0fef2017-04-16 17:26:30 +0200177 assert_cmd_reply("GET 1 fsm.Test_FSM.id.my_id.state", "ONE");
Harald Welte136e7372016-05-29 10:53:17 +0900178
179 /* Legitimate transition with timer */
180 fsm.timer_cb = test_fsm_tmr_cb;
181 osmo_fsm_inst_dispatch(fi, EV_B, (void *) 42);
182 OSMO_ASSERT(fi->state == ST_TWO);
Harald Welte31c0fef2017-04-16 17:26:30 +0200183 assert_cmd_reply("GET 1 fsm.Test_FSM.id.my_id.state", "TWO");
Harald Welte136e7372016-05-29 10:53:17 +0900184
Harald Welte31c0fef2017-04-16 17:26:30 +0200185 cmd = exec_ctrl_cmd("GET 2 fsm.Test_FSM.id.my_id.dump");
186 const char *exp = "'Test_FSM(my_id)','my_id','DEBUG','TWO',2342,timeout_sec=";
187 OSMO_ASSERT(!strncmp(cmd->reply, exp, strlen(exp)));
188 talloc_free(cmd);
Harald Welte136e7372016-05-29 10:53:17 +0900189
Max3de97e12016-11-02 10:37:58 +0100190 return fi;
Harald Welte136e7372016-05-29 10:53:17 +0900191}
192
Harald Weltee61d4592022-11-03 11:05:58 +0100193static void test_id_api(void)
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +0200194{
195 struct osmo_fsm_inst *fi;
196
197 fprintf(stderr, "\n--- %s()\n", __func__);
198
199/* Assert the instance has this name and can be looked up by it */
200#define assert_name(expected_name) \
201do { \
202 const char *name = osmo_fsm_inst_name(fi); \
203 fprintf(stderr, " osmo_fsm_inst_name() == %s\n", osmo_quote_str(name, -1)); \
204 if (safe_strcmp(name, expected_name)) { \
205 fprintf(stderr, " ERROR: expected %s\n", osmo_quote_str(expected_name, -1)); \
206 OSMO_ASSERT(false); \
207 } \
208 OSMO_ASSERT(osmo_fsm_inst_find_by_name(&fsm, expected_name) == fi); \
209 fprintf(stderr, " osmo_fsm_inst_find_by_name(%s) == fi\n", osmo_quote_str(expected_name, -1)); \
210} while(0)
211
212/* Assert the instance can be looked up by this id string */
213#define assert_id(expected_id) \
214do { \
215 OSMO_ASSERT(osmo_fsm_inst_find_by_id(&fsm, expected_id) == fi); \
216 fprintf(stderr, " osmo_fsm_inst_find_by_id(%s) == fi\n", osmo_quote_str(expected_id, -1)); \
217} while(0)
218
219/* Update the id, assert the proper rc, and expect a resulting fsm inst name + lookup */
220#define test_id(new_id, expect_rc, expect_name_suffix) do { \
221 int rc; \
222 fprintf(stderr, "osmo_fsm_inst_update_id(%s)\n", osmo_quote_str(new_id, -1)); \
223 rc = osmo_fsm_inst_update_id(fi, new_id); \
224 fprintf(stderr, " rc == %d", rc); \
225 if (rc == (expect_rc)) \
226 fprintf(stderr, ", ok\n"); \
227 else { \
228 fprintf(stderr, ", ERROR: expected rc == %d\n", expect_rc); \
229 OSMO_ASSERT(rc == expect_rc); \
230 } \
231 assert_name("Test_FSM" expect_name_suffix); \
232 }while (0)
233
234/* Successfully set a new id, along with name and id lookup assertions */
235#define change_id(new_id) \
236 test_id(new_id, 0, "(" new_id ")"); \
237 assert_id(new_id)
238
239 /* allocate FSM instance without id, there should be a name without id */
240 fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);
241 OSMO_ASSERT(fi);
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +0200242 assert_name("Test_FSM");
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +0200243
244 change_id("my_id");
245 change_id("another_id");
246
247 test_id(NULL, 0, "");
248 /* clear already cleared id */
249 test_id(NULL, 0, "");
250
251 change_id("arbitrary_id");
252
253 /* clear id by empty string doesn't work */
254 test_id("", -EINVAL, "(arbitrary_id)");
255
256 test_id("invalid.id", -EINVAL, "(arbitrary_id)");
257
Neels Hofmeyra64c45a2018-03-31 16:34:49 +0200258 fprintf(stderr, "--- id format tests...\n");
259/* Update the id, assert the proper rc, and expect a resulting fsm inst name + lookup */
260#define test_id_f(expect_rc, expect_name_suffix, new_id_fmt, args...) do { \
261 int rc; \
262 fprintf(stderr, "osmo_fsm_inst_update_id_f(%s, " #args ")\n", \
263 osmo_quote_str(new_id_fmt, -1)); \
264 rc = osmo_fsm_inst_update_id_f(fi, new_id_fmt, ## args); \
265 fprintf(stderr, " rc == %d", rc); \
266 if (rc == (expect_rc)) \
267 fprintf(stderr, ", ok\n"); \
268 else { \
269 fprintf(stderr, ", ERROR: expected rc == %d\n", expect_rc); \
270 OSMO_ASSERT(rc == expect_rc); \
271 } \
272 assert_name("Test_FSM" expect_name_suffix); \
273 }while (0)
274
275 test_id_f(-EINVAL, "(arbitrary_id)", "format%cid", '.');
276 test_id_f(-EINVAL, "(arbitrary_id)", "%s", "");
277 test_id_f(0, "(format23id42)", "format%xid%d", 0x23, 42);
278 test_id_f(0, "", NULL);
279 test_id_f(0, "", NULL);
280 test_id_f(0, "(arbitrary_id)", "%s%c%s", "arbitrary", '_', "id");
281
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +0200282 fprintf(stderr, "\n--- %s() done\n\n", __func__);
283
284 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);
285}
286
Neels Hofmeyr407df022018-05-25 18:20:06 +0200287const struct timeval fake_time_start_time = { 123, 456 };
288
289#define fake_time_passes(secs, usecs) do \
290{ \
291 struct timeval diff; \
292 osmo_gettimeofday_override_add(secs, usecs); \
293 osmo_clock_override_add(CLOCK_MONOTONIC, secs, usecs * 1000); \
294 timersub(&osmo_gettimeofday_override_time, &fake_time_start_time, &diff); \
295 fprintf(stderr, "Total time passed: %d.%06d s\n", \
296 (int)diff.tv_sec, (int)diff.tv_usec); \
297 osmo_timers_prepare(); \
298 osmo_timers_update(); \
299} while (0)
300
Harald Weltee61d4592022-11-03 11:05:58 +0100301void fake_time_start(void)
Neels Hofmeyr407df022018-05-25 18:20:06 +0200302{
303 struct timespec *clock_override;
304
305 osmo_gettimeofday_override_time = fake_time_start_time;
306 osmo_gettimeofday_override = true;
307 clock_override = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
308 OSMO_ASSERT(clock_override);
309 clock_override->tv_sec = fake_time_start_time.tv_sec;
310 clock_override->tv_nsec = fake_time_start_time.tv_usec * 1000;
311 osmo_clock_override_enable(CLOCK_MONOTONIC, true);
312 fake_time_passes(0, 0);
313}
314
315static int timeout_fired = 0;
316static int timer_cb(struct osmo_fsm_inst *fi)
317{
318 timeout_fired = fi->T;
319 return 0;
320}
321
Harald Weltee61d4592022-11-03 11:05:58 +0100322static void test_state_chg_keep_timer(void)
Neels Hofmeyr407df022018-05-25 18:20:06 +0200323{
324 struct osmo_fsm_inst *fi;
325
326 fprintf(stderr, "\n--- %s()\n", __func__);
327
328 fsm.timer_cb = timer_cb;
329
330 /* Test that no timer remains no timer */
331 fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);
332 OSMO_ASSERT(fi);
333
334 osmo_fsm_inst_state_chg(fi, ST_ONE, 0, 0);
335 timeout_fired = -1;
336
337 osmo_fsm_inst_state_chg_keep_timer(fi, ST_TWO);
338
339 OSMO_ASSERT(timeout_fired == -1);
340 OSMO_ASSERT(fi->T == 0);
341
342 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);
343
344 /* Test that a set time continues with exact precision */
345 fake_time_start();
346 fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);
347 OSMO_ASSERT(fi);
348
349 osmo_fsm_inst_state_chg(fi, ST_ONE, 10, 10);
350
351 timeout_fired = -1;
352
353 fake_time_passes(2, 342);
354 osmo_fsm_inst_state_chg_keep_timer(fi, ST_TWO);
355
356 fake_time_passes(0, 0);
357 OSMO_ASSERT(timeout_fired == -1);
358
359 fake_time_passes(7, 1000000 - 342 - 1);
360 OSMO_ASSERT(timeout_fired == -1);
361
362 fake_time_passes(0, 1);
363 OSMO_ASSERT(timeout_fired == 10);
364
365 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);
366
367 fprintf(stderr, "--- %s() done\n", __func__);
368}
369
Harald Weltee61d4592022-11-03 11:05:58 +0100370static void test_state_chg_T(void)
Neels Hofmeyrbd5a1dc2019-01-28 15:38:09 +0100371{
372 struct osmo_fsm_inst *fi;
373
374 fprintf(stderr, "\n--- %s()\n", __func__);
375
376 fsm.timer_cb = NULL;
377
378 /* Test setting to timeout_secs = 0, T = 0 */
379 fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);
380 OSMO_ASSERT(fi);
381
382 osmo_fsm_inst_state_chg(fi, ST_ONE, 23, 42);
383 printf("T = %d\n", fi->T);
384 OSMO_ASSERT(fi->T == 42);
385 osmo_fsm_inst_state_chg(fi, ST_TWO, 0, 0);
386 printf("T = %d\n", fi->T);
387 OSMO_ASSERT(fi->T == 0);
388
389 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);
390
391 /* Test setting to timeout_secs = 0, T != 0 */
392 fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);
393 OSMO_ASSERT(fi);
394
395 osmo_fsm_inst_state_chg(fi, ST_ONE, 23, 42);
396 printf("T = %d\n", fi->T);
397 OSMO_ASSERT(fi->T == 42);
398 osmo_fsm_inst_state_chg(fi, ST_TWO, 0, 11);
399 printf("T = %d\n", fi->T);
400 OSMO_ASSERT(fi->T == 11);
401
402 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);
403
404 fprintf(stderr, "--- %s() done\n", __func__);
405}
406
Vadim Yanitskiyd2964a92022-07-19 06:08:42 +0700407/* Test setting a state timeout with second granularity */
408static void test_state_chg_Ts(void)
409{
410 struct osmo_fsm_inst *fi;
411
412 fprintf(stderr, "\n--- %s()\n", __func__);
413
414 fsm.timer_cb = &timer_cb;
415 timeout_fired = -1;
416 fake_time_start();
417
418 fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);
419 OSMO_ASSERT(fi);
420
421 osmo_fsm_inst_state_chg(fi, ST_ONE, 8, 4242);
422 OSMO_ASSERT(timeout_fired == -1);
423
424 fake_time_passes(3, 0); /* +3s */
425 OSMO_ASSERT(timeout_fired == -1);
426
427 fake_time_passes(2, 500000); /* +2.5s */
428 OSMO_ASSERT(timeout_fired == -1);
429
430 fake_time_passes(2, 500000); /* +2.5s */
431 OSMO_ASSERT(timeout_fired == 4242);
432
433 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);
434
435 fprintf(stderr, "--- %s() done\n", __func__);
436}
437
438/* Test setting a state timeout with millisecond granularity */
439static void test_state_chg_Tms(void)
440{
441 struct osmo_fsm_inst *fi;
442
443 fprintf(stderr, "\n--- %s()\n", __func__);
444
445 fsm.timer_cb = &timer_cb;
446 timeout_fired = -1;
447 fake_time_start();
448
449 fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);
450 OSMO_ASSERT(fi);
451
452 osmo_fsm_inst_state_chg_ms(fi, ST_ONE, 1337, 4242); /* 1s 337ms */
453 OSMO_ASSERT(timeout_fired == -1);
454
455 fake_time_passes(0, 500000); /* +500ms, 500ms total */
456 OSMO_ASSERT(timeout_fired == -1);
457
458 fake_time_passes(0, 250000); /* +250ms, 750ms total */
459 OSMO_ASSERT(timeout_fired == -1);
460
461 fake_time_passes(0, 350000); /* +350ms, 1s 100ms total */
Vadim Yanitskiy76bdbd42022-07-19 06:20:55 +0700462 OSMO_ASSERT(timeout_fired == -1);
Vadim Yanitskiyd2964a92022-07-19 06:08:42 +0700463
464 fake_time_passes(0, 200000); /* +200ms, 1s 300ms total */
Vadim Yanitskiy76bdbd42022-07-19 06:20:55 +0700465 OSMO_ASSERT(timeout_fired == -1);
Vadim Yanitskiyd2964a92022-07-19 06:08:42 +0700466
467 fake_time_passes(0, 37000); /* +37ms, 1s 337ms total */
Vadim Yanitskiy76bdbd42022-07-19 06:20:55 +0700468 OSMO_ASSERT(timeout_fired == 4242);
Vadim Yanitskiyd2964a92022-07-19 06:08:42 +0700469
470 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);
471
472 fprintf(stderr, "--- %s() done\n", __func__);
473}
474
Harald Welte136e7372016-05-29 10:53:17 +0900475static const struct log_info_cat default_categories[] = {
476 [DMAIN] = {
477 .name = "DMAIN",
478 .description = "Main",
479 .enabled = 1, .loglevel = LOGL_DEBUG,
480 },
481};
482
483static const struct log_info log_info = {
484 .cat = default_categories,
485 .num_cat = ARRAY_SIZE(default_categories),
486};
487
488int main(int argc, char **argv)
489{
490 struct log_target *stderr_target;
Max3de97e12016-11-02 10:37:58 +0100491 struct osmo_fsm_inst *finst;
Harald Welte136e7372016-05-29 10:53:17 +0900492
493 osmo_fsm_log_addr(false);
494
Neels Hofmeyr050f2d32018-05-31 15:30:15 +0200495 /* Using fake time to get deterministic timeout logging */
496 osmo_fsm_log_timeouts(true);
497
Harald Welte136e7372016-05-29 10:53:17 +0900498 log_init(&log_info, NULL);
499 stderr_target = log_target_create_stderr();
500 log_add_target(stderr_target);
Pau Espin Pedrol01e0d3e2021-02-18 19:25:44 +0100501 log_set_print_filename2(stderr_target, LOG_FILENAME_NONE);
Pau Espin Pedroleb028fa2020-07-20 16:46:54 +0200502 log_set_use_color(stderr_target, 0);
Pau Espin Pedrol690b6612021-02-18 19:10:28 +0100503 log_set_print_category(stderr_target, 0);
504 log_set_print_category_hex(stderr_target, 0);
Harald Welte31c0fef2017-04-16 17:26:30 +0200505 g_ctrl = ctrl_handle_alloc(NULL, NULL, NULL);
Harald Welte136e7372016-05-29 10:53:17 +0900506
Harald Welte4585e672017-04-16 17:23:56 +0200507 g_ctx = NULL;
508 OSMO_ASSERT(osmo_fsm_find_by_name(fsm.name) == NULL);
Harald Welteae5016f2019-12-01 13:38:20 +0100509 OSMO_ASSERT(osmo_fsm_register(&fsm) == 0);
Harald Welte4585e672017-04-16 17:23:56 +0200510 OSMO_ASSERT(osmo_fsm_find_by_name(fsm.name) == &fsm);
511
512 OSMO_ASSERT(osmo_fsm_inst_find_by_name(&fsm, "my_id") == NULL);
Max3de97e12016-11-02 10:37:58 +0100513 finst = foo();
Harald Welte136e7372016-05-29 10:53:17 +0900514
Neels Hofmeyrd8f175c2018-04-09 00:42:22 +0200515 while (main_loop_run) {
Harald Welte136e7372016-05-29 10:53:17 +0900516 osmo_select_main(0);
517 }
Max3de97e12016-11-02 10:37:58 +0100518 osmo_fsm_inst_free(finst);
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +0200519
520 test_id_api();
Neels Hofmeyr407df022018-05-25 18:20:06 +0200521 test_state_chg_keep_timer();
Neels Hofmeyrbd5a1dc2019-01-28 15:38:09 +0100522 test_state_chg_T();
Vadim Yanitskiyd2964a92022-07-19 06:08:42 +0700523 test_state_chg_Ts();
524 test_state_chg_Tms();
Neels Hofmeyr975ee6b2018-04-09 00:42:12 +0200525
Max8b25a3f2016-11-01 11:02:17 +0100526 osmo_fsm_unregister(&fsm);
Harald Welte136e7372016-05-29 10:53:17 +0900527 exit(0);
528}