summaryrefslogtreecommitdiff
path: root/cesar/cp/eoc/fsm/test/utest/src/test_fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/cp/eoc/fsm/test/utest/src/test_fsm.c')
-rw-r--r--cesar/cp/eoc/fsm/test/utest/src/test_fsm.c477
1 files changed, 477 insertions, 0 deletions
diff --git a/cesar/cp/eoc/fsm/test/utest/src/test_fsm.c b/cesar/cp/eoc/fsm/test/utest/src/test_fsm.c
new file mode 100644
index 0000000000..54a17abc6d
--- /dev/null
+++ b/cesar/cp/eoc/fsm/test/utest/src/test_fsm.c
@@ -0,0 +1,477 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_fsm.c
+ * \brief Test FSM module.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "lib/blk.h"
+#include "lib/test.h"
+#include "lib/scenario/scenario.h"
+
+#include "cp/fsm/fsm.h"
+
+#include "cp/inc/context.h"
+
+#include "cp/sta/core/core.h"
+
+extern int cp_fsm__STATE1__enter_nb;
+extern int cp_fsm__STATE2__enter_nb;
+
+void
+test_fsm_basic_test_case (test_t t)
+{
+ test_case_begin (t, "basic");
+ cp_t cp;
+ cp.sta_core_urgent_flag = false;
+ cp_trace_init (&cp);
+ slab_cache_t cache;
+ slab_cache_init (&cache, "dummy", 1, NULL);
+ cp_mme_rx_t *mme = slab_alloc (&cache);
+ cp_sta_t *sta = slab_alloc (&cache);
+ cp_net_t *net = (void *) 0x9abcdef0;
+ bsu_beacon_t *beacon = blk_alloc ();
+ test_begin (t, "bare")
+ {
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ /* STATE1 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_EVENT (cp_fsm__STATE1__event1),
+ /* STATE1 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event2),
+ SCENARIO_EVENT (cp_fsm__STATE1__event2),
+ /* STATE2 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event3),
+ SCENARIO_EVENT (cp_fsm__STATE2__event3,
+ .branch = CP_FSM_BRANCH (STATE2, event3, branch1)),
+ /* STATE3 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_EVENT (cp_fsm__STATE3__event1,
+ .branch = CP_FSM_BRANCH (STATE3, event1, branch2)),
+ /* STATE3 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event2),
+ SCENARIO_EVENT (cp_fsm__STATE3__event2),
+ /* STATE2 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event3),
+ SCENARIO_EVENT (cp_fsm__STATE2__event3,
+ .branch = CP_FSM_BRANCH (STATE2, event3, branch2)),
+ /* STATE4 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_EVENT (cp_fsm__STATE4__event1,
+ .branch = CP_FSM_BRANCH (STATE4, event1, branch2)),
+ /* STATE4 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_EVENT (cp_fsm__STATE4__event1,
+ .branch = CP_FSM_BRANCH (STATE4, event1, branch1)),
+ /* STATE1 */
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ test_begin (t, "mme")
+ {
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event_mme, .mme = mme),
+ SCENARIO_EVENT (cp_fsm__STATE1__event_mme, .mme = mme),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ test_begin (t, "sta")
+ {
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event_sta,
+ .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_fsm__STATE1__event_sta,
+ .net = net, .sta = sta),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ test_begin (t, "beacon")
+ {
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event_beacon,
+ .beacon = beacon, .net = net, .sta = sta),
+ SCENARIO_EVENT (cp_fsm__STATE1__event_beacon,
+ .beacon = beacon, .net = net, .sta = sta),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ test_begin (t, "dual")
+ {
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ /* STATE1, STATEA */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_eventb),
+ SCENARIO_EVENT (cp_fsm__STATE1__eventb),
+ SCENARIO_EVENT (cp_fsm__STATEA__eventb),
+ /* STATE3, STATEB */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_eventa),
+ SCENARIO_EVENT (cp_fsm__STATEB__eventa),
+ /* STATE3, STATEA */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_EVENT (cp_fsm__STATE3__event1,
+ .branch = CP_FSM_BRANCH (STATE3, event1, branch1)),
+ /* STATE1, STATEA */
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ test_fail_unless (cp.fsm.active_states[1] == CP_FSM_STATE_STATEA);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ test_begin (t, "no action")
+ {
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ /* STATE1 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event_no_action),
+ /* STATE3 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_EVENT (cp_fsm__STATE3__event1,
+ .branch = CP_FSM_BRANCH (STATE3, event1, branch1)),
+ /* STATE1 */
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ test_begin (t, "enter leave")
+ {
+ cp_fsm__STATE1__enter_nb = 0;
+ cp_fsm__STATE2__enter_nb = 0;
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ /* STATE1 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event5),
+ SCENARIO_EVENT (cp_fsm__STATE5__enter),
+ /* STATE5 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event5),
+ /* No enter/leave here. */
+ /* STATE5 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event6),
+ SCENARIO_EVENT (cp_fsm__STATE5__leave),
+ SCENARIO_EVENT (cp_fsm__STATE6__enter),
+ /* STATE6 */
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_EVENT (cp_fsm__STATE6__leave),
+ /* STATE1 */
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ test_fail_unless (cp_fsm__STATE1__enter_nb == 2);
+ test_fail_unless (cp_fsm__STATE2__enter_nb == 0);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ test_begin (t, "trigger")
+ {
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ /* STATE1 */
+ SCENARIO_ACTION (post, .type = CP_FSM_EVENT_TYPE_event3),
+ SCENARIO_ACTION (trigger, .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_ACTION (trigger, .type = CP_FSM_EVENT_TYPE_event2),
+ SCENARIO_ACTION (process),
+ SCENARIO_EVENT (cp_fsm__STATE1__event1),
+ SCENARIO_ACTION (process),
+ SCENARIO_EVENT (cp_fsm__STATE1__event2),
+ /* STATE2 */
+ SCENARIO_ACTION (process),
+ SCENARIO_EVENT (cp_fsm__STATE2__event3,
+ .branch = CP_FSM_BRANCH (STATE2, event3, branch1)),
+ /* STATE3 */
+ SCENARIO_ACTION (trigger, .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_ACTION (process),
+ SCENARIO_EVENT (cp_fsm__STATE3__event1,
+ .branch = CP_FSM_BRANCH (STATE3, event1, branch1)),
+ /* STATE1 */
+ /* Now, test some insertion corner cases. */
+ SCENARIO_ACTION (trigger, .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_ACTION (trigger, .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_ACTION (post, .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ test_begin (t, "urgent")
+ {
+ cp_fsm_init (&cp);
+ cp.sta_core_flag = false;
+ scenario_entry_t entries[] = {
+ /* STATE1 */
+ SCENARIO_ACTION (post, .type = CP_FSM_EVENT_TYPE_long_event),
+ SCENARIO_ACTION (post_urgent,
+ .type = CP_FSM_EVENT_TYPE_urgent_event),
+ SCENARIO_ACTION (process),
+ SCENARIO_EVENT (cp_fsm__STATE1__long_event),
+ SCENARIO_EVENT (cp_fsm__STATE1__urgent_event),
+ /* STATE3 */
+ SCENARIO_ACTION (post_urgent,
+ .type = CP_FSM_EVENT_TYPE_urgent_event),
+ SCENARIO_ACTION (post_urgent,
+ .type = CP_FSM_EVENT_TYPE_urgent_event),
+ SCENARIO_ACTION (process_urgent),
+ SCENARIO_EVENT (cp_fsm__STATE3__urgent_event),
+ SCENARIO_ACTION (process_urgent),
+ SCENARIO_EVENT (cp_fsm__STATE3__urgent_event),
+ SCENARIO_ACTION (post_and_process,
+ .type = CP_FSM_EVENT_TYPE_event1),
+ SCENARIO_EVENT (cp_fsm__STATE3__event1,
+ .branch = CP_FSM_BRANCH (STATE3, event1, branch1)),
+ SCENARIO_END
+ };
+ scenario_globals_t globals = {
+ .cp = &cp,
+ };
+ scenario_run (t, entries, &globals);
+ test_fail_unless (cp.fsm.active_states[0] == CP_FSM_STATE_STATE1);
+ cp_fsm_uninit (&cp);
+ } test_end;
+ slab_release (mme);
+ slab_release (sta);
+ slab_cache_uninit (&cache);
+ blk_release (beacon);
+#if CONFIG_TRACE
+ trace_buffer_dbg_dump (&cp.trace);
+#endif /* CONFIG_TRACE */
+ cp_trace_uninit (&cp);
+}
+
+void
+test_fsm_error_test_case (test_t t)
+{
+ test_case_begin (t, "error");
+ cp_t cp;
+ cp_trace_init (&cp);
+ test_begin (t, "no branch")
+ {
+ cp_fsm_init (&cp);
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ &cp, CP_FSM_EVENT_TYPE_error_event_no_branch);
+ cp_fsm_post (&cp, event);
+ const char *asserted = NULL;
+ dbg_fatal_try_begin
+ {
+ cp_fsm_process (&cp);
+ }
+ dbg_fatal_try_catch (const char *msg)
+ {
+ slab_release (event); /* Was not release due to assert. */
+ asserted = msg;
+ }
+ dbg_fatal_try_end;
+ test_fail_unless (asserted);
+ } test_end;
+ test_begin (t, "bad branch")
+ {
+ cp_fsm_init (&cp);
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ &cp, CP_FSM_EVENT_TYPE_error_event_bad_branch);
+ cp_fsm_post (&cp, event);
+ const char *asserted = NULL;
+ dbg_fatal_try_begin
+ {
+ cp_fsm_process (&cp);
+ }
+ dbg_fatal_try_catch (const char *msg)
+ {
+ slab_release (event); /* Was not release due to assert. */
+ asserted = msg;
+ }
+ dbg_fatal_try_end;
+ test_fail_unless (asserted);
+ } test_end;
+ test_begin (t, "dup branch")
+ {
+ cp_fsm_init (&cp);
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ &cp, CP_FSM_EVENT_TYPE_error_event_dup_branch);
+ cp_fsm_post (&cp, event);
+ const char *asserted = NULL;
+ dbg_fatal_try_begin
+ {
+ cp_fsm_process (&cp);
+ }
+ dbg_fatal_try_catch (const char *msg)
+ {
+ slab_release (event); /* Was not release due to assert. */
+ asserted = msg;
+ }
+ dbg_fatal_try_end;
+ test_fail_unless (asserted);
+ } test_end;
+ test_begin (t, "not in transition")
+ {
+ cp_fsm_init (&cp);
+ const char *asserted = NULL;
+ dbg_fatal_try_begin
+ {
+ cp_fsm_branch (&cp, STATE1, error_event_no_branch, branch1);
+ }
+ dbg_fatal_try_catch (const char *msg)
+ {
+ asserted = msg;
+ }
+ dbg_fatal_try_end;
+ test_fail_unless (asserted);
+ } test_end;
+ test_begin (t, "transition for urgent event")
+ {
+ cp_fsm_init (&cp);
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ &cp, CP_FSM_EVENT_TYPE_error_urgent_event_transition);
+ cp_fsm_post_urgent (&cp, event);
+ const char *asserted = NULL;
+ dbg_fatal_try_begin
+ {
+ cp_fsm_process_urgent (&cp);
+ }
+ dbg_fatal_try_catch (const char *msg)
+ {
+ slab_release (event); /* Was not release due to assert. */
+ asserted = msg;
+ }
+ dbg_fatal_try_end;
+ test_fail_unless (asserted);
+ } test_end;
+ test_begin (t, "branch for urgent event")
+ {
+ cp_fsm_init (&cp);
+ cp_fsm_event_t *event = cp_fsm_event_bare_new (
+ &cp, CP_FSM_EVENT_TYPE_error_urgent_event_branch);
+ cp_fsm_post_urgent (&cp, event);
+ const char *asserted = NULL;
+ dbg_fatal_try_begin
+ {
+ cp_fsm_process_urgent (&cp);
+ }
+ dbg_fatal_try_catch (const char *msg)
+ {
+ slab_release (event); /* Was not release due to assert. */
+ asserted = msg;
+ }
+ dbg_fatal_try_end;
+ test_fail_unless (asserted);
+ } test_end;
+#if CONFIG_TRACE
+ trace_buffer_dbg_dump (&cp.trace);
+#endif /* CONFIG_TRACE */
+ cp_trace_uninit (&cp);
+}
+
+void
+test_fsm_test_suite (test_t t)
+{
+ test_suite_begin (t, "fsm");
+ test_fsm_basic_test_case (t);
+ test_fsm_error_test_case (t);
+ test_case_begin (t, "memory");
+ test_begin (t, "memory")
+ {
+ test_fail_unless (blk_check_memory ());
+ } test_end;
+}
+
+void
+cp_sta_core_signal_fsm_event (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ ctx->sta_core_flag = true;
+}
+
+void
+cp_sta_core_signal_fsm_urgent_event (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ ctx->sta_core_urgent_flag = true;
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ trace_init ();
+ test_init (t, argc, argv);
+ test_fsm_test_suite (t);
+ trace_uninit ();
+ test_result (t);
+ return test_nb_failed (t) == 0 ? 0 : 1;
+}
+