Single-package agentidp SDK in sdk-go/: - AgentIdPClient composing AgentRegistryClient, CredentialClient, TokenServiceClient, AuditClient — all 14 endpoints covered - Goroutine-safe TokenManager (sync.Mutex) with 60s refresh buffer - AgentIdPError implementing error interface with Code/HTTPStatus/Details - Context-aware: all service methods take context.Context as first arg - doRequest shared helper; token endpoints use form-encoded POST directly - go vet: 0 warnings | staticcheck: 0 warnings - go test ./...: 37/37 passed | coverage: 81.0% (>80% gate) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
125 lines
3.6 KiB
Go
125 lines
3.6 KiB
Go
package agentidp
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// integrationServer returns a minimal mock server that handles the token endpoint
|
|
// plus a provided handler for all other routes.
|
|
func integrationServer(t *testing.T, handler http.HandlerFunc) *httptest.Server {
|
|
t.Helper()
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/api/v1/token", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"access_token": "integration-token",
|
|
"token_type": "Bearer",
|
|
"expires_in": 3600,
|
|
"scope": "agents:read agents:write tokens:read audit:read",
|
|
})
|
|
})
|
|
mux.HandleFunc("/", handler)
|
|
return httptest.NewServer(mux)
|
|
}
|
|
|
|
func TestNewAgentIdPClient_GetAgent(t *testing.T) {
|
|
srv := integrationServer(t, func(w http.ResponseWriter, r *http.Request) {
|
|
if !strings.HasPrefix(r.URL.Path, "/api/v1/agents/") {
|
|
t.Errorf("unexpected path: %s", r.URL.Path)
|
|
}
|
|
if r.Header.Get("Authorization") != "Bearer integration-token" {
|
|
t.Errorf("unexpected Authorization: %q", r.Header.Get("Authorization"))
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(mockAgent)
|
|
})
|
|
defer srv.Close()
|
|
|
|
client := NewAgentIdPClient(AgentIdPClientConfig{
|
|
BaseURL: srv.URL,
|
|
ClientID: "cid",
|
|
ClientSecret: "secret",
|
|
})
|
|
|
|
agent, err := client.Agents.GetAgent(context.Background(), "uuid-1")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if agent.AgentID != "uuid-1" {
|
|
t.Errorf("expected uuid-1, got %q", agent.AgentID)
|
|
}
|
|
}
|
|
|
|
func TestNewAgentIdPClient_ClearTokenCache(t *testing.T) {
|
|
callCount := 0
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/api/v1/token" {
|
|
callCount++
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"access_token": "tok",
|
|
"token_type": "Bearer",
|
|
"expires_in": 3600,
|
|
"scope": "agents:read",
|
|
})
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(mockAgent)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := NewAgentIdPClient(AgentIdPClientConfig{
|
|
BaseURL: srv.URL,
|
|
ClientID: "cid",
|
|
ClientSecret: "secret",
|
|
})
|
|
|
|
_, _ = client.Agents.GetAgent(context.Background(), "uuid-1")
|
|
client.ClearTokenCache()
|
|
_, _ = client.Agents.GetAgent(context.Background(), "uuid-1")
|
|
|
|
if callCount != 2 {
|
|
t.Errorf("expected 2 token fetches after ClearTokenCache, got %d", callCount)
|
|
}
|
|
}
|
|
|
|
func TestNewAgentIdPClient_DefaultScope(t *testing.T) {
|
|
var capturedScope string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/api/v1/token" {
|
|
_ = r.ParseForm()
|
|
capturedScope = r.FormValue("scope")
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"access_token": "tok",
|
|
"token_type": "Bearer",
|
|
"expires_in": 3600,
|
|
"scope": capturedScope,
|
|
})
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(mockAgent)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := NewAgentIdPClient(AgentIdPClientConfig{
|
|
BaseURL: srv.URL,
|
|
ClientID: "cid",
|
|
ClientSecret: "secret",
|
|
// Scope intentionally omitted → defaults applied
|
|
})
|
|
_, _ = client.Agents.GetAgent(context.Background(), "uuid-1")
|
|
|
|
expected := "agents:read agents:write tokens:read audit:read"
|
|
if capturedScope != expected {
|
|
t.Errorf("expected scope %q, got %q", expected, capturedScope)
|
|
}
|
|
}
|