Files
novel_server/utility/state_machine/ads_state_machine_test.go

191 lines
6.8 KiB
Go
Raw Permalink 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.

// Package state_machine 提供广告状态机的单元测试
package state_machine
import (
"server/internal/consts"
"testing"
)
// TestNewAdStateMachine 测试创建新的广告状态机
func TestNewAdStateMachine(t *testing.T) {
sm := NewAdStateMachine()
if sm == nil {
t.Fatal("期望创建非空的状态机但得到了nil")
}
if sm.transitions == nil {
t.Error("期望transitions非空但得到了nil")
}
if sm.terminalStates == nil {
t.Error("期望terminalStates非空但得到了nil")
}
}
// TestAdStateMachine_CanTransition 测试状态转换验证功能
func TestAdStateMachine_CanTransition(t *testing.T) {
sm := NewAdStateMachine()
// 测试有效转换
if !sm.CanTransition(consts.StateFetchSuccess, consts.StateDisplaySuccess) {
t.Error("期望从拉取成功到显示成功的转换是有效的")
}
// 测试无效转换
if sm.CanTransition(consts.StateFetchSuccess, consts.StateNotWatched) {
t.Error("期望从拉取成功到未观看完成的转换是无效的")
}
// 测试从终止状态转换
if sm.CanTransition(consts.StateFetchFailed, consts.StateDisplaySuccess) {
t.Error("期望从拉取失败终止状态无法转换到其他状态")
}
}
// TestAdStateMachine_IsTerminalState 测试终止状态检查功能
func TestAdStateMachine_IsTerminalState(t *testing.T) {
sm := NewAdStateMachine()
// 测试终止状态
if !sm.IsTerminalState(consts.StateDisplayFailed) {
t.Error("期望显示失败状态是终止状态")
}
// 测试非终止状态
if sm.IsTerminalState(consts.StateFetchSuccess) {
t.Error("期望拉取成功状态不是终止状态")
}
}
// TestAdStateMachine_GetAvailableTransitions 测试获取可用转换状态功能
func TestAdStateMachine_GetAvailableTransitions(t *testing.T) {
sm := NewAdStateMachine()
// 测试有可用转换的状态
transitions := sm.GetAvailableTransitions(consts.StateFetchSuccess)
if len(transitions) == 0 {
t.Error("期望拉取成功状态有可用的转换状态")
}
// 测试终止状态
transitions = sm.GetAvailableTransitions(consts.StateDisplayFailed)
if len(transitions) != 0 {
t.Error("期望显示失败终止状态没有可用的转换状态")
}
// 测试不存在的状态
transitions = sm.GetAvailableTransitions(999) // 不存在的状态
if len(transitions) != 0 {
t.Error("期望不存在的状态没有可用的转换状态")
}
}
// TestAdStateMachine_StateTransitionFlow 测试状态流转路径
func TestAdStateMachine_StateTransitionFlow(t *testing.T) {
sm := NewAdStateMachine()
// 测试路径1拉取失败是终止状态
if !sm.IsTerminalState(consts.StateFetchFailed) {
t.Error("期望拉取失败是终止状态")
}
// 测试路径2拉取成功 -> 显示失败 -> 终止
if !sm.CanTransition(consts.StateFetchSuccess, consts.StateDisplayFailed) {
t.Error("期望从拉取成功到显示失败的转换是有效的")
}
if !sm.IsTerminalState(consts.StateDisplayFailed) {
t.Error("期望显示失败是终止状态")
}
// 测试路径3拉取成功 -> 显示成功 -> 未观看完成 -> 终止
if !sm.CanTransition(consts.StateFetchSuccess, consts.StateDisplaySuccess) {
t.Error("期望从拉取成功到显示成功的转换是有效的")
}
if !sm.CanTransition(consts.StateDisplaySuccess, consts.StateNotWatched) {
t.Error("期望从显示成功到未观看完成的转换是有效的")
}
if !sm.IsTerminalState(consts.StateNotWatched) {
t.Error("期望未观看完成是终止状态")
}
// 测试路径4拉取成功 -> 显示成功 -> 观看完成 -> 未点击 -> 终止
if !sm.CanTransition(consts.StateDisplaySuccess, consts.StateWatched) {
t.Error("期望从显示成功到观看完成的转换是有效的")
}
if !sm.CanTransition(consts.StateWatched, consts.StateNotClicked) {
t.Error("期望从观看完成到未点击的转换是有效的")
}
if !sm.IsTerminalState(consts.StateNotClicked) {
t.Error("期望未点击是终止状态")
}
// 测试路径5拉取成功 -> 显示成功 -> 观看完成 -> 已点击 -> 未下载 -> 已下载
if !sm.CanTransition(consts.StateWatched, consts.StateClicked) {
t.Error("期望从观看完成到已点击的转换是有效的")
}
if !sm.CanTransition(consts.StateClicked, consts.StateNotDownloaded) {
t.Error("期望从已点击到未下载的转换是有效的")
}
if sm.IsTerminalState(consts.StateNotDownloaded) {
t.Error("期望未下载不是终止状态")
}
if !sm.CanTransition(consts.StateNotDownloaded, consts.StateDownloaded) {
t.Error("期望从未下载到已下载的转换是有效的")
}
// 测试路径6拉取成功 -> 显示成功 -> 观看完成 -> 已点击 -> 已下载 -> 终止
if !sm.CanTransition(consts.StateClicked, consts.StateDownloaded) {
t.Error("期望从已点击到已下载的转换是有效的")
}
if !sm.IsTerminalState(consts.StateDownloaded) {
t.Error("期望已下载是终止状态")
}
}
// TestAdStateMachine_InvalidTransitions 测试无效的状态转换
func TestAdStateMachine_InvalidTransitions(t *testing.T) {
sm := NewAdStateMachine()
// 测试不允许的跳跃转换
if sm.CanTransition(consts.StateFetchSuccess, consts.StateWatched) {
t.Error("不应该允许从拉取成功直接转换到观看完成")
}
if sm.CanTransition(consts.StateDisplaySuccess, consts.StateClicked) {
t.Error("不应该允许从显示成功直接转换到已点击")
}
if sm.CanTransition(consts.StateWatched, consts.StateDownloaded) {
t.Error("不应该允许从观看完成直接转换到已下载")
}
// 测试反向转换
if sm.CanTransition(consts.StateDisplaySuccess, consts.StateFetchSuccess) {
t.Error("不应该允许从显示成功转换回拉取成功")
}
if sm.CanTransition(consts.StateWatched, consts.StateDisplaySuccess) {
t.Error("不应该允许从观看完成转换回显示成功")
}
if sm.CanTransition(consts.StateClicked, consts.StateWatched) {
t.Error("不应该允许从已点击转换回观看完成")
}
if sm.CanTransition(consts.StateDownloaded, consts.StateClicked) {
t.Error("不应该允许从已下载转换回已点击")
}
}
// TestAdStateMachine_TransitionFromNotDownloaded 测试从未下载状态的转换
func TestAdStateMachine_TransitionFromNotDownloaded(t *testing.T) {
sm := NewAdStateMachine()
// 测试从未下载到已下载的转换
if !sm.CanTransition(consts.StateNotDownloaded, consts.StateDownloaded) {
t.Error("期望从未下载到已下载的转换是有效的")
}
// 确认未下载状态的可用转换只有已下载
transitions := sm.GetAvailableTransitions(consts.StateNotDownloaded)
if len(transitions) != 1 {
t.Errorf("期望未下载状态有1个可用转换但得到了%d个", len(transitions))
}
if len(transitions) > 0 && transitions[0] != consts.StateDownloaded {
t.Errorf("期望未下载状态的可用转换是已下载,但得到了%d", transitions[0])
}
}