98 lines
3.6 KiB
Go
98 lines
3.6 KiB
Go
package index
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// ADR 0549 §2 (issue 1126): a merge changing one node's file writes that key alone and says one event; a merge with no
|
|
// placement change writes nothing and says nothing; a node whose file is gone loses its key and says its modules
|
|
// removed; a file that does not read leaves its key; a message that read no placement changes none.
|
|
func TestPlacementIsWrittenAtAMergeOnlyWhereItChanged(t *testing.T) {
|
|
ctx := context.Background()
|
|
ix, _, logs := newIndexer(t)
|
|
place := newMem()
|
|
ix.Placement = place
|
|
var said []delivery.PlacementChange
|
|
ix.Say = func(event string, body any) error {
|
|
if event != delivery.PlacementChangedEvent {
|
|
t.Errorf("said %s", event)
|
|
}
|
|
said = append(said, body.(delivery.PlacementChange))
|
|
return nil
|
|
}
|
|
merged := func(merge string, files map[string]string) delivery.Forge {
|
|
return delivery.Forge{V: delivery.Version, Kind: delivery.ForgeMerged, Repository: delivery.CatalogueRepository, Branch: "main",
|
|
Number: 7, Head: "h", Merge: merge, Root: "r", Trees: map[string]string{"": "t"}, Placements: files, PlacementsRead: true}
|
|
}
|
|
ace := `{"v":1,"node":"ace","modules":[{"module":"plex"}]}`
|
|
g14 := `{"v":1,"node":"g14","modules":[{"module":"zsh"}]}`
|
|
written := func(node string) (delivery.Placement, uint64) {
|
|
t.Helper()
|
|
v, ok := place.vals["placement."+node]
|
|
if !ok {
|
|
return delivery.Placement{}, 0
|
|
}
|
|
p, err := delivery.DecodePlacement(v)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return p, place.revs["placement."+node]
|
|
}
|
|
|
|
if err := ix.Apply(ctx, merged("m1", map[string]string{"ace": ace, "g14": g14})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p, _ := written("ace"); p.Revision != "m1" || !reflect.DeepEqual(p.Assigned(), []string{"plex"}) || len(said) != 2 {
|
|
t.Fatalf("first merge: %+v, said %v", p, said)
|
|
}
|
|
_, aceRev := written("ace")
|
|
|
|
said = nil
|
|
if err := ix.Apply(ctx, merged("m2", map[string]string{"ace": ace, "g14": g14})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p, rev := written("ace"); rev != aceRev || p.Revision != "m1" || len(said) != 0 {
|
|
t.Errorf("a merge with no placement change wrote %+v (revision %d, was %d) and said %v", p, rev, aceRev, said)
|
|
}
|
|
|
|
said = nil
|
|
if err := ix.Apply(ctx, merged("m3", map[string]string{"ace": ace, "g14": `{"v":1,"node":"g14","modules":[{"module":"zsh"},{"module":"xterm"}]}`})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, rev := written("ace"); rev != aceRev || len(said) != 1 || said[0].Node != "g14" || said[0].Revision != "m3" ||
|
|
!reflect.DeepEqual(said[0].Added, []string{"xterm"}) {
|
|
t.Errorf("one file changed: ace's revision %d (was %d), said %+v", rev, aceRev, said)
|
|
}
|
|
|
|
said = nil
|
|
if err := ix.Apply(ctx, merged("m4", map[string]string{"ace": ace, "g14": `{"v":1,"node":"ace","modules":[]}`})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p, _ := written("g14"); len(p.Modules) != 2 || len(said) != 0 || !strings.Contains(logs.String(), "the placement file of %s is refused") {
|
|
t.Errorf("a file naming another node replaced the key: %+v, said %v, logs %s", p, said, logs)
|
|
}
|
|
|
|
said = nil
|
|
if err := ix.Apply(ctx, merged("m5", map[string]string{"ace": ace})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, rev := written("g14"); rev != 0 || len(said) != 1 || !reflect.DeepEqual(said[0].Removed, []string{"xterm", "zsh"}) {
|
|
t.Errorf("a file removed: g14's key at revision %d, said %+v", rev, said)
|
|
}
|
|
|
|
said = nil
|
|
unread := merged("m6", nil)
|
|
unread.PlacementsRead = false
|
|
if err := ix.Apply(ctx, unread); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p, _ := written("ace"); p.Revision != "m1" || len(said) != 0 {
|
|
t.Errorf("a message that read no placement changed it: %+v, %v", p, said)
|
|
}
|
|
}
|