panel — open-source game server manager (public release)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 19:19:43 -07:00
commit 5232609719
2160 changed files with 300415 additions and 0 deletions
+170
View File
@@ -0,0 +1,170 @@
package dayzxml
import (
"strings"
"testing"
)
func TestDetectKind(t *testing.T) {
cases := []struct {
in string
want FileKind
}{
{`<types><type name="X"/></types>`, KindTypes},
{`<events><event name="X"/></events>`, KindEvents},
{`<spawnabletypes><type name="X"/></spawnabletypes>`, KindSpawnableTypes},
{`<messages><message/></messages>`, KindMessages},
{`<randompresets><cargo name="X"/></randompresets>`, KindRandomPresets},
{`<eventposdef><event name="X"/></eventposdef>`, KindEventSpawns},
}
for _, c := range cases {
got, err := DetectKind([]byte(c.in))
if err != nil {
t.Errorf("DetectKind(%q) err: %v", c.in, err)
continue
}
if got != c.want {
t.Errorf("DetectKind(%q) = %v, want %v", c.in, got, c.want)
}
}
if _, err := DetectKind([]byte(`<foo/>`)); err == nil {
t.Error("expected error for unknown root")
}
}
func TestMergeTypes_AddAndReplace(t *testing.T) {
base := []byte(`<types>
<type name="AKM"><nominal>5</nominal><min>2</min></type>
<type name="M4A1"><nominal>3</nominal><min>1</min></type>
</types>`)
snippet := []byte(`<types>
<type name="AKM"><nominal>8</nominal><min>4</min></type>
<type name="NewItem"><nominal>1</nominal><min>1</min></type>
</types>`)
res, err := Merge(KindTypes, base, snippet, false)
if err != nil {
t.Fatal(err)
}
if len(res.Plan.Added) != 1 || res.Plan.Added[0] != "NewItem" {
t.Errorf("Added = %v, want [NewItem]", res.Plan.Added)
}
if len(res.Plan.Replaced) != 1 || res.Plan.Replaced[0] != "AKM" {
t.Errorf("Replaced = %v, want [AKM]", res.Plan.Replaced)
}
out := string(res.Bytes)
if !strings.Contains(out, `name="NewItem"`) {
t.Error("merged output missing NewItem")
}
if !strings.Contains(out, `<nominal>8</nominal>`) {
t.Error("merged output missing updated AKM nominal value")
}
if !strings.Contains(out, `name="M4A1"`) {
t.Error("merged output dropped untouched M4A1 entry")
}
}
func TestMergeTypes_Unchanged(t *testing.T) {
xml := []byte(`<types>
<type name="AKM"><nominal>5</nominal></type>
</types>`)
res, err := Merge(KindTypes, xml, xml, true)
if err != nil {
t.Fatal(err)
}
if len(res.Plan.Unchanged) != 1 || res.Plan.Unchanged[0] != "AKM" {
t.Errorf("Unchanged = %v, want [AKM]", res.Plan.Unchanged)
}
if len(res.Plan.Replaced) != 0 {
t.Errorf("Replaced = %v, want []", res.Plan.Replaced)
}
}
func TestMergeEvents_AppendsChildren(t *testing.T) {
base := []byte(`<events>
<event name="VehicleSpawn">
<nominal>3</nominal>
<children>
<child type="UAZ_Base" min="1" max="1"/>
</children>
</event>
</events>`)
snippet := []byte(`<events>
<event name="VehicleSpawn">
<nominal>5</nominal>
<children>
<child type="UAZ_Mod1" min="1" max="1"/>
<child type="UAZ_Base" min="1" max="1"/>
</children>
</event>
</events>`)
res, err := Merge(KindEvents, base, snippet, false)
if err != nil {
t.Fatal(err)
}
out := string(res.Bytes)
// nominal overridden
if !strings.Contains(out, `<nominal>5</nominal>`) {
t.Error("event scalar child <nominal> not overridden")
}
// new child appended, existing child not duplicated
if strings.Count(out, `type="UAZ_Base"`) != 1 {
t.Errorf("existing child duplicated; output:\n%s", out)
}
if !strings.Contains(out, `type="UAZ_Mod1"`) {
t.Error("new child not appended")
}
if got := res.Plan.AppendedChildren["VehicleSpawn"]; len(got) != 1 || got[0] != "UAZ_Mod1" {
t.Errorf("AppendedChildren[VehicleSpawn] = %v, want [UAZ_Mod1]", got)
}
}
func TestMergeMessages_AppendOnly(t *testing.T) {
base := []byte(`<messages>
<message><id>1</id><text>Welcome</text></message>
</messages>`)
snippet := []byte(`<messages>
<message><id>2</id><text>Restart in 10m</text></message>
</messages>`)
res, err := Merge(KindMessages, base, snippet, false)
if err != nil {
t.Fatal(err)
}
if len(res.Plan.Added) != 1 {
t.Errorf("Added count = %d, want 1", len(res.Plan.Added))
}
if !strings.Contains(string(res.Bytes), "Restart in 10m") {
t.Error("appended message not present")
}
}
func TestStripBOM(t *testing.T) {
bom := []byte{0xEF, 0xBB, 0xBF}
raw := append(bom, []byte(`<types><type name="X"/></types>`)...)
k, err := DetectKind(raw)
if err != nil {
t.Fatal(err)
}
if k != KindTypes {
t.Errorf("kind = %v, want %v", k, KindTypes)
}
}
func TestRootMismatch(t *testing.T) {
base := []byte(`<types></types>`)
snippet := []byte(`<events></events>`)
if _, err := Merge(KindTypes, base, snippet, true); err == nil {
t.Error("expected error when snippet root doesn't match")
}
}
func TestPreserveCRLF(t *testing.T) {
base := []byte("<types>\r\n <type name=\"AKM\"><nominal>5</nominal></type>\r\n</types>")
snippet := []byte(`<types><type name="NEW"><nominal>1</nominal></type></types>`)
res, err := Merge(KindTypes, base, snippet, false)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(string(res.Bytes), "\r\n") {
t.Error("output dropped CRLF line endings; base had CRLF")
}
}