converge_test.go raw
1 package converge
2
3 import (
4 "testing"
5
6 "git.mleku.dev/mleku/dendrite/pkg/ratio"
7 )
8
9 func TestTrackerConverges(t *testing.T) {
10 // Window size of 100, threshold of 1/100.
11 tr := NewTracker(100, ratio.New(1, 100))
12
13 // First window: 100 tokens, 50 new vertices (interleaved).
14 for i := range 100 {
15 tr.RecordToken()
16 if i < 50 {
17 tr.RecordNewVertex()
18 }
19 }
20
21 if tr.IsConverged() {
22 t.Error("should not converge after 1 window")
23 }
24
25 // Next 3 windows: 100 tokens each, 0 new vertices. Rate = 0.
26 for range 300 {
27 tr.RecordToken()
28 }
29
30 if !tr.IsConverged() {
31 r := tr.Report()
32 t.Errorf("should converge after 3 windows with zero vertex creation; windows=%d rate=%s",
33 r.WindowCount, r.CurrentRate.String())
34 for i, w := range r.RecentWindows {
35 t.Logf(" window %d: tokens=%d vertices=%d rate=%s",
36 i, w.TokensProcessed, w.NewVertices, w.VertexRate.String())
37 }
38 }
39 }
40
41 func TestTrackerNotConvergedEarly(t *testing.T) {
42 tr := NewTracker(100, ratio.New(1, 100))
43
44 // Only 2 empty windows — need 3.
45 for range 200 {
46 tr.RecordToken()
47 }
48
49 if tr.IsConverged() {
50 t.Error("should not converge with only 2 windows")
51 }
52 }
53
54 func TestTrackerReportAccuracy(t *testing.T) {
55 tr := NewTracker(50, ratio.New(1, 100))
56
57 for range 100 {
58 tr.RecordToken()
59 }
60 for range 10 {
61 tr.RecordNewVertex()
62 }
63
64 r := tr.Report()
65 if r.TotalTokens != 100 {
66 t.Errorf("total tokens = %d, want 100", r.TotalTokens)
67 }
68 if r.TotalNewVertices != 10 {
69 t.Errorf("total vertices = %d, want 10", r.TotalNewVertices)
70 }
71 if r.WindowCount != 2 {
72 t.Errorf("window count = %d, want 2", r.WindowCount)
73 }
74 expected := ratio.New(10, 100)
75 if !r.CurrentRate.Equal(expected) {
76 t.Errorf("rate = %s, want %s", r.CurrentRate.String(), expected.String())
77 }
78 }
79
80 func TestTrackerMarshal(t *testing.T) {
81 tr := NewTracker(100, ratio.New(1, 1000))
82 for range 200 {
83 tr.RecordToken()
84 }
85 tr.RecordNewVertex()
86
87 data, err := tr.Marshal()
88 if err != nil {
89 t.Fatal(err)
90 }
91 if len(data) == 0 {
92 t.Error("marshal produced empty data")
93 }
94 }
95