package adminrpc
import (
"path/filepath"
"testing"
"time"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/admin"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/ca"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/federation"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/store"
)
// TestErrNotFoundSurvivesRPC reproduces a real bug: the wire only carries
// error strings, so a naive client just wrapping resp.Error in a fresh
// errors.New produces a value that will never compare equal to
// store.ErrNotFound — breaking every `err == store.ErrNotFound` check
// downstream (this exact thing 500'd gitfed-web's repo settings page,
// since GetACL on a repo with no collaborators yet returns ErrNotFound).
func TestErrNotFoundSurvivesRPC(t *testing.T) {
dir := t.TempDir()
st, err := store.Open(filepath.Join(dir, "gitfed.db"))
if err != nil {
t.Fatalf("open store: %v", err)
}
defer st.Close()
localCA, err := ca.LoadOrCreate(filepath.Join(dir, "ca"))
if err != nil {
t.Fatalf("load CA: %v", err)
}
a := admin.New(st, federation.NewResolver(st, "local.test", true), "local.test", dir, localCA)
if err := a.CreateRepo("alice/demo", "alice"); err != nil {
t.Fatalf("create repo: %v", err)
}
// No collaborators granted, so the ACL bucket has no entry for this
// repo — GetACL is expected to return store.ErrNotFound.
socketPath := filepath.Join(dir, "admin.sock")
srv := NewServer(a, socketPath)
go func() { _ = srv.ListenAndServe() }()
client := NewClient(socketPath)
deadline := time.Now().Add(2 * time.Second)
for {
if client.Ping() == nil {
break
}
if time.Now().After(deadline) {
t.Fatal("server never came up")
}
time.Sleep(10 * time.Millisecond)
}
_, err = client.GetACL("alice/demo")
if err == nil {
t.Fatal("expected store.ErrNotFound, got nil")
}
if err != store.ErrNotFound {
t.Fatalf("got error %q (%T), want the exact store.ErrNotFound sentinel — identity was lost crossing the RPC boundary", err, err)
}
}