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>
86 lines
2.5 KiB
Go
86 lines
2.5 KiB
Go
package agentidp
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestAgentIdPError_Error(t *testing.T) {
|
|
err := &AgentIdPError{Code: "AgentNotFoundError", Message: "Agent not found.", HTTPStatus: 404}
|
|
if err.Error() != "Agent not found." {
|
|
t.Errorf("expected 'Agent not found.', got %q", err.Error())
|
|
}
|
|
}
|
|
|
|
func TestParseAPIError_ValidBody(t *testing.T) {
|
|
body := []byte(`{"code":"AgentNotFoundError","message":"Not found.","details":{"id":"x"}}`)
|
|
err := parseAPIError(body, 404)
|
|
if err.Code != "AgentNotFoundError" {
|
|
t.Errorf("expected code AgentNotFoundError, got %q", err.Code)
|
|
}
|
|
if err.HTTPStatus != 404 {
|
|
t.Errorf("expected status 404, got %d", err.HTTPStatus)
|
|
}
|
|
if err.Details == nil {
|
|
t.Error("expected non-nil Details")
|
|
}
|
|
}
|
|
|
|
func TestParseAPIError_UnparseableBody(t *testing.T) {
|
|
err := parseAPIError([]byte("not json"), 500)
|
|
if err.Code != "UNKNOWN_ERROR" {
|
|
t.Errorf("expected UNKNOWN_ERROR, got %q", err.Code)
|
|
}
|
|
if err.HTTPStatus != 500 {
|
|
t.Errorf("expected 500, got %d", err.HTTPStatus)
|
|
}
|
|
}
|
|
|
|
func TestParseAPIError_EmptyCode(t *testing.T) {
|
|
// Valid JSON but no "code" field → falls back to UNKNOWN_ERROR
|
|
err := parseAPIError([]byte(`{"message":"oops"}`), 503)
|
|
if err.Code != "UNKNOWN_ERROR" {
|
|
t.Errorf("expected UNKNOWN_ERROR, got %q", err.Code)
|
|
}
|
|
}
|
|
|
|
func TestParseOAuth2Error_ValidBody(t *testing.T) {
|
|
body := []byte(`{"error":"invalid_client","error_description":"Bad credentials."}`)
|
|
err := parseOAuth2Error(body, 401)
|
|
if err.Code != "invalid_client" {
|
|
t.Errorf("expected invalid_client, got %q", err.Code)
|
|
}
|
|
if err.Message != "Bad credentials." {
|
|
t.Errorf("expected 'Bad credentials.', got %q", err.Message)
|
|
}
|
|
if err.HTTPStatus != 401 {
|
|
t.Errorf("expected 401, got %d", err.HTTPStatus)
|
|
}
|
|
}
|
|
|
|
func TestParseOAuth2Error_UnparseableBody(t *testing.T) {
|
|
err := parseOAuth2Error([]byte("garbage"), 400)
|
|
if err.Code != "UNKNOWN_ERROR" {
|
|
t.Errorf("expected UNKNOWN_ERROR, got %q", err.Code)
|
|
}
|
|
}
|
|
|
|
func TestNewNetworkError(t *testing.T) {
|
|
cause := &testError{msg: "connection refused"}
|
|
err := newNetworkError(cause)
|
|
if err.Code != "NETWORK_ERROR" {
|
|
t.Errorf("expected NETWORK_ERROR, got %q", err.Code)
|
|
}
|
|
if err.HTTPStatus != 0 {
|
|
t.Errorf("expected HTTPStatus 0, got %d", err.HTTPStatus)
|
|
}
|
|
if !strings.Contains(err.Message, "connection refused") {
|
|
t.Errorf("expected message to contain 'connection refused', got %q", err.Message)
|
|
}
|
|
}
|
|
|
|
// testError is a simple error implementation for testing.
|
|
type testError struct{ msg string }
|
|
|
|
func (e *testError) Error() string { return e.msg }
|