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

169 lines
4.8 KiB
Go

package quality
import (
"os"
"path/filepath"
"testing"
"time"
)
func TestDiffFingerprints_NoPreviousIsNoDrift(t *testing.T) {
cur := EmbedderFingerprint{Provider: "hugot", Model: "MiniLM-L6-v2", EmbeddingDim: 384}
w := DiffFingerprints(EmbedderFingerprint{}, cur)
if w.HasDrift() {
t.Errorf("no previous fingerprint should not flag drift; got %v", w.Changes)
}
}
func TestDiffFingerprints_ProviderChangeFlagged(t *testing.T) {
prev := EmbedderFingerprint{Provider: "hugot", Model: "MiniLM-L6-v2", EmbeddingDim: 384}
cur := EmbedderFingerprint{Provider: "openai", Model: "text-embedding-3-small", EmbeddingDim: 384}
w := DiffFingerprints(prev, cur)
if !w.HasDrift() {
t.Fatal("provider change should flag drift")
}
hasProvider := false
hasModel := false
for _, c := range w.Changes {
if contains(c, "provider:") {
hasProvider = true
}
if contains(c, "model:") {
hasModel = true
}
}
if !hasProvider || !hasModel {
t.Errorf("expected provider + model in changes, got %v", w.Changes)
}
}
func TestDiffFingerprints_DimChangeFlagged(t *testing.T) {
prev := EmbedderFingerprint{Provider: "hugot", Model: "MiniLM-L6-v2", EmbeddingDim: 384}
cur := EmbedderFingerprint{Provider: "hugot", Model: "MiniLM-L6-v2", EmbeddingDim: 768}
w := DiffFingerprints(prev, cur)
if !w.HasDrift() {
t.Fatal("dim change should flag drift")
}
}
func TestDiffFingerprints_IdenticalIsNoDrift(t *testing.T) {
fp := EmbedderFingerprint{Provider: "hugot", Model: "MiniLM-L6-v2", EmbeddingDim: 384, SampleVecSHA256: "abc"}
w := DiffFingerprints(fp, fp)
if w.HasDrift() {
t.Errorf("identical fingerprints should not flag drift; got %v", w.Changes)
}
}
func TestDiffFingerprints_SampleVecChangeFlagged(t *testing.T) {
prev := EmbedderFingerprint{Provider: "hugot", Model: "M", EmbeddingDim: 384, SampleVecSHA256: "abc"}
cur := EmbedderFingerprint{Provider: "hugot", Model: "M", EmbeddingDim: 384, SampleVecSHA256: "xyz"}
w := DiffFingerprints(prev, cur)
if !w.HasDrift() {
t.Fatal("sample-vec change should flag drift")
}
}
func TestDriftDetector_RoundTripFingerprint(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "fp.json")
d := NewDriftDetector(path)
want := EmbedderFingerprint{
Provider: "hugot",
Model: "MiniLM-L6-v2",
ModelRevision: "fp32",
EmbeddingDim: 384,
SampleVecSHA256: "deadbeef",
RecordedAt: time.Now().UTC().Round(time.Second),
}
if err := d.Save(want); err != nil {
t.Fatalf("Save: %v", err)
}
got, err := d.LoadPrevious()
if err != nil {
t.Fatalf("LoadPrevious: %v", err)
}
if got.Provider != want.Provider || got.EmbeddingDim != want.EmbeddingDim {
t.Errorf("round-trip lost data: got %+v want %+v", got, want)
}
}
func TestDriftDetector_LoadMissingReturnsZero(t *testing.T) {
d := NewDriftDetector(filepath.Join(t.TempDir(), "missing.json"))
got, err := d.LoadPrevious()
if err != nil {
t.Errorf("missing file should not error, got %v", err)
}
if got != (EmbedderFingerprint{}) {
t.Errorf("missing file should yield zero, got %+v", got)
}
}
func TestDriftDetector_EmptyPathSilent(t *testing.T) {
d := NewDriftDetector("")
if err := d.Save(EmbedderFingerprint{Provider: "x"}); err != nil {
t.Errorf("empty path Save should be no-op, got %v", err)
}
got, err := d.LoadPrevious()
if err != nil || got != (EmbedderFingerprint{}) {
t.Errorf("empty path LoadPrevious should return zero / nil, got %+v / %v", got, err)
}
}
func TestDriftDetector_Compare_EndToEnd(t *testing.T) {
dir := t.TempDir()
d := NewDriftDetector(filepath.Join(dir, "fp.json"))
// First compare: no previous record → no drift.
cur := EmbedderFingerprint{Provider: "hugot", Model: "A", EmbeddingDim: 384}
w, err := d.Compare(cur)
if err != nil {
t.Fatal(err)
}
if w.HasDrift() {
t.Error("first comparison should report no drift")
}
_ = d.Save(cur)
// Second compare with same fingerprint: still no drift.
w, _ = d.Compare(cur)
if w.HasDrift() {
t.Errorf("identical fingerprint should not drift, got %v", w.Changes)
}
// Change the model: should drift.
cur.Model = "B"
w, _ = d.Compare(cur)
if !w.HasDrift() {
t.Error("model change should drift")
}
}
func TestDefaultFingerprintPath(t *testing.T) {
got := DefaultFingerprintPath()
if got == "" {
// Acceptable when UserCacheDir is unavailable; just don't panic.
return
}
if filepath.Base(got) != "embedding-fingerprint.json" {
t.Errorf("default path basename = %q, want embedding-fingerprint.json", filepath.Base(got))
}
}
func contains(s, sub string) bool {
return len(s) >= len(sub) && (s == sub || stringsHasSubstring(s, sub))
}
func stringsHasSubstring(s, sub string) bool {
for i := 0; i+len(sub) <= len(s); i++ {
if s[i:i+len(sub)] == sub {
return true
}
}
return false
}
// Quiet "imported and not used" when the harness iterates the
// fingerprint file directly without going through DriftDetector.
var _ = os.Stat