package realtime import ( "net/http/httptest" "testing" ) func TestExtractToken(t *testing.T) { req := httptest.NewRequest("GET", "/ws", nil) req.Header.Set("Authorization", "Bearer abc") token, ok := extractToken(req) if !ok || token != "abc" { t.Fatalf("extractToken auth header = (%q, %v), want (abc, true)", token, ok) } req = httptest.NewRequest("GET", "/ws?token=q1", nil) token, ok = extractToken(req) if !ok || token != "q1" { t.Fatalf("extractToken token query = (%q, %v), want (q1, true)", token, ok) } req = httptest.NewRequest("GET", "/ws?access_token=q2", nil) token, ok = extractToken(req) if !ok || token != "q2" { t.Fatalf("extractToken access_token query = (%q, %v), want (q2, true)", token, ok) } } func TestParseSinceCursor(t *testing.T) { req := httptest.NewRequest("GET", "/ws?since=42", nil) if got := parseSinceCursor(req); got != 42 { t.Fatalf("parseSinceCursor() = %d, want 42", got) } req = httptest.NewRequest("GET", "/ws?since=bad", nil) if got := parseSinceCursor(req); got != 0 { t.Fatalf("parseSinceCursor() invalid = %d, want 0", got) } } func TestTokenSessionKeyStable(t *testing.T) { a := tokenSessionKey("same-token") b := tokenSessionKey("same-token") c := tokenSessionKey("other-token") if a != b { t.Fatalf("session keys for same token differ: %q != %q", a, b) } if a == c { t.Fatalf("session keys for different tokens should differ") } } func TestRegisterRespectsLimits(t *testing.T) { h := NewHub(nil, nil) h.SetLimits(2, 1, 10) c1 := &conn{userID: "u1", sessionKey: "s1"} c2 := &conn{userID: "u1", sessionKey: "s2"} c3 := &conn{userID: "u1", sessionKey: "s3"} if err := h.register(c1); err != nil { t.Fatalf("register c1 error = %v", err) } if err := h.register(c2); err != nil { t.Fatalf("register c2 error = %v", err) } if err := h.register(c3); err == nil { t.Fatalf("register c3 expected user limit error") } h2 := NewHub(nil, nil) h2.SetLimits(5, 1, 10) if err := h2.register(&conn{userID: "u1", sessionKey: "s1"}); err != nil { t.Fatalf("register first session conn error = %v", err) } if err := h2.register(&conn{userID: "u1", sessionKey: "s1"}); err == nil { t.Fatalf("register second session conn expected session limit error") } } func TestBroadcastAssignsSequenceAndKeepsReplayBuffer(t *testing.T) { h := NewHub(nil, nil) h.SetLimits(10, 10, 2) h.Broadcast("u1", NewMailCreatedEvent("m1", "a1")) h.Broadcast("u1", NewMailUpdatedEvent("m2", "a1")) h.Broadcast("u1", NewMailDeletedEvent("m3", "a1")) if head := h.HistoryHead("u1"); head != 3 { t.Fatalf("HistoryHead() = %d, want 3", head) } if len(h.history["u1"]) != 2 { t.Fatalf("history length = %d, want 2", len(h.history["u1"])) } if h.history["u1"][0].Seq != 2 || h.history["u1"][1].Seq != 3 { t.Fatalf("history seqs = [%d, %d], want [2, 3]", h.history["u1"][0].Seq, h.history["u1"][1].Seq) } }