Files
browser/platform/service/control_test.go
T
2026-07-15 19:43:06 +08:00

233 lines
7.8 KiB
Go

package service
import (
"errors"
"strings"
"testing"
"browser.local/platform/domain"
"browser.local/platform/repo"
)
func TestCoreServiceRegistersNewRunControlSession(t *testing.T) {
svc := newTestCoreService()
result, err := svc.RegisterRunHello(validRunControlHello())
if err != nil {
t.Fatalf("register hello: %v", err)
}
if !result.Accepted || result.SessionToken == "" || result.HeartbeatIntervalSeconds <= 0 {
t.Fatalf("expected accepted hello response, got %+v", result)
}
endpoint, err := svc.GetRunEndpoint("run-local")
if err != nil {
t.Fatalf("get registered endpoint: %v", err)
}
if endpoint.Status != domain.RunEndpointStatusOnline || !endpoint.LastHeartbeatAt.Equal(fixedTime) {
t.Fatalf("expected online endpoint with heartbeat time, got %+v", endpoint)
}
if len(endpoint.Capabilities) != 3 || endpoint.Capacity.MaxJobs != 4 {
t.Fatalf("expected capabilities and capacity, got %+v", endpoint)
}
}
func TestCoreServiceReRegistersExistingRunEndpoint(t *testing.T) {
svc := newTestCoreService()
first, err := svc.RegisterRunHello(validRunControlHello())
if err != nil {
t.Fatalf("register first hello: %v", err)
}
hello := validRunControlHello()
hello.DisplayName = "Local Run Updated"
hello.Version = "0.2.0"
hello.CapabilityReport.Capabilities = []string{"control.hello", "control.heartbeat", "jobs.claim"}
hello.CapabilityReport.Fingerprint = "cap-v2"
second, err := svc.RegisterRunHello(hello)
if err != nil {
t.Fatalf("register second hello: %v", err)
}
if second.SessionToken == first.SessionToken {
t.Fatalf("expected re-registration to issue a new token, got %q", second.SessionToken)
}
endpoint, err := svc.GetRunEndpoint("run-local")
if err != nil {
t.Fatalf("get re-registered endpoint: %v", err)
}
if endpoint.DisplayName != "Local Run Updated" || endpoint.Version != "0.2.0" || len(endpoint.Capabilities) != 3 {
t.Fatalf("expected endpoint metadata update, got %+v", endpoint)
}
}
func TestCoreServiceAcceptsRunHeartbeat(t *testing.T) {
svc := newTestCoreService()
hello, err := svc.RegisterRunHello(validRunControlHello())
if err != nil {
t.Fatalf("register hello: %v", err)
}
result, err := svc.AcceptRunHeartbeat(domain.RunControlHeartbeat{
RunEndpointID: "run-local",
SessionToken: hello.SessionToken,
Version: "0.1.1",
Status: domain.RunEndpointStatusDegraded,
CapabilityFingerprint: "cap-v1",
Capacity: domain.RunCapacity{MaxJobs: 4, RunningJobs: 2, QueuedJobs: 1},
})
if err != nil {
t.Fatalf("accept heartbeat: %v", err)
}
if !result.Accepted || result.RefreshCapabilities {
t.Fatalf("expected accepted heartbeat without refresh, got %+v", result)
}
endpoint, err := svc.GetRunEndpoint("run-local")
if err != nil {
t.Fatalf("get heartbeat endpoint: %v", err)
}
if endpoint.Status != domain.RunEndpointStatusDegraded || endpoint.Version != "0.1.1" || endpoint.Capacity.RunningJobs != 2 {
t.Fatalf("expected heartbeat metadata update, got %+v", endpoint)
}
}
func TestCoreServiceRejectsInvalidRunHeartbeatToken(t *testing.T) {
svc := newTestCoreService()
if _, err := svc.RegisterRunHello(validRunControlHello()); err != nil {
t.Fatalf("register hello: %v", err)
}
_, err := svc.AcceptRunHeartbeat(domain.RunControlHeartbeat{
RunEndpointID: "run-local",
SessionToken: "stale-token",
Version: "0.1.1",
Status: domain.RunEndpointStatusOnline,
CapabilityFingerprint: "cap-v1",
Capacity: domain.RunCapacity{MaxJobs: 4, RunningJobs: 3},
})
if err == nil || !strings.Contains(err.Error(), "sessionToken is invalid") {
t.Fatalf("expected invalid token rejection, got %v", err)
}
endpoint, err := svc.GetRunEndpoint("run-local")
if err != nil {
t.Fatalf("get endpoint after rejected heartbeat: %v", err)
}
if endpoint.Capacity.RunningJobs != 0 || endpoint.Version != "0.1.0" {
t.Fatalf("heartbeat with invalid token must not update endpoint, got %+v", endpoint)
}
}
func TestCoreServiceRejectsInvalidRunControlHello(t *testing.T) {
svc := newTestCoreService()
invalid := validRunControlHello()
invalid.RegistrationToken = ""
invalid.Capacity.RunningJobs = 8
_, err := svc.RegisterRunHello(invalid)
if err == nil || !strings.Contains(err.Error(), "registrationToken") || !strings.Contains(err.Error(), "runningJobs") {
t.Fatalf("expected validation errors, got %v", err)
}
if _, err := svc.GetRunEndpoint("run-local"); !errors.Is(err, repo.ErrNotFound) {
t.Fatalf("invalid hello must not create endpoint, got %v", err)
}
}
func TestCoreServiceRunHelloRejectsStalePackageKeyAfterReset(t *testing.T) {
svc, session, instance := newDistributionTestFixture(t)
distribution, err := svc.GenerateRunDistributionForSession(session, domain.RunDistributionGenerateRequest{
ServerInstanceID: instance.ID,
TargetOS: "linux",
TargetArch: "amd64",
IdempotencyKey: "idem-control-auth",
})
if err != nil {
t.Fatalf("generate run distribution: %v", err)
}
pkg := readGeneratedPackageConfig(t, svc, session, distribution.ArtifactID)
hello := validRunControlHello()
hello.RunEndpointID = instance.RunEndpointID
hello.RegistrationToken = pkg.AuthKey
hello.ServerInstanceID = instance.ID
hello.PluginID = instance.PluginID
hello.ComponentKind = domain.DistributionComponentRun
hello.KeyGeneration = pkg.KeyGeneration
result, err := svc.RegisterRunHello(hello)
if err != nil {
t.Fatalf("register current package hello: %v", err)
}
if !result.Accepted || result.SessionToken == "" {
t.Fatalf("expected current package hello to be accepted, got %+v", result)
}
if _, err := svc.ResetComponentKeyForSession(session, domain.ComponentKeyResetRequest{
ServerInstanceID: instance.ID,
ComponentKind: domain.DistributionComponentRun,
}); err != nil {
t.Fatalf("reset run key: %v", err)
}
result, err = svc.RegisterRunHello(hello)
if err != nil {
t.Fatalf("register stale package hello: %v", err)
}
if result.Accepted || result.SessionToken != "" {
t.Fatalf("expected stale package hello to be rejected, got %+v", result)
}
}
func TestCoreServiceRequestsCapabilityRefreshOnFingerprintDrift(t *testing.T) {
svc := newTestCoreService()
hello, err := svc.RegisterRunHello(validRunControlHello())
if err != nil {
t.Fatalf("register hello: %v", err)
}
result, err := svc.AcceptRunHeartbeat(domain.RunControlHeartbeat{
RunEndpointID: "run-local",
SessionToken: hello.SessionToken,
Version: "0.1.0",
Status: domain.RunEndpointStatusOnline,
CapabilityFingerprint: "cap-v2",
Capacity: domain.RunCapacity{MaxJobs: 4},
})
if err != nil {
t.Fatalf("accept drift heartbeat: %v", err)
}
if !result.RefreshCapabilities {
t.Fatalf("expected capability refresh request, got %+v", result)
}
result, err = svc.AcceptRunHeartbeat(domain.RunControlHeartbeat{
RunEndpointID: "run-local",
SessionToken: hello.SessionToken,
Version: "0.1.0",
Status: domain.RunEndpointStatusOnline,
CapabilityFingerprint: "cap-v2",
Capacity: domain.RunCapacity{MaxJobs: 4},
})
if err != nil {
t.Fatalf("accept stable heartbeat: %v", err)
}
if result.RefreshCapabilities {
t.Fatalf("expected refreshed fingerprint to become known, got %+v", result)
}
}
func validRunControlHello() domain.RunControlHello {
return domain.RunControlHello{
RegistrationToken: "registration-token",
RunEndpointID: "run-local",
DisplayName: "Local Run",
Version: "0.1.0",
Status: domain.RunEndpointStatusOnline,
Platform: "darwin/arm64",
CapabilityReport: domain.RunCapabilityReport{
Capabilities: []string{"control.hello", "control.heartbeat", domain.JobCapabilityDistributionBuild},
Fingerprint: "cap-v1",
},
Capacity: domain.RunCapacity{MaxJobs: 4},
}
}