awtk/tests/state_machine_utest.c
2023-01-03 18:34:27 +08:00

275 lines
7.1 KiB
C

/**
* File: state_machine.c
* Author: AWTK Develop Team
* Brief: state_machine
*
* Copyright (c) 2019 - 2023 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
*/
/**
* History:
* ================================================================
* 2020-12-29 code generated
* 2020-12-29 Wang LinFu <wanglinfu@zlg.cn> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "tkc/state_machine.h"
typedef enum {
EVENT_IDLE,
EVENT_A,
EVENT_B,
EVENT_C,
EVENT_D,
EVENT_E,
EVENT_MAX_NUM,
} event_type_t;
static bool_t condition_check(void* condition, tk_sm_event_t* event) {
str_t* str = ((str_t*)event->data);
return tk_str_start_with(str->str, (const char*)condition);
}
static void on_base_action(void* old_state_data, tk_sm_event_t* event, void* new_state_data) {
str_t* str = ((str_t*)event->data);
ENSURE(tk_str_eq((const char*)old_state_data, "idle"));
ENSURE(tk_str_eq((const char*)new_state_data, "idle"));
str_append(str, "base");
}
static void on_idle_action(void* old_state_data, tk_sm_event_t* event, void* new_state_data) {
str_t* str = ((str_t*)event->data);
ENSURE(tk_str_eq((const char*)old_state_data, "idle"));
str_append(str, ",idle");
}
static void on_common_action(void* old_state_data, tk_sm_event_t* event, void* new_state_data) {
str_t* str = ((str_t*)event->data);
if (tk_str_eq((char*)old_state_data, (char*)new_state_data)) {
str_append(str, "common,");
} else {
str_append(str, "]");
}
}
static void on_special_action(void* old_state_data, tk_sm_event_t* event, void* new_state_data) {
str_t* str = ((str_t*)event->data);
str_append(str, "special,");
}
static void on_finish_action(void* old_state_data, tk_sm_event_t* event, void* new_state_data) {
str_t* str = ((str_t*)event->data);
str_append(str, "]");
}
static void on_enter_action(void* stateData, tk_sm_event_t* event) {
str_t* str = ((str_t*)event->data);
str_append(str, ",[");
}
static void on_exit_action(void* stateData, tk_sm_event_t* event) {
if (event) {
str_t* str = ((str_t*)event->data);
str_append(str, (const char*)stateData);
}
}
static void on_special_exit(void* stateData, tk_sm_event_t* event) {
if (event) {
str_t* str = ((str_t*)event->data);
str_pop(str);
str_append(str, "]");
} else {
log_debug("deinit");
}
}
static tk_sm_state_t idle_state, common_state, special_state;
static tk_sm_state_t base_state = {
.transitions =
(tk_sm_transition_t[]){
{EVENT_IDLE, NULL, NULL, on_base_action, &idle_state},
},
.ntransitions = 1,
.data = "base",
};
static tk_sm_state_t idle_state = {
.base_state = &base_state,
.transitions =
(tk_sm_transition_t[]){
{EVENT_A, "base", condition_check, on_idle_action, &idle_state},
{EVENT_B, "base", condition_check, on_idle_action, &common_state},
},
.ntransitions = 2,
.data = "idle",
};
static tk_sm_state_t common_state = {
.base_state = &base_state,
.transitions =
(tk_sm_transition_t[]){
{EVENT_C, NULL, NULL, on_common_action, &common_state},
{EVENT_D, NULL, NULL, on_common_action, &special_state},
},
.ntransitions = 3,
.data = "common",
.entry_action = on_enter_action,
.exit_action = on_exit_action,
};
static tk_sm_state_t special_state = {
.base_state = &base_state,
.transitions =
(tk_sm_transition_t[]){
{EVENT_E, NULL, NULL, on_special_action, NULL},
{EVENT_MAX_NUM, NULL, NULL, on_special_action, NULL},
},
.ntransitions = 3,
.data = "special",
.entry_action = on_enter_action,
.exit_action = on_special_exit,
};
void state_machine_utest_basic(void) {
tk_state_machine_t sm;
ret_t ret;
int eventid = EVENT_IDLE;
tk_sm_event_t ev;
str_t s;
str_t* str = str_init(&s, 32);
ret = tk_state_machine_init(&sm, &idle_state);
ENSURE(RET_OK == ret);
ev.data = str;
while (eventid <= EVENT_MAX_NUM) {
ev.type = eventid;
ret = tk_state_machine_handle(&sm, &ev);
ENSURE(RET_OK == ret);
eventid++;
}
ENSURE(tk_state_machine_deinit(&sm, &ev) == RET_OK);
log_debug("result: %s", str->str);
ENSURE(tk_str_eq(str->str, "base,idle,idle,[common,common],[special,special]"));
str_reset(str);
return;
}
#define MAX_STEP 4
static void on_step_exit_action(void* old_state_data, tk_sm_event_t* event, void* new_state_data) {
str_t* str = ((str_t*)event->data);
str_append(str, "-");
str_append(str, old_state_data);
}
static void on_step_enter(void* stateData, tk_sm_event_t* event) {
str_t* str = ((str_t*)event->data);
str_append(str, "+");
str_append(str, stateData);
}
static void on_step_exit(void* stateData, tk_sm_event_t* event) {
if (event) {
str_t* str = ((str_t*)event->data);
str_append(str, "-");
str_append(str, (const char*)stateData);
} else {
log_debug("deinit");
}
}
static tk_sm_state_t step1_state, step2_state, step3_state;
static tk_sm_state_t step_init_state = {
.transitions =
(tk_sm_transition_t[]){
{1, NULL, NULL, NULL, &step1_state},
{MAX_STEP, NULL, NULL, NULL, &step_init_state},
},
.ntransitions = 2,
.data = "0,",
};
static tk_sm_state_t step1_state = {
.base_state = &step_init_state,
.transitions =
(tk_sm_transition_t[]){
{2, NULL, NULL, NULL, &step2_state},
},
.ntransitions = 1,
.transitions_back =
(tk_sm_transition_t[]){
{MAX_STEP, NULL, NULL, on_step_exit_action, &step_init_state},
},
.ntransitions_back = 1,
.data = "1,",
.entry_action = on_step_enter,
};
static tk_sm_state_t step2_state = {
.base_state = &step_init_state,
.transitions =
(tk_sm_transition_t[]){
{3, NULL, NULL, NULL, &step3_state},
},
.ntransitions = 1,
.transitions_back =
(tk_sm_transition_t[]){
{MAX_STEP, NULL, NULL, on_step_exit_action, &step1_state},
},
.ntransitions_back = 1,
.data = "2,",
.entry_action = on_step_enter,
};
static tk_sm_state_t step3_state = {
.base_state = &step_init_state,
.transitions_back =
(tk_sm_transition_t[]){
{MAX_STEP, NULL, NULL, NULL, &step2_state},
},
.ntransitions_back = 1,
.data = "3,",
.entry_action = on_step_enter,
.exit_action = on_step_exit,
};
void state_machine_utest_back_transition(void) {
tk_state_machine_t sm;
ret_t ret;
int eventid = 1;
tk_sm_event_t ev;
str_t s;
str_t* str = str_init(&s, 32);
ret = tk_state_machine_init(&sm, &step_init_state);
ENSURE(RET_OK == ret);
ev.data = str;
while (eventid < MAX_STEP) {
ev.type = eventid;
ret = tk_state_machine_handle(&sm, &ev);
ENSURE(RET_OK == ret);
eventid++;
}
ev.type = eventid;
ret = tk_state_machine_handle(&sm, &ev);
ENSURE(RET_OK == ret);
ENSURE(tk_state_machine_deinit(&sm, &ev) == RET_OK);
log_debug("result: %s", str->str);
ENSURE(tk_str_eq(str->str, "+1,+2,+3,-3,-2,-1,"));
str_reset(str);
return;
}
void state_machine_utest(void) {
state_machine_utest_basic();
state_machine_utest_back_transition();
}