Files

168 lines
8.6 KiB
Go

package service
import (
"errors"
"testing"
"time"
"browser.local/platform/domain"
)
func TestSCUMFactIngestMaintainsPlatformTablesAndWelcomeQueue(t *testing.T) {
svc, session, runSession, instance := newSourceRCONFixture(t)
squadID := int64(42)
bank := int64(1200)
gold := int64(3)
exists := true
locked := true
functional := true
observedAt := fixedTime.Add(-1 * time.Minute)
result, err := svc.IngestSCUMFacts(domain.SCUMFactIngest{
RunEndpointID: instance.RunEndpointID,
SessionToken: runSession,
ServerInstanceID: instance.ID,
Users: []domain.SCUMUserFact{{
SteamID: "76561198000000001", DisplayName: "Mira", SquadID: &squadID, LoginIP: "203.0.113.7", Online: true, Login: true,
ObservedAt: observedAt, LoginObservedAt: observedAt, Position: &domain.SCUMPosition{X: 10, Y: 20, Z: 3}, BankBalance: &bank, GoldBars: &gold, RiddenGameVehicleID: "game-veh-1",
}},
Vehicles: []domain.SCUMVehicleFact{{
GameVehicleID: "game-veh-1", VehicleClass: "BPC_Laika_C", DisplayName: "Laika", Exists: &exists, Locked: &locked, Functional: &functional, LockedBySteamID: "76561198000000001", LockedAt: observedAt, ObservedAt: observedAt, Position: &domain.SCUMPosition{X: 400, Y: 200, Z: 0},
}},
})
if err != nil {
t.Fatalf("ingest SCUM facts: %v", err)
}
if !result.Accepted || result.AcceptedUserCount != 1 || result.AcceptedVehicleCount != 1 || result.WelcomeQueuedCount != 1 {
t.Fatalf("unexpected ingest result: %+v", result)
}
users, err := svc.ListSCUMUsersForSession(session, domain.SCUMUserFilter{ServerInstanceID: instance.ID})
if err != nil || len(users) != 1 {
t.Fatalf("list SCUM users: users=%+v err=%v", users, err)
}
user := users[0]
if user.SteamID != "76561198000000001" || user.SquadID != squadID || user.LastLoginIP != "203.0.113.7" || !user.Online || user.BankBalance == nil || *user.BankBalance != bank || user.GoldBars == nil || *user.GoldBars != gold || user.RiddenVehicleID == "" || user.GameVehicleID != "game-veh-1" {
t.Fatalf("unexpected SCUM user: %+v", user)
}
if user.LastLoginAge != time.Minute {
t.Fatalf("expected one-minute login age, got %s", user.LastLoginAge)
}
jobs, err := svc.store.Jobs().List(domain.JobFilter{ServerInstanceID: instance.ID})
if err != nil || len(jobs) != 1 {
t.Fatalf("expected one queued welcome job, jobs=%+v err=%v", jobs, err)
}
if jobs[0].Capability != domain.JobCapabilityRemoteRunRCONCommand || !jobs[0].QueueEligibleAt.Equal(fixedTime.Add(domain.SCUMWelcomeMessageDelay)) {
t.Fatalf("unexpected welcome job: %+v", jobs[0])
}
userTracks, err := svc.ListSCUMUserTrajectoriesForSession(session, domain.SCUMUserTrajectoryFilter{ServerInstanceID: instance.ID})
if err != nil || len(userTracks) != 1 || userTracks[0].RiddenVehicleID != user.RiddenVehicleID {
t.Fatalf("unexpected user trajectory rows: rows=%+v err=%v", userTracks, err)
}
vehicles, err := svc.ListSCUMVehiclesForSession(session, domain.SCUMVehicleFilter{ServerInstanceID: instance.ID})
if err != nil || len(vehicles) != 1 || vehicles[0].GameVehicleID != "game-veh-1" || !vehicles[0].Exists || !vehicles[0].Locked || vehicles[0].Functional == nil || !*vehicles[0].Functional {
t.Fatalf("unexpected SCUM vehicles: vehicles=%+v err=%v", vehicles, err)
}
vehicleTracks, err := svc.ListSCUMVehicleTrajectoriesForSession(session, domain.SCUMVehicleTrajectoryFilter{ServerInstanceID: instance.ID})
if err != nil || len(vehicleTracks) != 1 || vehicleTracks[0].SCUMVehicleID != vehicles[0].ID {
t.Fatalf("unexpected vehicle trajectory rows: rows=%+v err=%v", vehicleTracks, err)
}
locks, err := svc.ListSCUMVehicleLocksForSession(session, domain.SCUMVehicleLockFilter{ServerInstanceID: instance.ID})
if err != nil || len(locks) != 1 || locks[0].SCUMUserID != user.ID || locks[0].SCUMVehicleID != vehicles[0].ID {
t.Fatalf("unexpected vehicle lock history: locks=%+v err=%v", locks, err)
}
_, err = svc.IngestSCUMFacts(domain.SCUMFactIngest{
RunEndpointID: instance.RunEndpointID, SessionToken: runSession, ServerInstanceID: instance.ID,
Users: []domain.SCUMUserFact{{SteamID: "76561198000000001", Online: true, ObservedAt: observedAt, Position: &domain.SCUMPosition{X: 10, Y: 20, Z: 3}}},
Vehicles: []domain.SCUMVehicleFact{{GameVehicleID: "game-veh-1", ObservedAt: observedAt, Position: &domain.SCUMPosition{X: 400, Y: 200, Z: 0}}},
})
if err != nil {
t.Fatalf("re-ingest unchanged SCUM facts: %v", err)
}
userTracks, _ = svc.ListSCUMUserTrajectoriesForSession(session, domain.SCUMUserTrajectoryFilter{ServerInstanceID: instance.ID})
vehicleTracks, _ = svc.ListSCUMVehicleTrajectoriesForSession(session, domain.SCUMVehicleTrajectoryFilter{ServerInstanceID: instance.ID})
if len(userTracks) != 1 || len(vehicleTracks) != 1 {
t.Fatalf("unchanged positions must not create trajectory rows, users=%+v vehicles=%+v", userTracks, vehicleTracks)
}
_, err = svc.IngestSCUMFacts(domain.SCUMFactIngest{
RunEndpointID: instance.RunEndpointID, SessionToken: runSession, ServerInstanceID: instance.ID,
Users: []domain.SCUMUserFact{{SteamID: "76561198000000001", Online: false, ObservedAt: fixedTime, Position: &domain.SCUMPosition{X: 11, Y: 21, Z: 4}}},
})
if err != nil {
t.Fatalf("ingest offline SCUM user fact: %v", err)
}
userTracks, _ = svc.ListSCUMUserTrajectoriesForSession(session, domain.SCUMUserTrajectoryFilter{ServerInstanceID: instance.ID})
if len(userTracks) != 1 {
t.Fatalf("offline users must not create trajectory rows, rows=%+v", userTracks)
}
}
func TestSCUMFactIngestQueuesFreshWelcomeAfterActivityGap(t *testing.T) {
svc, session, runSession, instance := newSourceRCONFixture(t)
firstLogin := fixedTime.Add(-20 * time.Minute)
secondLogin := fixedTime.Add(-4 * time.Minute)
for _, loginAt := range []time.Time{firstLogin, secondLogin} {
result, err := svc.IngestSCUMFacts(domain.SCUMFactIngest{RunEndpointID: instance.RunEndpointID, SessionToken: runSession, ServerInstanceID: instance.ID, Users: []domain.SCUMUserFact{{SteamID: "76561198000000002", DisplayName: "Noah", Online: true, Login: true, ObservedAt: loginAt, LoginObservedAt: loginAt}}})
if err != nil {
t.Fatalf("ingest login at %s: %v", loginAt, err)
}
if result.WelcomeQueuedCount != 1 {
t.Fatalf("expected fresh welcome for login at %s, got %+v", loginAt, result)
}
}
users, err := svc.ListSCUMUsersForSession(session, domain.SCUMUserFilter{ServerInstanceID: instance.ID, SteamID: "76561198000000002"})
if err != nil || len(users) != 1 {
t.Fatalf("list gap user: users=%+v err=%v", users, err)
}
if users[0].LastLoginAge != 4*time.Minute {
t.Fatalf("expected last login age to show the second login, got %s", users[0].LastLoginAge)
}
jobs, err := svc.store.Jobs().List(domain.JobFilter{ServerInstanceID: instance.ID})
if err != nil || len(jobs) != 2 {
t.Fatalf("expected two welcome jobs after activity gap, jobs=%+v err=%v", jobs, err)
}
}
func TestSCUMStaleOnlineUserConvergesToOffline(t *testing.T) {
svc, session, runSession, instance := newSourceRCONFixture(t)
staleAt := fixedTime.Add(-16 * time.Minute)
if _, err := svc.IngestSCUMFacts(domain.SCUMFactIngest{
RunEndpointID: instance.RunEndpointID, SessionToken: runSession, ServerInstanceID: instance.ID,
Users: []domain.SCUMUserFact{{SteamID: "76561198000000003", DisplayName: "Stale", Online: true, Login: true, ObservedAt: staleAt, LoginObservedAt: staleAt}},
}); err != nil {
t.Fatalf("ingest stale SCUM user fact: %v", err)
}
users, err := svc.ListSCUMUsersForSession(session, domain.SCUMUserFilter{ServerInstanceID: instance.ID})
if err != nil || len(users) != 1 {
t.Fatalf("list stale SCUM users: users=%+v err=%v", users, err)
}
if users[0].Online {
t.Fatalf("expected a user without activity for %s to converge offline: %+v", domain.SCUMUserOfflineAfter, users[0])
}
}
func TestSCUMFactsRejectedForNonSCUMServerInstance(t *testing.T) {
svc, _, runSession, instance := newSourceRCONFixture(t)
if err := svc.store.GamePlugins().Create(domain.GamePlugin{ID: "server.other", Name: "Other", Version: "1.0.0", ServerType: "other"}); err != nil {
t.Fatalf("create non-SCUM plugin: %v", err)
}
if err := svc.store.ServerInstances().Create(domain.ServerInstance{ID: "server-other", PluginID: "server.other", RunEndpointID: instance.RunEndpointID, Name: "Other Server", State: domain.ServerInstanceStateRunning, ConfigVersion: 1}); err != nil {
t.Fatalf("create non-SCUM server: %v", err)
}
_, err := svc.IngestSCUMFacts(domain.SCUMFactIngest{
RunEndpointID: instance.RunEndpointID, SessionToken: runSession, ServerInstanceID: "server-other",
Users: []domain.SCUMUserFact{{SteamID: "76561198000000004", Online: true}},
})
if !errors.Is(err, ErrForbidden) {
t.Fatalf("expected SCUM facts for a non-SCUM server to be rejected, got %v", err)
}
}