Files
david d6d2a24ddc style: gofmt all packages (#4)
Applies gofmt to the 18 files that were already unformatted at HEAD (pre-existing debt — 122 insertions / 122 deletions, whitespace plus import-block reorderings only; `git diff -w` confirms no semantic changes).

Kept on its own branch so the functional change set (see the review-hardening PR) stays reviewable without formatting noise.

Verified: go build, go vet, go test ./... pass on this branch; a merge simulation with the functional branch produces a clean 3-way merge with all tests green.
Reviewed-on: #4
Co-authored-by: David Gwilliam <dhgwilliam@gmail.com>
Co-committed-by: David Gwilliam <dhgwilliam@gmail.com>
2026-09-17 09:05:57 +00:00

115 lines
2.6 KiB
Go

package metrics
import (
"io"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
"github.com/david/knox/internal/db"
"github.com/prometheus/client_golang/prometheus/testutil"
)
func tmpKdb(t *testing.T) *db.KnoxDB {
t.Helper()
k, err := db.Open(filepath.Join(t.TempDir(), "index.db"))
if err != nil {
t.Fatalf("open db: %v", err)
}
t.Cleanup(func() { k.Close() })
return k
}
func seed(t *testing.T, k *db.KnoxDB, src string, n int) {
t.Helper()
for i := 0; i < n; i++ {
_, _, err := k.RecordObservation(db.ObservationRecord{
Fingerprint: "fp-" + src + "-" + string(rune('a'+i)),
SourceID: src,
SourcePath: src,
Project: "test",
ContentType: "test",
Title: src,
Summary: "s",
CreatedAt: "2026-08-29T00:00:00Z",
Confidence: 0.9,
IngesterVersion: "itest/v1",
})
if err != nil {
t.Fatalf("seed: %v", err)
}
}
}
func TestMetricsSnapshot(t *testing.T) {
k := tmpKdb(t)
seed(t, k, "git", 2)
seed(t, k, "browser-history", 3)
s, err := k.MetricsSnapshot()
if err != nil {
t.Fatalf("snapshot: %v", err)
}
if s.Observations != 5 {
t.Errorf("observations = %d, want 5", s.Observations)
}
if s.BySource["git"] != 2 || s.BySource["browser-history"] != 3 {
t.Errorf("by source = %v", s.BySource)
}
if s.KnowledgeVector[k.NodeID()] == 0 {
t.Errorf("knowledge vector missing own node")
}
if s.ByOriginNode[k.NodeID()] != 5 {
t.Errorf("by origin node = %v", s.ByOriginNode)
}
}
func TestMetricsScrape(t *testing.T) {
k := tmpKdb(t)
seed(t, k, "git", 2)
m := New(k, "testnode")
h := m.Handler()
rec := httptest.NewRecorder()
h.ServeHTTP(rec, httptest.NewRequest("GET", "/metrics", nil))
body, _ := io.ReadAll(rec.Body)
out := string(body)
for _, want := range []string{
`knox_node_info{name="testnode"`,
`knox_observations_total{source_id="git"} 2`,
`knox_gossip_pulls_total 0`,
"go_goroutines",
"process_cpu_seconds_total",
} {
if !strings.Contains(out, want) {
t.Errorf("scrape output missing %q", want)
}
}
}
func TestMetricsCounters(t *testing.T) {
k := tmpKdb(t)
m := New(k, "t")
// Manually drive counters through the Metrics API.
m.IncrementPull(3)
m.IncrementPush(7)
m.IncrementErrors()
if got := testutil.ToFloat64(m.pullsTotal); got != 1 {
t.Errorf("pullsTotal = %v, want 1", got)
}
if got := testutil.ToFloat64(m.obsPulledTotal); got != 3 {
t.Errorf("obsPulled = %v, want 3", got)
}
if got := testutil.ToFloat64(m.obsPushedTotal); got != 7 {
t.Errorf("obsPushed = %v, want 7", got)
}
if got := testutil.ToFloat64(m.errorsTotal); got != 1 {
t.Errorf("errorsTotal = %v, want 1", got)
}
}