diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-26 22:57:10 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-26 22:57:10 +0300 |
| commit | 3d3fcacbdc28c4296b1477e34999011b5a7d93f2 (patch) | |
| tree | 7e383af76f4d38ba971159ac05e9689c0d1ca7bb /internal/flamegraph | |
| parent | 7f81653beed3f6d0317a23017914a0d9a7d7794a (diff) | |
test: add xo coverage for dual metrics and variable-height flamegraph
Diffstat (limited to 'internal/flamegraph')
| -rw-r--r-- | internal/flamegraph/livetrie_test.go | 52 | ||||
| -rw-r--r-- | internal/flamegraph/trie_test.go | 56 |
2 files changed, 108 insertions, 0 deletions
diff --git a/internal/flamegraph/livetrie_test.go b/internal/flamegraph/livetrie_test.go index 32e2b40..a12f5d9 100644 --- a/internal/flamegraph/livetrie_test.go +++ b/internal/flamegraph/livetrie_test.go @@ -359,6 +359,27 @@ func TestLiveTrieSetHeightFieldRejectsInvalidValue(t *testing.T) { } } +func TestLiveTrieSetHeightFieldNoopKeepsBaseline(t *testing.T) { + lt := NewLiveTrie([]string{"comm"}, "count", "bytes") + lt.Ingest(newTestPair("svc", 42, 1001, "/tmp/a", 10, 1, 64)) + beforeVersion := lt.Version() + + if err := lt.SetHeightField("bytes"); err != nil { + t.Fatalf("set height field noop: %v", err) + } + if got := lt.Version(); got != beforeVersion { + t.Fatalf("version changed on noop height field set: got %d want %d", got, beforeVersion) + } + + snap := decodeLiveSnapshot(t, lt) + if got, want := snap.Total, uint64(1); got != want { + t.Fatalf("total after noop height switch = %d, want %d", got, want) + } + if got, want := snap.HeightTotal, uint64(64); got != want { + t.Fatalf("height total after noop height switch = %d, want %d", got, want) + } +} + func TestLiveTrieHeightFieldEmptyDisablesHeightTotals(t *testing.T) { lt := NewLiveTrie([]string{"comm"}, "count", "") lt.Ingest(newTestPair("svc", 42, 1001, "/tmp/a", 10, 1, 64)) @@ -372,6 +393,37 @@ func TestLiveTrieHeightFieldEmptyDisablesHeightTotals(t *testing.T) { } } +func TestLiveTrieSnapshotHeightTotalsAccumulateAcrossBranches(t *testing.T) { + lt := NewLiveTrie([]string{"comm", "pid"}, "count", "bytes") + lt.Ingest(newTestPair("svc", 101, 1001, "/tmp/a", 10, 1, 100)) + lt.Ingest(newTestPair("svc", 102, 1002, "/tmp/b", 10, 1, 40)) + lt.Ingest(newTestPair("db", 201, 1003, "/tmp/c", 10, 1, 10)) + + snap := decodeLiveSnapshot(t, lt) + if got, want := snap.Total, uint64(3); got != want { + t.Fatalf("root total = %d, want %d", got, want) + } + if got, want := snap.HeightTotal, uint64(150); got != want { + t.Fatalf("root height total = %d, want %d", got, want) + } + + svc := findSnapshotPath(t, &snap, "svc") + if got, want := svc.Total, uint64(2); got != want { + t.Fatalf("svc total = %d, want %d", got, want) + } + if got, want := svc.HeightTotal, uint64(140); got != want { + t.Fatalf("svc height total = %d, want %d", got, want) + } + + db := findSnapshotPath(t, &snap, "db") + if got, want := db.Total, uint64(1); got != want { + t.Fatalf("db total = %d, want %d", got, want) + } + if got, want := db.HeightTotal, uint64(10); got != want { + t.Fatalf("db height total = %d, want %d", got, want) + } +} + func TestLiveTrieSnapshotJSONCaching(t *testing.T) { lt := NewLiveTrie([]string{"comm"}, "count", "count") lt.Ingest(newTestPair("svc", 42, 1001, "/tmp/a", 1, 1, 1)) diff --git a/internal/flamegraph/trie_test.go b/internal/flamegraph/trie_test.go index 47ef770..9f56b15 100644 --- a/internal/flamegraph/trie_test.go +++ b/internal/flamegraph/trie_test.go @@ -167,3 +167,59 @@ func TestInsertTriePathStoresValueAndHeightValueIndependently(t *testing.T) { t.Fatalf("expected leaf heightValue=5, got %d", b.heightValue) } } + +func TestTrieComputeTotalsPropagatesDualMetricsAcrossBranches(t *testing.T) { + tr := newTrie() + insertTriePath(tr.root, []string{"a", "x"}, 5, 100) + insertTriePath(tr.root, []string{"a", "y"}, 3, 40) + insertTriePath(tr.root, []string{"b", "z"}, 7, 1) + tr.computeTotals() + + a := findChild(tr.root, "a") + if a == nil { + t.Fatal("expected node a") + } + b := findChild(tr.root, "b") + if b == nil { + t.Fatal("expected node b") + } + x := findChild(a, "x") + if x == nil { + t.Fatal("expected node x") + } + y := findChild(a, "y") + if y == nil { + t.Fatal("expected node y") + } + + if got, want := x.total, uint64(5); got != want { + t.Fatalf("x total = %d, want %d", got, want) + } + if got, want := x.heightTotal, uint64(100); got != want { + t.Fatalf("x heightTotal = %d, want %d", got, want) + } + if got, want := y.total, uint64(3); got != want { + t.Fatalf("y total = %d, want %d", got, want) + } + if got, want := y.heightTotal, uint64(40); got != want { + t.Fatalf("y heightTotal = %d, want %d", got, want) + } + if got, want := a.total, uint64(8); got != want { + t.Fatalf("a total = %d, want %d", got, want) + } + if got, want := a.heightTotal, uint64(140); got != want { + t.Fatalf("a heightTotal = %d, want %d", got, want) + } + if got, want := b.total, uint64(7); got != want { + t.Fatalf("b total = %d, want %d", got, want) + } + if got, want := b.heightTotal, uint64(1); got != want { + t.Fatalf("b heightTotal = %d, want %d", got, want) + } + if got, want := tr.root.total, uint64(15); got != want { + t.Fatalf("root total = %d, want %d", got, want) + } + if got, want := tr.root.heightTotal, uint64(141); got != want { + t.Fatalf("root heightTotal = %d, want %d", got, want) + } +} |
