package meshmoduleassignerclient import ( "testing" "time" seat "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" ) // The digest a node key names is kept as the first writer made it, so a node key written before this client reads. func TestDigestIsTheFirstWritersAndHoldersAndStandingRead(t *testing.T) { m := seat.PlacedModule{Module: "app", Ports: map[string]int64{"8080": 18080}, Bindings: map[string]seat.Provider{"postgres": {Node: "novox", Module: "postgres"}}, HasMeshWide: true, MeshWide: map[string]any{"a": 1.0}, Layer: map[string]any{"expose": "x"}, HasLayer: true, MeshWideValues: map[string]any{"k": "v"}, Values: map[string]any{"p": 2.0}} if got := Digest(m); got != "62b3c2796d264c42" { t.Errorf("Digest = %s, the first writer's is 62b3c2796d264c42", got) } keys := map[string][]byte{ "mesh-module-assigner": []byte(`{"v":1,"seat":"mesh-module-assigner","scope":"mesh","holders":[{"module":"mesh-delivery-assigner","node":"novox"}]}`), "node-files.ace": []byte(`{"v":1,"seat":"node-files","scope":"node","node":"ace","holders":[{"module":"node-files","node":"ace"}]}`), "mesh-vault": []byte(`{"v":2,"seat":"mesh-vault","scope":"mesh","holders":[]}`), } for _, c := range []struct { seat, node string want int bad bool }{{"mesh-module-assigner", "", 1, false}, {"node-files", "ace", 1, false}, {"node-files", "g14", 0, false}, {"mesh-vault", "", 0, true}} { got, err := HoldersOf(keys, c.seat, c.node) if (err != nil) != c.bad || len(got) != c.want { t.Errorf("HoldersOf(%s, %q) = %v, %v", c.seat, c.node, got, err) } } // A module stands since the revision of its node's key that first named it; the first revision heard stands since // the zero time. p := NewPlaced() t0 := time.Date(2026, 11, 5, 12, 0, 0, 0, time.UTC) node := func(modules ...string) []byte { n := seat.PlacementByNodeNodeValue{Node: "ace"} for _, name := range modules { n.Modules = append(n.Modules, seat.PlacementByNodeNodeValueModulesItem{Module: name, Digest: "d"}) } raw, err := EncodeNode(n) if err != nil { t.Fatal(err) } return raw } if _, changed, err := p.Put("ace.node", node("a"), false, t0); err != nil || len(changed) != 1 { t.Fatalf("first: %v, %v", changed, err) } if _, changed, _ := p.Put("ace.node", node("a", "b"), false, t0.Add(time.Hour)); len(changed) != 1 || changed[0] != "b" { t.Fatalf("second: %v", changed) } if since, ok := p.Since("ace", "a"); !ok || !since.IsZero() { t.Errorf("a stands since the zero time: %v %v", since, ok) } if since, ok := p.Since("ace", "b"); !ok || !since.Equal(t0.Add(time.Hour)) { t.Errorf("b stands since the second revision: %v %v", since, ok) } if got := p.PlacedNodes("b"); len(got) != 1 || got[0] != "ace" { t.Errorf("PlacedNodes = %v", got) } }