eis/eqpalg/test/test_fb_state_machine.cc
2026-05-15 13:27:27 +08:00

198 lines
5.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// eqpalg/test/test_fb_state_machine.cc
#include "test_harness.h"
#include <eqpalg/utility/fb_state_machine.h>
#include <chrono>
#include <map>
#include <string>
using namespace std::chrono;
// 测试辅助:构建最小环境
struct FbTestEnv {
std::map<std::string, double> vars;
FbStateMachine fsm;
TimePoint now;
FbTestEnv(size_t tag_count = 2) {
// 模拟已初始化的变量状态
for (size_t i = 0; i < tag_count; i++) {
std::string idx = std::to_string(i + 1);
vars["tag" + idx] = 0.0;
vars["p" + idx] = 0.0;
vars["now"] = 0;
}
now = std::chrono::system_clock::now();
vars["now"] = duration_cast<milliseconds>(now.time_since_epoch()).count();
}
void setTag(int n, double val) {
std::string idx = std::to_string(n);
vars["p" + idx] = vars["tag" + idx]; // p = old tag
vars["tag" + idx] = val;
}
void advanceTime(int ms) {
now += milliseconds(ms);
vars["now"] = duration_cast<milliseconds>(now.time_since_epoch()).count();
}
FbUpdateResult step(bool trigger) {
return fsm.update(trigger, now, vars, 2);
}
};
// ==================== 初始状态 ====================
TEST(initial_state_is_idle) {
FbTestEnv env;
CHECK(env.fsm.currentState() == FbState::Idle);
CHECK_EQ(env.fsm.isActive(), false);
}
// ==================== Idle → Started ====================
TEST(idle_to_started_when_triggered) {
FbTestEnv env;
auto result = env.step(true);
CHECK(result.state == FbState::Started);
CHECK_EQ(env.fsm.isActive(), true);
CHECK_EQ(result.funVarsNeedReset, false);
}
TEST(idle_stays_idle_when_not_triggered) {
FbTestEnv env;
auto result = env.step(false);
CHECK(result.state == FbState::Idle);
CHECK_EQ(result.funVarsNeedReset, true); // 空闲时重置 fun_vars
}
// ==================== Started → InProgress → Done ====================
TEST(started_proceeds_to_done_via_feedback) {
FbTestEnv env;
// 首次触发 → Started
auto r1 = env.step(true);
CHECK(r1.state == FbState::Started);
// Started 自动推进到 InProgress第二次 update
auto r2 = env.step(true);
CHECK(r2.state == FbState::InProgress || r2.state == FbState::Started);
// 如果第二次还在 Started第三次一定到 InProgress
if (r2.state == FbState::Started) {
r2 = env.step(true);
}
CHECK(r2.state == FbState::InProgress);
// 反馈条件满足 → Done
bool done = env.fsm.checkFeedback(true, env.now, env.vars);
CHECK_EQ(done, true);
CHECK(env.fsm.currentState() == FbState::Idle); // 自动回到 Idle
}
// ==================== NotHold ====================
TEST(keep_mode_not_hold_when_trigger_lost) {
FbTestEnv env;
env.fsm.configure(true, milliseconds(600000)); // keep_mode=true
// 触发 → Started
env.step(true);
// → InProgress
env.step(true);
// 触发丢失 → NotHold
auto r = env.step(false);
CHECK(r.state == FbState::NotHold);
CHECK_EQ(r.funVarsNeedReset, true);
}
// ==================== Timeout ====================
TEST(timeout_when_exceeds_limit) {
FbTestEnv env;
env.fsm.configure(false, milliseconds(100)); // 100ms timeout
// 触发 → Started → InProgress
env.step(true);
env.step(true);
// 超时
env.advanceTime(200);
auto r = env.step(true);
CHECK(r.state == FbState::Timeout);
CHECK_EQ(r.funVarsNeedReset, true);
}
// ==================== 变量快照 ====================
TEST(snapshot_on_action_start) {
FbTestEnv env;
env.setTag(1, 3.0);
env.setTag(2, 7.0);
env.step(true); // → Started快照发生
CHECK_FLOAT_EQ(env.vars["s1"], 3.0, 0.001);
CHECK_FLOAT_EQ(env.vars["s2"], 7.0, 0.001);
CHECK_FLOAT_EQ(env.vars["time"], 0.0, 0.001);
CHECK_FLOAT_EQ(env.vars["mv2_tag1"], 0.0, 0.001);
// stime 应该被设置
CHECK(env.vars["stime"] > 0);
}
// ==================== 变量累积 ====================
TEST(action_vars_accumulate_in_progress) {
FbTestEnv env;
env.setTag(1, 1.0); // tag1=1
env.setTag(2, 0.0);
env.step(true); // Started
env.step(true); // InProgress (累积发生)
CHECK_EQ(env.vars["mv2_tag1"] >= 1.0, true); // tag1==1 被计数
CHECK_FLOAT_EQ(env.vars["mx_tag1"], 1.0, 0.001);
CHECK_FLOAT_EQ(env.vars["mi_tag2"], 0.0, 0.001);
}
// ==================== forceReset ====================
TEST(force_reset_returns_to_idle) {
FbTestEnv env;
env.step(true); // Started
CHECK_EQ(env.fsm.isActive(), true);
env.fsm.forceReset();
CHECK(env.fsm.currentState() == FbState::Idle);
CHECK_EQ(env.fsm.isActive(), false);
}
// ==================== 非 keep 模式下触发丢失 ====================
TEST(no_keep_mode_trigger_loss_stays_in_progress) {
FbTestEnv env;
env.fsm.configure(false, milliseconds(600000)); // keep_mode=false
env.step(true); // Started
env.step(true); // InProgress
auto r = env.step(false); // 触发丢失但 keep_mode=false
CHECK(r.state == FbState::InProgress); // 不退出
}
// ==================== 终端状态自动回归 Idle ====================
TEST(terminal_state_returns_to_idle_next_cycle) {
FbTestEnv env;
env.fsm.configure(false, milliseconds(10));
env.step(true);
env.step(true);
env.advanceTime(20);
auto r = env.step(true);
CHECK(r.state == FbState::Timeout);
// 下一周期自动回到 Idle
auto r2 = env.step(false);
CHECK(r2.state == FbState::Idle);
}