package engine import ( "testing" "pve-confsync/internal/model" ) func keys(p Plan) []string { var out []string for _, c := range p.Changes { out = append(out, c.Key()) } return out } func TestFilterDependencies(t *testing.T) { p := Plan{Client: "c", Changes: []Change{ {Kind: model.KindZone, ID: "z1", Op: OpCreate, Set: map[string]any{"type": "vlan"}}, {Kind: model.KindZone, ID: "z2", Op: OpUpdate, Set: map[string]any{"mtu": 1500}}, {Kind: model.KindVNet, ID: "v1", Op: OpCreate, Set: map[string]any{"zone": "z1"}}, {Kind: model.KindVNet, ID: "v2", Op: OpCreate, Set: map[string]any{"zone": "z2"}}, {Kind: model.KindSubnet, ID: "z1-10.0.0.0-24", Op: OpCreate, Set: map[string]any{"vnet": "v1"}}, }} got := keys(Filter(p, []string{"sdn-subnet/z1-10.0.0.0-24"})) want := []string{"sdn-zone/z1", "sdn-vnet/v1", "sdn-subnet/z1-10.0.0.0-24"} if len(got) != len(want) { t.Fatalf("got %v, want %v", got, want) } for i := range want { if got[i] != want[i] { t.Fatalf("got %v, want %v (plan order kept)", got, want) } } // an update of the parent zone is not pulled in if got := keys(Filter(p, []string{"sdn-vnet/v2"})); len(got) != 1 { t.Fatalf("got %v, want only the vnet", got) } // unknown keys select nothing; no keys select everything if got := Filter(p, []string{"sdn-vnet/nope"}); len(got.Changes) != 0 { t.Fatalf("unknown key selected %v", keys(got)) } if got := Filter(p, nil); len(got.Changes) != len(p.Changes) { t.Fatal("empty selection must keep the whole plan") } } func TestFilterDeleteChildrenFirst(t *testing.T) { p := Plan{Changes: []Change{ {Kind: model.KindSubnet, ID: "z-10.0.0.0-24", Op: OpDelete, Old: map[string]any{"vnet": "v"}}, {Kind: model.KindVNet, ID: "v", Op: OpDelete, Old: map[string]any{"zone": "z"}}, {Kind: model.KindVNet, ID: "other", Op: OpDelete, Old: map[string]any{"zone": "y"}}, {Kind: model.KindZone, ID: "z", Op: OpDelete}, }} got := keys(Filter(p, []string{"sdn-zone/z"})) if len(got) != 3 || got[2] != "sdn-zone/z" { t.Fatalf("got %v", got) } } func TestFilterErrors(t *testing.T) { p := Plan{ Changes: []Change{ {Kind: model.KindVNet, ID: "ceph", Op: OpCreate, Set: map[string]any{"zone": "stor"}}, {Kind: model.KindVNet, ID: "vx1", Op: OpCreate, Set: map[string]any{"zone": "vxz"}}, }, Errors: []string{`sdn-zone/stor: field "bridge" required`, "sdn-subnet/z-fd00::-64: bad", "global problem"}, } if got := Filter(p, []string{"sdn-vnet/vx1"}); len(got.Errors) != 1 || got.Errors[0] != "global problem" { t.Fatalf("vx1: errors %v", got.Errors) } // the zone of ceph cannot be created: its error blocks ceph if got := Filter(p, []string{"sdn-vnet/ceph"}); len(got.Errors) != 2 { t.Fatalf("ceph: errors %v", got.Errors) } if k, ok := ErrorKey("sdn-subnet/z-fd00::-64: bad"); !ok || k != "sdn-subnet/z-fd00::-64" { t.Fatalf("ErrorKey IPv6: %q %v", k, ok) } } func TestDigest(t *testing.T) { a := Plan{Client: "c", Changes: []Change{{Kind: model.KindZone, ID: "z", Op: OpUpdate, Set: map[string]any{"mtu": 1500}}}} b := Plan{Client: "c", Changes: []Change{{Kind: model.KindZone, ID: "z", Op: OpUpdate, Set: map[string]any{"mtu": 9000}}}} if a.Digest() == b.Digest() { t.Fatal("different plans, same digest") } a2 := a a2.Warnings = []string{"w"} if a.Digest() != a2.Digest() { t.Fatal("warnings must not change the digest") } }