Files
sherlock/internal/broker/methods_test.go
T
amacocian fe71a4e60c
CI / build (push) Successful in 1m5s
Code fixes
2026-05-25 09:51:14 +02:00

111 lines
2.9 KiB
Go

package broker
import (
"context"
"encoding/json"
"testing"
"time"
"gitea.alexandru.macocian.me/Charlie/sherlock/internal/authn"
"gitea.alexandru.macocian.me/Charlie/sherlock/internal/keyring"
fakekeyring "gitea.alexandru.macocian.me/Charlie/sherlock/internal/keyring/fake"
"gitea.alexandru.macocian.me/Charlie/sherlock/internal/rpc"
)
func newMethods(t *testing.T) *Methods {
t.Helper()
return &Methods{
Store: fakekeyring.New(),
Cfg: authn.Config{},
AgentNames: func() []string { return []string{"copilot"} },
}
}
func TestStatus_NotLoggedIn(t *testing.T) {
m := newMethods(t)
res, rpcErr := m.handleStatus(context.Background(), nil)
if rpcErr != nil {
t.Fatalf("rpc err: %v", rpcErr)
}
s := res.(StatusResult)
if s.LoggedIn {
t.Fatal("expected not logged in")
}
if s.AuthnConfigured {
t.Fatal("expected not configured")
}
if len(s.Agents) != 1 || s.Agents[0] != "copilot" {
t.Fatalf("agents = %v", s.Agents)
}
}
func TestStatus_LoggedIn(t *testing.T) {
m := newMethods(t)
exp := time.Now().Add(time.Hour).UTC().Truncate(time.Second)
if err := m.Store.SetAuthentikTokens(keyring.TokenSet{
IDToken: "id", Subject: "alice", Email: "a@e", Name: "Alice",
IDExpiresAt: exp, Issuer: "https://id.example/",
}); err != nil {
t.Fatal(err)
}
res, rpcErr := m.handleStatus(context.Background(), nil)
if rpcErr != nil {
t.Fatalf("rpc err: %v", rpcErr)
}
s := res.(StatusResult)
if !s.LoggedIn || s.Subject != "alice" {
t.Fatalf("got %+v", s)
}
if s.IDExpiresAt == nil || !s.IDExpiresAt.Equal(exp) {
t.Fatalf("expiry: got %v want %v", s.IDExpiresAt, exp)
}
}
func TestWhoami_NotLoggedIn(t *testing.T) {
m := newMethods(t)
_, rpcErr := m.handleWhoami(context.Background(), nil)
if rpcErr == nil || rpcErr.Code != rpc.CodeNotLoggedIn {
t.Fatalf("want not_logged_in, got %+v", rpcErr)
}
}
func TestLoginStart_NotConfigured(t *testing.T) {
m := newMethods(t)
_, rpcErr := m.handleLoginStart(context.Background(), nil)
if rpcErr == nil || rpcErr.Code != rpc.CodeNotConfigured {
t.Fatalf("want not_configured, got %+v", rpcErr)
}
}
func TestLogout_Idempotent(t *testing.T) {
m := newMethods(t)
if _, err := m.handleLogout(context.Background(), nil); err != nil {
t.Fatalf("logout1: %v", err)
}
if _, err := m.handleLogout(context.Background(), nil); err != nil {
t.Fatalf("logout2: %v", err)
}
}
func TestShutdown_InvokesFn(t *testing.T) {
done := make(chan struct{})
m := newMethods(t)
m.ShutdownFn = func() { close(done) }
if _, err := m.handleShutdown(context.Background(), nil); err != nil {
t.Fatalf("shutdown: %v", err)
}
select {
case <-done:
case <-time.After(time.Second):
t.Fatal("ShutdownFn not invoked")
}
}
func TestLoginWait_BadParams(t *testing.T) {
m := newMethods(t)
_, rpcErr := m.handleLoginWait(context.Background(), json.RawMessage(`{}`))
if rpcErr == nil || rpcErr.Code != rpc.CodeBadRequest {
t.Fatalf("want bad_request, got %+v", rpcErr)
}
}