Files

145 lines
3.7 KiB
Go

package emotion
import "testing"
func TestDefaultTransitions_StandardEdges(t *testing.T) {
t.Parallel()
d := DefaultTransitions()
if _, ok := d[Calm]; !ok {
t.Errorf("DefaultTransitions missing %q", Calm)
}
if _, ok := d[Angry]; !ok {
t.Errorf("DefaultTransitions missing %q", Angry)
}
}
func TestNewMachine_DefaultTransitionsWhenEmpty(t *testing.T) {
t.Parallel()
m, err := NewMachine(Params{InitialState: Excited})
if err != nil {
t.Fatalf("NewMachine() error: %v", err)
}
if got := m.Current(); got != Excited {
t.Fatalf("Current() = %q, want %q", got, Excited)
}
if !m.CanTransition(Happy) {
t.Errorf("excited should be able to reach happy by default")
}
if m.CanTransition(Sad) {
t.Errorf("excited must not reach sad by default")
}
}
func TestNewMachine_RejectsNegativeDecay(t *testing.T) {
t.Parallel()
if _, err := NewMachine(Params{InitialState: Calm, DecayRate: -1}); err == nil {
t.Fatal("NewMachine() should error on negative decay rate")
}
}
func TestMachine_TransitionFollowsTable(t *testing.T) {
t.Parallel()
tr := map[EmotionState][]EmotionState{
Calm: {Happy, Sad, Excited},
Happy: {Excited, Calm},
Sad: {Calm},
Angry: {Calm},
}
tests := []struct {
name string
initial EmotionState
to EmotionState
wantErr bool
}{
{name: "ok_calm_to_happy", initial: Calm, to: Happy},
{name: "ok_calm_to_excited", initial: Calm, to: Excited},
{name: "ok_happy_to_excited", initial: Happy, to: Excited},
{name: "reject_calm_to_angry", initial: Calm, to: Angry, wantErr: true},
{name: "reject_happy_to_sad", initial: Happy, to: Sad, wantErr: true},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
m, err := NewMachine(Params{InitialState: tt.initial, Transitions: tr})
if err != nil {
t.Fatalf("NewMachine() error: %v", err)
}
err = m.Transition(tt.to)
if tt.wantErr && err == nil {
t.Fatalf("Transition(%q) want error, got nil", tt.to)
}
if !tt.wantErr && err != nil {
t.Fatalf("Transition(%q) want nil, got %v", tt.to, err)
}
if !tt.wantErr && m.Current() != tt.to {
t.Fatalf("Current() = %q, want %q", m.Current(), tt.to)
}
})
}
}
func TestMachine_SetForce(t *testing.T) {
t.Parallel()
m, err := NewMachine(Params{InitialState: Calm})
if err != nil {
t.Fatalf("NewMachine() error: %v", err)
}
m.Set(Angry)
if got := m.Current(); got != Angry {
t.Fatalf("Current() = %q, want %q", got, Angry)
}
}
func TestMachine_AddTransitionExtends(t *testing.T) {
t.Parallel()
tr := map[EmotionState][]EmotionState{Calm: {Happy}}
m, err := NewMachine(Params{InitialState: Calm, Transitions: tr})
if err != nil {
t.Fatalf("NewMachine() error: %v", err)
}
if m.CanTransition(Angry) {
t.Fatalf("calm must not reach angry before AddTransition")
}
m.AddTransition(Calm, Angry)
if !m.CanTransition(Angry) {
t.Errorf("calm should reach angry after AddTransition")
}
}
func TestMachine_DecayMovesTowardCalm(t *testing.T) {
t.Parallel()
m, err := NewMachine(Params{InitialState: Excited, DecayRate: 1})
if err != nil {
t.Fatalf("NewMachine() error: %v", err)
}
if got := m.Decay(); got != Happy {
t.Fatalf("Decay() from excited = %q, want %q", got, Happy)
}
if got := m.Decay(); got != Calm {
t.Fatalf("Decay() from happy = %q, want %q", got, Calm)
}
if got := m.Decay(); got != Calm {
t.Fatalf("Decay() from calm = %q, want %q", got, Calm)
}
}
func TestMachine_DecayDisabledAtZeroRate(t *testing.T) {
t.Parallel()
m, err := NewMachine(Params{InitialState: Angry, DecayRate: 0})
if err != nil {
t.Fatalf("NewMachine() error: %v", err)
}
if got := m.Decay(); got != Angry {
t.Fatalf("Decay() at zero rate = %q, want %q", got, Angry)
}
}