Files

95 lines
3.2 KiB
Go

package storage
import (
"context"
"encoding/json"
"testing"
"github.com/metazla/meta-core/internal/claim"
"github.com/metazla/meta-core/internal/schema"
)
func schemaJSON(t *testing.T, c *Client) string {
t.Helper()
snap, err := schema.NewIndexer(c.Store()).Snapshot(context.Background())
if err != nil {
t.Fatal(err)
}
snap.GeneratedAt = snap.GeneratedAt.Truncate(0).UTC()
b, _ := json.Marshal(snap.Fields)
return string(b)
}
// The counters behind /api/schema and search's `total` follow the merged view.
// Whatever sequence of claims, retractions and edits runs, they must equal what
// a full rebuild from the records computes.
func TestCountersStayExactAcrossWrites(t *testing.T) {
c := newTestClient(t)
a, b := signer(t, 1), signer(t, 2)
mustAccept(t, c,
vote(t, a, "bafyR1", "title", "One", 10), vote(t, a, "bafyR1", "sizeByte", "100", 10),
vote(t, a, "bafyR1", "title/eng", "One", 10),
vote(t, a, "bafyR2", "title", "Two", 10), vote(t, a, "bafyR2", "sizeByte", "x", 10),
vote(t, a, "bafyR2", "genres/Action", "true", 10),
vote(t, a, "bafyR3", "title", "Three", 10), vote(t, a, "bafyR3", "sizeByte", "300", 10),
)
mustAccept(t, c,
vote(t, a, "bafyR2", "sizeByte", "200", 20), // label string → int
vote(t, b, "bafyR1", "title", "One", 20), // agreeing vote: merged value unchanged
vote(t, a, "bafyR1", "title/eng", nil, 20), // retraction
)
if n, err := c.CountRoots(); err != nil || n != 3 {
t.Fatalf("CountRoots = %d (err %v), want 3", n, err)
}
incremental := schemaJSON(t, c)
snap, _ := schema.NewIndexer(c.Store()).Snapshot(context.Background())
if f := snap.Fields["sizeByte"]; f == nil || f.Type != schema.PrimInt || f.Breakdown["int"] != 3 {
t.Fatalf("sizeByte = %+v, want 3 ints", f)
}
if _, ok := snap.Fields["title/eng"]; ok {
t.Fatalf("retracted title/eng still counted: %v", snap.Fields)
}
if err := c.RebuildCounters(); err != nil {
t.Fatal(err)
}
if rebuilt := schemaJSON(t, c); rebuilt != incremental {
t.Fatalf("incremental counters drifted from a rebuild:\n incremental %s\n rebuilt %s", incremental, rebuilt)
}
if n, _ := c.CountRoots(); n != 3 {
t.Fatalf("CountRoots after rebuild = %d", n)
}
}
func TestEnsureCountersBuildsOnce(t *testing.T) {
c := newTestClient(t)
seed(t, c, map[string]map[string]string{"R1": {"title": "One"}})
built, err := c.EnsureCounters()
if err != nil || !built {
t.Fatalf("first EnsureCounters built=%v err=%v", built, err)
}
if built, _ := c.EnsureCounters(); built {
t.Fatal("second EnsureCounters rebuilt again")
}
}
// Re-persisting the same signed claims writes nothing and publishes nothing —
// the gateway's constant repeats.
func TestUnchangedClaimWriteIsANoOp(t *testing.T) {
c := newTestClient(t)
a := signer(t, 1)
batch := []claim.Claim{
vote(t, a, "bafkreiabc", "title", "Naruto", 5),
vote(t, a, "bafkreiabc", "fileType", "video", 5),
}
mustAccept(t, c, batch...)
before, _ := c.GetStreamLength(MetaEventsStream)
for _, st := range write(t, c, batch...) {
if st != StatusUnchanged {
t.Fatalf("re-sent claim status %s, want unchanged", st)
}
}
if after, _ := c.GetStreamLength(MetaEventsStream); after != before {
t.Fatalf("re-persisting unchanged claims published %d events", after-before)
}
}