mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-05-26 07:08:11 +00:00
178 lines
5.2 KiB
Go
178 lines
5.2 KiB
Go
package supervisor
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/openlibrecommunity/olcrtc/internal/app/session"
|
|
)
|
|
|
|
var errRunnerBoom = errors.New("boom")
|
|
|
|
const (
|
|
testProfileFirst = "first"
|
|
testProfileSecond = "second"
|
|
testProfileOne = "one"
|
|
)
|
|
|
|
func TestRunRequiresProfiles(t *testing.T) {
|
|
err := Run(context.Background(), Config{}, func(context.Context, session.Config) error { return nil })
|
|
if !errors.Is(err, ErrNoProfiles) {
|
|
t.Fatalf("Run() error = %v, want %v", err, ErrNoProfiles)
|
|
}
|
|
}
|
|
|
|
func TestRunAdvancesProfilesAndStopsAtMaxCycles(t *testing.T) {
|
|
profiles := []Profile{
|
|
{Name: testProfileFirst, Config: session.Config{Auth: "wbstream"}},
|
|
{Name: testProfileSecond, Config: session.Config{Auth: "jitsi"}},
|
|
}
|
|
var started []string
|
|
var ended []string
|
|
err := Run(context.Background(), Config{
|
|
Profiles: profiles,
|
|
RetryDelay: -1,
|
|
MaxCycles: 1,
|
|
OnProfileStart: func(profile Profile, cycle int) {
|
|
started = append(started, profile.Name)
|
|
if cycle != 1 {
|
|
t.Fatalf("cycle = %d, want 1", cycle)
|
|
}
|
|
},
|
|
OnProfileEnd: func(profile Profile, _ int, err error) {
|
|
ended = append(ended, profile.Name)
|
|
if !errors.Is(err, errRunnerBoom) {
|
|
t.Fatalf("profile %s err = %v, want %v", profile.Name, err, errRunnerBoom)
|
|
}
|
|
},
|
|
}, func(_ context.Context, cfg session.Config) error {
|
|
if cfg.Auth == "" {
|
|
t.Fatal("runner received empty auth")
|
|
}
|
|
return errRunnerBoom
|
|
})
|
|
if !errors.Is(err, ErrMaxCyclesExceeded) {
|
|
t.Fatalf("Run() error = %v, want %v", err, ErrMaxCyclesExceeded)
|
|
}
|
|
if got, want := started, []string{testProfileFirst, testProfileSecond}; !equalStrings(got, want) {
|
|
t.Fatalf("started = %v, want %v", got, want)
|
|
}
|
|
if got, want := ended, []string{testProfileFirst, testProfileSecond}; !equalStrings(got, want) {
|
|
t.Fatalf("ended = %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
//nolint:cyclop // status history test verifies one complete failover cycle
|
|
func TestRunEmitsStatusHistory(t *testing.T) {
|
|
profiles := []Profile{
|
|
{Name: testProfileFirst, Config: session.Config{Auth: "wbstream"}},
|
|
{Name: testProfileSecond, Config: session.Config{Auth: "jitsi"}},
|
|
}
|
|
var snapshots []Status
|
|
err := Run(context.Background(), Config{
|
|
Profiles: profiles,
|
|
RetryDelay: -1,
|
|
MaxCycles: 1,
|
|
HistoryLimit: 3,
|
|
OnStatus: func(status Status) {
|
|
snapshots = append(snapshots, status)
|
|
},
|
|
}, func(_ context.Context, cfg session.Config) error {
|
|
if cfg.Auth == testProfileFirst {
|
|
t.Fatal("runner received profile name instead of config")
|
|
}
|
|
return errRunnerBoom
|
|
})
|
|
if !errors.Is(err, ErrMaxCyclesExceeded) {
|
|
t.Fatalf("Run() error = %v, want %v", err, ErrMaxCyclesExceeded)
|
|
}
|
|
if len(snapshots) != 4 {
|
|
t.Fatalf("status snapshots = %d, want 4", len(snapshots))
|
|
}
|
|
first := snapshots[0]
|
|
if first.ActiveProfile != testProfileFirst || first.ActiveProfileIndex != 0 || first.Cycle != 1 {
|
|
t.Fatalf("first status = %+v", first)
|
|
}
|
|
if first.Profiles[0].Starts != 1 || first.Profiles[0].LastStarted.IsZero() {
|
|
t.Fatalf("first profile start status = %+v", first.Profiles[0])
|
|
}
|
|
last := snapshots[len(snapshots)-1]
|
|
if last.ActiveProfile != "" || last.ActiveProfileIndex != -1 {
|
|
t.Fatalf("last active status = %+v", last)
|
|
}
|
|
if last.Profiles[0].Failures != 1 || last.Profiles[1].Failures != 1 {
|
|
t.Fatalf("profile failures = %+v", last.Profiles)
|
|
}
|
|
if last.LastError == "" || last.Profiles[1].LastError == "" {
|
|
t.Fatalf("last errors missing: %+v", last)
|
|
}
|
|
if len(last.History) != 3 {
|
|
t.Fatalf("history length = %d, want 3", len(last.History))
|
|
}
|
|
if last.History[0].Type != EventProfileEnd || last.History[0].Profile != testProfileFirst {
|
|
t.Fatalf("oldest bounded history event = %+v", last.History[0])
|
|
}
|
|
if last.History[2].Type != EventProfileEnd || last.History[2].Profile != testProfileSecond ||
|
|
last.History[2].Error == "" {
|
|
t.Fatalf("last history event = %+v", last.History[2])
|
|
}
|
|
}
|
|
|
|
func TestRunStatusSnapshotIsImmutable(t *testing.T) {
|
|
var first Status
|
|
var second Status
|
|
err := Run(context.Background(), Config{
|
|
Profiles: []Profile{{Name: testProfileOne}},
|
|
RetryDelay: -1,
|
|
MaxCycles: 1,
|
|
OnStatus: func(status Status) {
|
|
if first.Profiles == nil {
|
|
first = status
|
|
first.Profiles[0].Starts = 99
|
|
first.History[0].Profile = "mutated"
|
|
return
|
|
}
|
|
second = status
|
|
},
|
|
}, func(context.Context, session.Config) error {
|
|
return errRunnerBoom
|
|
})
|
|
if !errors.Is(err, ErrMaxCyclesExceeded) {
|
|
t.Fatalf("Run() error = %v, want %v", err, ErrMaxCyclesExceeded)
|
|
}
|
|
if first.Profiles[0].Starts != 99 || first.History[0].Profile != "mutated" {
|
|
t.Fatalf("test mutation did not apply to snapshot: %+v", first)
|
|
}
|
|
if second.Profiles[0].Starts != 1 || second.History[0].Profile != testProfileOne {
|
|
t.Fatalf("snapshot mutation leaked into later status: %+v", second)
|
|
}
|
|
}
|
|
|
|
func TestRunReturnsNilOnContextCancel(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
err := Run(ctx, Config{
|
|
Profiles: []Profile{{Name: testProfileOne}},
|
|
RetryDelay: time.Hour,
|
|
}, func(context.Context, session.Config) error {
|
|
cancel()
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Run() error = %v, want nil", err)
|
|
}
|
|
}
|
|
|
|
func equalStrings(a, b []string) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
for i := range a {
|
|
if a[i] != b[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|