Every container the node-agent starts gets /usr/sbin/docker-init, and SteamCMD rewrites its own config.vdf on every run. Counted as files written outside the volumes, they made every build look like it loses saves. A folder whose only changes were logs no longer counts either, and a folder followed by a same-named file (worlds, worlds.bak) is no longer taken for a file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
82 lines
2.8 KiB
Go
82 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestBootFailureKeepsVerdictAndServerOutput(t *testing.T) {
|
|
out := "[boot-test] deploying boottest-example (cm2network/steamcmd)\n" +
|
|
"[boot-test] container started; waiting for ready pattern /Server ready/\n" +
|
|
"[boot-test] FAILED: container exited before it was ready\n" +
|
|
"---- last 2 log lines ----\n" +
|
|
"Unknown argument --save-dir\n" +
|
|
"Usage: example_server ...\n"
|
|
got := bootFailure(out)
|
|
if !strings.Contains(got, "failed: FAILED: container exited before it was ready") {
|
|
t.Errorf("verdict missing: %s", got)
|
|
}
|
|
if !strings.Contains(got, "Unknown argument --save-dir") || strings.Contains(got, "deploying boottest") {
|
|
t.Errorf("want only the server's last lines, got: %s", got)
|
|
}
|
|
if v := bootVerdict("[boot-test] PASSED: READY: Server ready"); v != "PASSED: READY: Server ready" {
|
|
t.Errorf("verdict = %q", v)
|
|
}
|
|
}
|
|
|
|
func TestOutsideDirsSkipsSteamNoise(t *testing.T) {
|
|
r := &bootReport{ContainerChanges: []string{
|
|
"A /home/steam/.config/example-game/worlds/w.db",
|
|
"A /home/steam/Steam/logs/connection_log.txt",
|
|
"C /home/steam/Steam/config/config.vdf",
|
|
"C /home/steam/.steam/registry.vdf",
|
|
"A /usr/sbin/docker-init",
|
|
}}
|
|
got := outsideDirs(r)
|
|
if len(got) != 1 || got[0] != "/home/steam/.config/example-game/worlds" {
|
|
t.Errorf("got %v", got)
|
|
}
|
|
if outsideDirs(nil) != nil {
|
|
t.Error("nil report should have no dirs")
|
|
}
|
|
}
|
|
|
|
func TestVariantNotes(t *testing.T) {
|
|
v := variant{Title: "Crossplay", Description: "PC + Xbox", StartupHint: "./example_server -crossplay", Ports: []string{"30000/udp"}}
|
|
got := variantNotes(v, "needs Xbox")
|
|
for _, want := range []string{"variant: Crossplay (PC + Xbox)", "documented startup: ./example_server -crossplay", "30000/udp", "the admin asked for: needs Xbox"} {
|
|
if !strings.Contains(got, want) {
|
|
t.Errorf("missing %q in %q", want, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBlankRequiredLookingSettings(t *testing.T) {
|
|
dir := t.TempDir()
|
|
game := filepath.Join(dir, "example")
|
|
os.MkdirAll(game, 0o755)
|
|
os.WriteFile(filepath.Join(game, "game.yaml"), []byte(`id: example
|
|
defaultConfig:
|
|
JoinPassword: ""
|
|
AdminPassword: ""
|
|
ServerPassword: set-by-default
|
|
ServerName: x
|
|
configSchema:
|
|
properties:
|
|
JoinPassword: {type: string}
|
|
AdminPassword: {type: string, x-generate: {type: password}}
|
|
ServerPassword: {type: string}
|
|
ServerName: {type: string}
|
|
`), 0o644)
|
|
got := blankRequiredLooking(dir, "example")
|
|
if len(got) != 1 || got[0] != "JoinPassword" {
|
|
t.Errorf("got %v, want only JoinPassword (AdminPassword is generated, ServerPassword has a default)", got)
|
|
}
|
|
msg := emptySettingsProblem(got, "FAILED: server crashed")
|
|
if !strings.Contains(msg, "stops when JoinPassword is empty") || !strings.Contains(msg, `"x-generate": {"type": "password"}`) {
|
|
t.Errorf("message: %s", msg)
|
|
}
|
|
}
|