mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 08:23:45 +00:00
feat(multiplayer): deliver allocated server rosters
This commit is contained in:
@@ -68,6 +68,56 @@ func TestAllocatedStartInjectsDynamicEndpointAndCallsReadyAfterProbe(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocatedStartMaterializesWorkloadAuthenticatedRosterBeforeChild(t *testing.T) {
|
||||
rosterPath := filepath.Join(t.TempDir(), "join-roster.json")
|
||||
sdk := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/gameserver":
|
||||
_, _ = w.Write([]byte(`{"object_meta":{"annotations":{"cosmic-clash.io/match-id":"match-1","cosmic-clash.io/workload-token":"workload-token"}},"status":{"address":"127.0.0.1","ports":[{"name":"game","port":31001}]}}`))
|
||||
case "/ready-probe", "/ready":
|
||||
w.WriteHeader(http.StatusOK)
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer sdk.Close()
|
||||
controlPlane := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/v1/servers/server-1/roster" {
|
||||
if r.Method != http.MethodGet || r.Header.Get("Authorization") != "Bearer workload-token" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
_, _ = w.Write([]byte(`[{"authorisation":{"player_id":"player-1"},"signature":"sig"}]`))
|
||||
return
|
||||
}
|
||||
if r.URL.Path == "/v1/servers/server-1/register" {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}))
|
||||
defer controlPlane.Close()
|
||||
command := []string{"/bin/sh", "-c", "test -s '" + rosterPath + "'"}
|
||||
s, err := New(Config{
|
||||
Command: command, SDKBaseURL: sdk.URL, ReadyURL: sdk.URL + "/ready-probe", ControlPlaneURL: controlPlane.URL,
|
||||
ServerID: "server-1", ProtocolVersion: 1, ImageDigest: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
RosterPath: rosterPath, ReadyTimeout: time.Second, PollInterval: time.Millisecond,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.Start(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.Wait(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
contents, err := os.ReadFile(rosterPath)
|
||||
if err != nil || !strings.Contains(string(contents), "player-1") {
|
||||
t.Fatalf("materialized roster=%q err=%v", contents, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestControlPlaneRegistrationRejectsIncompleteConfig(t *testing.T) {
|
||||
base := Config{Command: []string{"/bin/true"}, ControlPlaneURL: "https://control-plane.invalid"}
|
||||
if _, err := New(base); err == nil {
|
||||
|
||||
Reference in New Issue
Block a user