package federation_test import ( "net/http" "net/http/httptest" "strings" "sync/atomic" "testing" "github.com/dariuszjaniak/warp/server/internal/federation" ) func TestGateFollowsTheSwitch(t *testing.T) { var enabled atomic.Bool gate := federation.NewGate(enabled.Load, nil) handler := gate.Protect(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })) rec := httptest.NewRecorder() handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/_matrix/federation/v1/version", nil)) if rec.Code != http.StatusNotFound { t.Fatalf("status = %d, want 404 while federation is off", rec.Code) } enabled.Store(true) rec = httptest.NewRecorder() handler.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/_matrix/federation/v1/version", nil)) if rec.Code != http.StatusOK { t.Fatalf("status = %d, want 200 once federation is on", rec.Code) } } func TestNilCallbackMeansDisabled(t *testing.T) { gate := federation.NewGate(nil, nil) if gate.Enabled() { t.Error("a gate without a switch must be closed") } } func TestPolicy(t *testing.T) { cases := []struct { name string allowlist []string denylist []string server string want bool }{ {"empty lists allow anything", nil, nil, "matrix.org", true}, {"denylist blocks", nil, []string{"evil.example"}, "evil.example", false}, {"denylist is case insensitive", nil, []string{"evil.example"}, "Evil.Example", false}, {"allowlist admits members", []string{"a.example"}, nil, "a.example", true}, {"allowlist excludes everyone else", []string{"a.example"}, nil, "b.example", false}, {"denylist wins over allowlist", []string{"a.example"}, []string{"a.example"}, "a.example", false}, {"empty server name is refused", nil, nil, "", false}, {"whitespace is trimmed", []string{"a.example"}, nil, " a.example ", true}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { p := federation.NewPolicy(tc.allowlist, tc.denylist) if got := p.Allowed(tc.server); got != tc.want { t.Errorf("Allowed(%q) = %v, want %v", tc.server, got, tc.want) } }) } } func TestPolicyReplace(t *testing.T) { p := federation.NewPolicy([]string{"a.example"}, nil) if !p.Allowed("a.example") { t.Fatal("a.example should be allowed") } p.Replace(nil, []string{"a.example"}) if p.Allowed("a.example") { t.Error("after Replace, a.example should be denied") } allow, deny := p.Lists() if len(allow) != 0 || len(deny) != 1 || deny[0] != "a.example" { t.Errorf("Lists() = %v, %v", allow, deny) } } func TestRejectClientRequestExplainsItself(t *testing.T) { err := federation.RejectClientRequest("joining a room on another server") if err == nil { t.Fatal("expected an error") } msg := err.Error() for _, want := range []string{"M_FORBIDDEN", "Federation is disabled", "joining a room"} { if !strings.Contains(msg, want) { t.Errorf("error %q should mention %q", msg, want) } } }