Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

434 lines
12 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package store_sqlite
import (
"bytes"
"encoding/gob"
"encoding/json"
"path/filepath"
"reflect"
"testing"
"github.com/zzet/gortex/internal/contracts"
"github.com/zzet/gortex/internal/graph"
)
// flatRoundTrip encodes via the flat codec only (asserting the fast path was
// taken) and decodes back through decodeMeta.
func flatRoundTrip(t *testing.T, in map[string]any) map[string]any {
t.Helper()
b, ok := encodeMetaFast(in)
if !ok {
t.Fatalf("encodeMetaFast bailed on a modelled map: %#v", in)
}
if !isFlatMeta(b) {
t.Fatalf("encodeMetaFast did not stamp the flat magic: %q", b)
}
out, err := decodeMetaFast(b)
if err != nil {
t.Fatalf("decodeMetaFast: %v", err)
}
return out
}
// TestFlatCodecEveryValueType round-trips one value of every type the codec
// models and asserts exact Go-type fidelity end to end.
func TestFlatCodecEveryValueType(t *testing.T) {
shape := &contracts.Shape{
Kind: "struct",
Fields: []contracts.ShapeField{{Name: "id", Type: "int64", Required: true}},
Notes: []string{"partial"},
}
in := map[string]any{
"str": "hello",
"unicode": "héllo мир 世界 🚀",
"bool_t": true,
"bool_f": false,
"int": -7,
"int64": int64(1700000000),
"float": 0.875,
"float_int": 2.0, // integral float must stay float64
"strs": []string{"a", "b", "c"},
"nested": map[string]any{"inner": 5, "rate": 1.5, "deep": map[string]any{"x": int64(9)}},
"map_slice": []map[string]any{{"k": "v", "n": 1}, {"k": "w", "n": 2}},
"any_slice": []any{"x", 3, true, 4.5},
"shape": shape,
"nilval": nil,
"empty_map": map[string]any{},
}
got := flatRoundTrip(t, in)
if !reflect.DeepEqual(got, in) {
t.Fatalf("flat round-trip mismatch:\n got: %#v\nwant: %#v", got, in)
}
// Spot-check the load-bearing concrete types explicitly.
mustType[string](t, got, "str")
mustType[bool](t, got, "bool_t")
mustType[int](t, got, "int")
mustType[int64](t, got, "int64")
mustType[float64](t, got, "float")
mustType[float64](t, got, "float_int")
mustType[[]string](t, got, "strs")
mustType[map[string]any](t, got, "nested")
mustType[[]map[string]any](t, got, "map_slice")
mustType[[]any](t, got, "any_slice")
mustType[*contracts.Shape](t, got, "shape")
if got["nilval"] != nil {
t.Errorf("nilval: want nil, got %#v", got["nilval"])
}
}
// TestFlatCodecLargeValues exercises long keys and values that cross the
// single-byte varint boundary (> 127 bytes), proving the length prefixes
// round-trip.
func TestFlatCodecLargeValues(t *testing.T) {
big := string(bytes.Repeat([]byte("x"), 5000))
bigKey := string(bytes.Repeat([]byte("k"), 300))
in := map[string]any{
bigKey: big,
"slice": []string{big, "", big},
}
got := flatRoundTrip(t, in)
if !reflect.DeepEqual(got, in) {
t.Fatalf("large-value round-trip mismatch")
}
}
// TestFlatCodecDeterministic proves the encoding is byte-stable across
// encodes (keys are sorted), which matters for any content-hash / dedup.
func TestFlatCodecDeterministic(t *testing.T) {
in := map[string]any{
"z": 1, "a": "x", "m": []string{"p", "q"},
"nested": map[string]any{"d": 4, "b": 2, "c": 3},
}
var prev []byte
for i := 0; i < 16; i++ {
b, ok := encodeMetaFast(in)
if !ok {
t.Fatalf("encodeMetaFast bailed")
}
if prev != nil && !bytes.Equal(prev, b) {
t.Fatalf("encoding is not deterministic across encodes")
}
prev = b
}
}
// TestEncodeMetaFallbackToJSON: a value whose type the flat codec does not
// model makes encodeMeta fall back to JSON (leading '{'), and decodeMeta
// still reads it. No data is dropped.
func TestEncodeMetaFallbackToJSON(t *testing.T) {
// uint64 is deliberately outside the modelled type set.
in := map[string]any{"weird": uint64(42), "name": "keep"}
if _, ok := encodeMetaFast(in); ok {
t.Fatal("encodeMetaFast should bail on an unmodelled value type")
}
b, err := encodeMeta(in)
if err != nil {
t.Fatalf("encodeMeta: %v", err)
}
if isFlatMeta(b) {
t.Fatalf("encodeMeta should have fallen back to JSON, got a flat blob")
}
if !isJSONObject(b) {
t.Fatalf("encodeMeta fallback did not produce a JSON object: %q", b)
}
got, err := decodeMeta(b)
if err != nil {
t.Fatalf("decodeMeta(json fallback): %v", err)
}
// The JSON fallback widens uint64 -> int (documented, lossy only for the
// exotic tail), but the string survives and no row is lost.
if got["name"] != "keep" {
t.Errorf("name not preserved through JSON fallback: %#v", got["name"])
}
if _, ok := got["weird"]; !ok {
t.Errorf("weird key dropped by JSON fallback")
}
}
// TestDecodeLegacyJSON proves rows written by the previous JSON encoder still
// decode (routed through metaWire for exact types) after the flat-codec
// switch — existing on-disk databases must keep loading.
func TestDecodeLegacyJSON(t *testing.T) {
orig := map[string]any{
"visibility": "private",
"complexity": 9,
"confidence": 1.0, // integral float — metaWire must keep it float64
"path_param_names": []string{"id"},
"last_authored": map[string]any{"timestamp": int64(1700000000)},
}
blob, err := json.Marshal(orig)
if err != nil {
t.Fatalf("json.Marshal: %v", err)
}
if isFlatMeta(blob) {
t.Fatalf("JSON blob unexpectedly looks like a flat blob")
}
got, err := decodeMeta(blob)
if err != nil {
t.Fatalf("decodeMeta(json): %v", err)
}
mustType[string](t, got, "visibility")
mustType[int](t, got, "complexity")
mustType[float64](t, got, "confidence")
mustType[[]string](t, got, "path_param_names")
la, ok := got["last_authored"].(map[string]any)
if !ok {
t.Fatalf("last_authored: want map[string]any, got %T", got["last_authored"])
}
mustType[int64](t, la, "timestamp")
}
// TestDecodeMetaFastMalformed: corrupt / truncated flat blobs return an error
// rather than panicking — a single bad row must not crash a store scan.
func TestDecodeMetaFastMalformed(t *testing.T) {
good, ok := encodeMetaFast(map[string]any{"k": "value", "n": 7, "s": []string{"a", "b"}})
if !ok {
t.Fatalf("encodeMetaFast bailed")
}
cases := map[string][]byte{
"magic only": {metaFlatMagic0, metaFlatVersion},
"count then nothing": {metaFlatMagic0, metaFlatVersion, 0x05},
"truncated mid-blob": good[:len(good)-3],
"unknown value tag": {metaFlatMagic0, metaFlatVersion, 0x01, 0x01, 'k', 0x7E},
"giant key length": {metaFlatMagic0, metaFlatVersion, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F},
}
for name, blob := range cases {
t.Run(name, func(t *testing.T) {
_, err := decodeMeta(blob)
if err == nil {
t.Errorf("expected an error for %q, got nil", name)
}
})
}
}
// TestStoreReloadMetaFidelity is the wired-path proof: persist a node and an
// edge with rich Meta through the real store, reopen it (warm restart), and
// assert Meta is byte-for-byte type-identical. Also runs PRAGMA
// integrity_check.
func TestStoreReloadMetaFidelity(t *testing.T) {
path := filepath.Join(t.TempDir(), "store.sqlite")
nodeMeta := map[string]any{
"complexity": 7,
"loop_depth": 2,
"confidence": 0.875,
"coverage_pct": 1.0, // integral float
"candidate_count": 2,
"path_param_names": []string{"id", "org"},
"status_codes": []string{"200", "404"},
"churn": map[string]any{"commit_count": 12, "churn_rate": 2.0, "last_author": "a@b.c"},
"last_authored": map[string]any{"timestamp": int64(1700000000), "email": "x@y.z"},
"response_envelope": []map[string]any{{"name": "data", "n": 1}},
"shape": &contracts.Shape{
Kind: "struct",
Fields: []contracts.ShapeField{{Name: "id", Type: "int64", Required: true}},
Notes: []string{"partial"},
},
"unicode_doc": "héllo 世界 🚀",
"is_generated": false,
}
edgeMeta := map[string]any{
"candidate_count": 3,
"similarity": 0.5,
"score": 1.0, // integral float
"count": 5,
"clone_tokens": 128,
"synthesized_by": "grpc",
"arg_names": []string{"ctx", "req"},
}
func() {
s, err := Open(path)
if err != nil {
t.Fatalf("Open: %v", err)
}
defer s.Close()
s.AddNode(&graph.Node{ID: "n1", Kind: "function", Name: "Foo", FilePath: "f.go", Meta: cloneMeta(nodeMeta)})
s.AddNode(&graph.Node{ID: "n2", Kind: "function", Name: "Bar", FilePath: "f.go"})
s.AddEdge(&graph.Edge{From: "n1", To: "n2", Kind: "calls", FilePath: "f.go", Line: 10, Meta: cloneMeta(edgeMeta)})
}()
// Reopen — the warm-restart path that reads every blob back.
s, err := Open(path)
if err != nil {
t.Fatalf("reopen: %v", err)
}
defer s.Close()
n := s.GetNode("n1")
if n == nil {
t.Fatal("GetNode(n1) = nil after reload")
}
if !reflect.DeepEqual(n.Meta, nodeMeta) {
t.Fatalf("node Meta mismatch after reload:\n got: %#v\nwant: %#v", n.Meta, nodeMeta)
}
edges := s.GetOutEdges("n1")
var got *graph.Edge
for _, e := range edges {
if e.To == "n2" && e.Kind == "calls" {
got = e
break
}
}
if got == nil {
t.Fatalf("edge n1->n2 not found after reload (got %d edges)", len(edges))
}
if !reflect.DeepEqual(got.Meta, edgeMeta) {
t.Fatalf("edge Meta mismatch after reload:\n got: %#v\nwant: %#v", got.Meta, edgeMeta)
}
var res string
if err := s.db.QueryRow(`PRAGMA integrity_check`).Scan(&res); err != nil {
t.Fatalf("integrity_check: %v", err)
}
if res != "ok" {
t.Fatalf("integrity_check = %q, want ok", res)
}
}
func cloneMeta(m map[string]any) map[string]any {
out := make(map[string]any, len(m))
for k, v := range m {
out[k] = v
}
return out
}
func mustType[T any](t *testing.T, m map[string]any, key string) {
t.Helper()
v, ok := m[key]
if !ok {
t.Errorf("%s: missing from decoded map", key)
return
}
if _, ok := v.(T); !ok {
var zero T
t.Errorf("%s: want type %T, got %T (value %v)", key, zero, v, v)
}
}
// -- benchmarks -----------------------------------------------------------
var metaSink any
// benchMetaSample is a representative node/edge meta map restricted to the
// types gob auto-registers (scalars + []string), so all three encoders run on
// identical input for an apples-to-apples comparison. Shape / nested-map /
// map-slice values also ride the flat path (see the round-trip tests); they
// are omitted here only because gob refuses unregistered interface types.
func benchMetaSample() map[string]any {
return map[string]any{
"complexity": 7,
"loop_depth": 2,
"parse_errors": 0,
"position": 3,
"line": 42,
"confidence": 0.875,
"coverage_pct": 83.5,
"candidate_count": 2,
"count": 5,
"clone_tokens": 128,
"timestamp": int64(1700000000),
"path_param_names": []string{"id", "org"},
"status_codes": []string{"200", "404"},
"signature": "func F(ctx context.Context, x int) (T, error)",
"some_plugin_flag": "go_linkname",
"is_generated": false,
"synthesized_by": "grpc",
}
}
func BenchmarkEncodeMetaGob(b *testing.B) {
m := benchMetaSample()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(m); err != nil {
b.Fatalf("gob encode: %v", err)
}
metaSink = buf.Bytes()
}
}
func BenchmarkEncodeMetaJSON(b *testing.B) {
m := benchMetaSample()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
out, err := json.Marshal(m)
if err != nil {
b.Fatalf("json marshal: %v", err)
}
metaSink = out
}
}
func BenchmarkEncodeMetaFlat(b *testing.B) {
m := benchMetaSample()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
out, ok := encodeMetaFast(m)
if !ok {
b.Fatal("encodeMetaFast bailed")
}
metaSink = out
}
}
func BenchmarkDecodeMetaGob(b *testing.B) {
var buf bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(benchMetaSample()); err != nil {
b.Fatalf("gob encode: %v", err)
}
blob := buf.Bytes()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
m, err := decodeMeta(blob)
if err != nil {
b.Fatalf("decodeMeta: %v", err)
}
metaSink = m
}
}
func BenchmarkDecodeMetaJSON(b *testing.B) {
blob, err := json.Marshal(benchMetaSample())
if err != nil {
b.Fatalf("json marshal: %v", err)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
m, err := decodeMeta(blob)
if err != nil {
b.Fatalf("decodeMeta: %v", err)
}
metaSink = m
}
}
func BenchmarkDecodeMetaFlat(b *testing.B) {
blob, ok := encodeMetaFast(benchMetaSample())
if !ok {
b.Fatal("encodeMetaFast bailed")
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
m, err := decodeMeta(blob)
if err != nil {
b.Fatalf("decodeMeta: %v", err)
}
metaSink = m
}
}