Files
aego/scene/prefab/prefab_test.go

123 lines
4.1 KiB
Go

package prefab_test
import (
"testing"
"aego/core/errs"
"aego/core/ids"
"aego/scene/prefab"
"aego/schema"
)
type library map[prefab.PrefabID]*prefab.Node
func (l library) Prefab(id prefab.PrefabID) (*prefab.Node, bool) {
n, ok := l[id]
return n, ok
}
func nid(n uint64) ids.NodeID {
return ids.NodeID{Hi: 0xa11, Lo: n}
}
func instanceOf(local ids.NodeID, p prefab.PrefabID) *prefab.Node {
return &prefab.Node{Local: local, Instance: &prefab.Instance{Prefab: p}}
}
func TestKeyID(t *testing.T) {
k := prefab.LocalKey(nid(7))
if k.ID() != nid(7) || k.Nested() {
t.Fatal("a single key must be its own local id")
}
n := prefab.Rekey(k, prefab.LocalKey(nid(1)), prefab.LocalKey(nid(2)))
again := prefab.Rekey(k, prefab.LocalKey(nid(1)), prefab.LocalKey(nid(2)))
if !n.Nested() || n.ID() == nid(7) || n.ID() != again.ID() || n.Instance() != prefab.LocalKey(nid(2)) {
t.Fatalf("nested key %s", n)
}
if got, ok := prefab.ParseKey(string(n)); !ok || got != n {
t.Fatal("nested key does not parse back")
}
if prefab.Rekey(prefab.LocalKey(nid(1)), prefab.LocalKey(nid(1)), prefab.LocalKey(nid(2))) != prefab.LocalKey(nid(2)) {
t.Fatal("the nested root takes the key of the instance node")
}
}
func TestNestedKeysAndRefs(t *testing.T) {
q := prefab.NewNode(nid(1), "Q", false)
b := prefab.NewNode(nid(2), "B", false)
q.Children = []*prefab.Node{b}
q.Comps = append(q.Comps, prefab.Comp{Owner: "test.A", Kind: prefab.CompComponent, Fields: []prefab.Field{
{Name: "r", Value: schema.Node(b.Local)},
{Name: "self", Value: schema.Node(q.Local)},
{Name: "out", Value: schema.Node(nid(99))},
}})
qid := ids.AssetID{Lo: 1}
p := prefab.NewNode(nid(3), "P", false)
p.Children = []*prefab.Node{instanceOf(nid(4), qid)}
tree, orph, err := prefab.Expand(library{qid: q}, p, nil)
if err != nil || !orph.Empty() {
t.Fatal(err)
}
n := tree.Children[0]
inner := n.Children[0]
if n.Key != prefab.LocalKey(nid(4)) || n.Local != nid(4) || n.Origin == nil || n.Name() != "Q" {
t.Fatalf("instance root = %+v", n)
}
if inner.Key != prefab.LocalKey(nid(4))+"/"+prefab.LocalKey(nid(2)) || inner.Local != inner.Key.ID() {
t.Fatalf("inner key = %s", inner.Key)
}
if v, _ := n.Get(prefab.PropKey{Owner: "test.A", Field: "r"}); v.Node != inner.Local {
t.Fatal("ref inside the nested prefab must follow the key")
}
if v, _ := n.Get(prefab.PropKey{Owner: "test.A", Field: "self"}); v.Node != nid(4) {
t.Fatal("ref to the nested root must point at the instance node")
}
if v, _ := n.Get(prefab.PropKey{Owner: "test.A", Field: "out"}); v.Node != nid(99) {
t.Fatal("ref outside the prefab must stay as is")
}
if v, _ := q.Comp("test.A").Get("r"); v.Node != nid(2) {
t.Fatal("expand changed the library prefab")
}
}
func TestMissingPrefab(t *testing.T) {
p := prefab.NewNode(nid(1), "P", false)
qid := ids.AssetID{Lo: 5}
p.Children = []*prefab.Node{instanceOf(nid(2), qid)}
tree, _, err := prefab.Expand(library{}, p, nil)
if err != nil {
t.Fatal(err)
}
m := tree.Children[0]
if !m.Missing || m.Origin == nil || m.Origin.Prefab != qid || m.Key != prefab.LocalKey(nid(2)) {
t.Fatalf("missing node = %+v", m)
}
}
func TestCycleAndDepth(t *testing.T) {
a, b := ids.AssetID{Lo: 1}, ids.AssetID{Lo: 2}
ra := prefab.NewNode(nid(1), "A", false)
ra.Children = []*prefab.Node{instanceOf(nid(2), b)}
rb := prefab.NewNode(nid(3), "B", false)
rb.Children = []*prefab.Node{instanceOf(nid(4), a)}
if _, _, err := prefab.Expand(library{a: ra, b: rb}, ra, nil); !errs.Has(err, errs.PrefabCycle) {
t.Fatalf("cycle: %v", err)
}
lib := library{}
var chain []*prefab.Node
for i := 0; i <= prefab.MaxDepth+1; i++ {
n := prefab.NewNode(nid(uint64(100+2*i)), "L", false)
if i > 0 {
n.Children = []*prefab.Node{instanceOf(nid(uint64(101+2*i)), ids.AssetID{Lo: uint64(i - 1)})}
}
lib[ids.AssetID{Lo: uint64(i)}] = n
chain = append(chain, n)
}
if _, _, err := prefab.Expand(lib, chain[prefab.MaxDepth], nil); err != nil {
t.Fatalf("depth %d must expand: %v", prefab.MaxDepth, err)
}
if _, _, err := prefab.Expand(lib, chain[prefab.MaxDepth+1], nil); !errs.Has(err, errs.PrefabDepth) {
t.Fatalf("depth: %v", err)
}
}