// eqpalg/test/test_fb_state_machine.cc #include #include #include #include #include using namespace std::chrono; // 测试辅助:构建最小环境 struct FbTestEnv { std::map 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(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(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); }