582b5a6b08
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
171 lines
4.9 KiB
Go
171 lines
4.9 KiB
Go
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")
|
|
}
|
|
}
|