package federation
import (
"fmt"
"net/http"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/store"
)
func newTestStore(t *testing.T) *store.Store {
t.Helper()
s, err := store.Open(filepath.Join(t.TempDir(), "gitfed.db"))
if err != nil {
t.Fatalf("open store: %v", err)
}
t.Cleanup(func() { s.Close() })
if err := s.PutInstanceMeta(store.InstanceMeta{
Domain: "local.test",
TrustPolicy: store.TrustPolicyWhitelist,
}); err != nil {
t.Fatalf("put instance meta: %v", err)
}
return s
}
func TestEnsureTrustCachesKnownDomain(t *testing.T) {
var hits int
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hits++
domain := r.Host
fmt.Fprintf(w, `{"version":1,"domain":%q,"ca_public_key":"ssh-ed25519 AAAAfake"}`, domain)
}))
defer srv.Close()
domain := strings.TrimPrefix(srv.URL, "http://")
s := newTestStore(t)
r := NewResolver(s, "local.test", true /* insecure http, this is a test */)
t1, err := r.EnsureTrust(domain)
if err != nil {
t.Fatalf("first EnsureTrust: %v", err)
}
if t1.Status != store.TrustPending {
t.Errorf("status = %v, want pending (default policy is whitelist)", t1.Status)
}
if hits != 1 {
t.Fatalf("hits after first call = %d, want 1", hits)
}
srv.Close() // if EnsureTrust hits the network again, this proves it isn't cached
t2, err := r.EnsureTrust(domain)
if err != nil {
t.Fatalf("second EnsureTrust (should be served from cache): %v", err)
}
if t2.CAPublicKey != t1.CAPublicKey {
t.Errorf("cached record changed between calls: %+v vs %+v", t1, t2)
}
if hits != 1 {
t.Errorf("hits after second call = %d, want still 1 (cached, no re-fetch)", hits)
}
}
func TestEnsureTrustRateLimitsNewDomainDiscovery(t *testing.T) {
s := newTestStore(t)
r := NewResolver(s, "local.test", true)
// Nothing listens on 127.0.0.1:1, so every attempt fails fast and is
// never cached — each call re-consumes the discovery quota.
const unreachable = "127.0.0.1:1"
for i := 0; i < maxNewDomainDiscoveries; i++ {
if _, err := r.EnsureTrust(unreachable); err == nil {
t.Fatalf("attempt %d: expected a connection error, got nil", i)
} else if strings.Contains(err.Error(), "too many new-domain discovery attempts") {
t.Fatalf("attempt %d: rate limited too early: %v", i, err)
}
}
_, err := r.EnsureTrust(unreachable)
if err == nil {
t.Fatal("expected rate limit error on attempt past the quota, got nil")
}
if !strings.Contains(err.Error(), "too many new-domain discovery attempts") {
t.Fatalf("attempt past quota: got %v, want a rate-limit error", err)
}
}
func TestEnsureTrustRejectsLocalDomain(t *testing.T) {
s := newTestStore(t)
r := NewResolver(s, "local.test", true)
if _, err := r.EnsureTrust("local.test"); err == nil {
t.Fatal("expected an error resolving the local domain as federated, got nil")
}
}