Documentation
¶
Overview ¶
Package testutil has helpers shared by tests: isolated config/cache/data dirs, in-process command runs, and golden files.
Index ¶
- Constants
- Variables
- func APIError(code int, message string) map[string]any
- func AuthorizeRedirect(authURL string) (string, error)
- func EnterpriseChunk(offset string, songs ...map[string]any) map[string]any
- func EnterpriseSong(artist, title string, startMS, endMS int) map[string]any
- func FollowAuthorize(authURL string) error
- func Golden(t testing.TB, name string, got []byte)
- func Isolate(t testing.TB) string
- func LiveFixture(tool string) map[string]any
- func MatchResult() map[string]any
- func ReleaseArchive(t testing.TB, version string, bin []byte) (name string, archive, checksums []byte)
- func Success(result any) map[string]any
- type FakeAPI
- type FakeHandler
- type FakeMCP
- type FakeMCPCall
- type FakeOAuth
- func (f *FakeOAuth) AccessScopes(token string) ([]string, bool)
- func (f *FakeOAuth) DropAccess()
- func (f *FakeOAuth) ForgetClients()
- func (f *FakeOAuth) HasRefresh(token string) bool
- func (f *FakeOAuth) IssueAccess(scopes ...string) string
- func (f *FakeOAuth) IssueSession(clientID string, scopes ...string) (access, refresh string)
- func (f *FakeOAuth) RegisterClient(scopes ...string) string
- func (f *FakeOAuth) RequestedClientIDs() []string
- func (f *FakeOAuth) RequestedScopes() []string
- func (f *FakeOAuth) RestrictClient(id string, scopes ...string)
- func (f *FakeOAuth) RevocationRequests() []Revocation
- func (f *FakeOAuth) RevokeAll()
- func (f *FakeOAuth) RevokedTokens() []string
- func (f *FakeOAuth) Set(fn func(f *FakeOAuth))
- func (f *FakeOAuth) Snapshot() FakeOAuthCounters
- func (f *FakeOAuth) URL() string
- type FakeOAuthCounters
- type FakeRequest
- type FakeTool
- type Main
- type Result
- type Revocation
Constants ¶
const ( EndpointRecognize = "recognize" // POST https://api.audd.io/ EndpointEnterprise = "enterprise" // POST https://enterprise.audd.io/ EndpointUpload = "upload" // POST https://api.audd.io/upload/ )
Endpoints of the fake API. Any other path is a raw method name, such as "getStreams".
const FakeAPIToken = PlaceholderToken
FakeAPIToken is the account API token the fake MCP server hands out.
const FakePaymentURL = "https://checkout.stripe.com/c/pay/cs_test_example"
FakePaymentURL is the link the fake payment tools return.
const FakeRotatedToken = "your-api-token"
FakeRotatedToken is the token rotate_api_token returns: the other allowed placeholder, so tests can tell the old and new tokens apart.
const FirstPartyClientID = "audd-cli"
FirstPartyClientID is AudD's pre-registered CLI client.
const PlaceholderToken = "0123456789abcdef0123456789abcdef"
PlaceholderToken is the only token value tests and docs use.
Variables ¶
var DefaultGrantScopes = []string{"openid", "profile:read", "account:read", "usage:read", "billing:read", "token:read"}
DefaultGrantScopes are granted to a client registered without a scope list: like the AudD service, they leave out billing:pay and token:write.
var FirstPartyScopes = []string{"openid", "email", "profile:read", "account:read", "usage:read", "billing:read", "billing:pay", "token:read", "token:write"}
FirstPartyScopes are the scopes audd-cli may ask for.
var LiveInputSchemas, FakeOutputSchemas = func() (in, out map[string]map[string]any) {
in, out = map[string]map[string]any{}, map[string]map[string]any{}
for name, t := range liveTools() {
in[name], out[name] = t.InputSchema, t.OutputSchema
}
in["rotate_api_token"] = in["get_api_token"]
out["rotate_api_token"] = out["get_api_token"]
return in, out
}()
LiveInputSchemas and FakeOutputSchemas are the account tools' schemas as the live server publishes them. rotate_api_token was not in the recording (it is listed only with token:write); it is assumed to answer like get_api_token.
Functions ¶
func AuthorizeRedirect ¶
AuthorizeRedirect requests the authorization URL without following the redirect and returns the redirect URL (what a user would paste).
func EnterpriseChunk ¶
EnterpriseChunk is one chunk of an enterprise response.
func EnterpriseSong ¶
EnterpriseSong is one enterprise match inside a chunk.
func FollowAuthorize ¶
FollowAuthorize plays the user's browser: it requests the authorization URL and follows the redirect to the CLI's loopback listener. Use it as the browser opener in tests.
func Golden ¶
Golden compares got with testdata/<name>.golden next to the test. Run tests with AUDD_UPDATE_GOLDEN=1 to rewrite the files.
func Isolate ¶
Isolate points config, cache, and data dirs at fresh temp dirs, forces the file-based secrets store, and clears environment variables that change CLI behavior. It returns the config dir.
func LiveFixture ¶
LiveFixture returns the structuredContent of a recorded tools/call response, freshly decoded (callers may change it).
func MatchResult ¶
MatchResult is a typical standard-endpoint match.
Types ¶
type FakeAPI ¶
FakeAPI is an httptest server that stands in for api.audd.io and enterprise.audd.io. NewFakeAPI points the CLI at it through the AUDD_API_BASE_URL and AUDD_ENTERPRISE_BASE_URL environment variables.
func NewFakeAPI ¶
NewFakeAPI starts a fake API for the test. Unhandled endpoints answer with error 1000 (unknown method).
func (*FakeAPI) AcceptTokens ¶
AcceptTokens limits the tokens the fake accepts; others get error 900.
func (*FakeAPI) On ¶
func (f *FakeAPI) On(endpoint string, h FakeHandler)
On sets the handler for an endpoint (EndpointRecognize, EndpointEnterprise, EndpointUpload, or a raw method name).
func (*FakeAPI) Requests ¶
func (f *FakeAPI) Requests() []FakeRequest
Requests returns every request received so far.
type FakeHandler ¶
type FakeHandler func(r FakeRequest) (status int, body any)
FakeHandler answers a request with an HTTP status and a JSON body.
type FakeMCP ¶
type FakeMCP struct {
Server *httptest.Server
OAuth *FakeOAuth
SSE bool // answer requests as text/event-stream
Calls []FakeMCPCall
Inits int
Lists int
// contains filtered or unexported fields
}
FakeMCP is a Streamable HTTP MCP server for tests. It checks bearer tokens against a FakeOAuth, issues Mcp-Session-Id on initialize, rejects unknown sessions with 404, scopes tools like the AudD MCP server, and can answer as JSON or as an SSE stream.
func NewFakeMCP ¶
NewFakeMCP starts a fake MCP server using oauth for tokens, with the default AudD account tools (see DefaultFakeTools).
func (*FakeMCP) CallsTo ¶
func (f *FakeMCP) CallsTo(name string) []FakeMCPCall
CallsTo returns the recorded calls to a tool.
func (*FakeMCP) ExpireSessions ¶
func (f *FakeMCP) ExpireSessions()
ExpireSessions forgets every session, as a server restart would.
type FakeMCPCall ¶
FakeMCPCall records one tools/call.
type FakeOAuth ¶
type FakeOAuth struct {
Server *httptest.Server
// Behavior knobs; set before the flow starts.
IssOverride string // iss sent on the redirect ("" = the real issuer)
OmitIss bool // leave iss off the redirect
StateOverride string // state sent on the redirect ("" = echo)
DenyScopes []string // scopes the server refuses with invalid_scope
// RejectRegistrationScope refuses registrations that name a scope list
// (invalid_client_metadata); clients registered without one get
// DefaultGrantScopes.
RejectRegistrationScope bool
AccessTTL time.Duration // access token lifetime (default 1h)
RefreshDelay time.Duration // slow down refresh responses
// NoFirstPartyClient models a server that does not know audd-cli.
NoFirstPartyClient bool
// NoDeviceEndpoint leaves device authorization out of the metadata.
NoDeviceEndpoint bool
// Untick lists scopes the user unticks on the consent or approval
// screen: they are left out of the grant.
Untick []string
// DeviceScript is the answer to each device poll in turn: "pending",
// "slow_down", "slow_down_429" (429 with no interval), "deny",
// "expire", "invalid_grant", or "approve". After the script, polls
// are approved.
DeviceScript []string
// DeviceInterval and DeviceExpiresIn are sent with each device code
// (default 5 and 900, like AudD's server).
DeviceInterval, DeviceExpiresIn int
// DeviceRetryAfter, when set, answers device authorization with 429
// and this Retry-After.
DeviceRetryAfter int
// RegisterReturns makes registration answer with this client_id
// without creating a client (AudD's answer to an "AudD CLI"
// registration is audd-cli itself).
RegisterReturns string
// RegisterError refuses registrations with 400 and this error code.
RegisterError, RegisterErrorDescription string
Counters FakeOAuthCounters
Revoked []string
// Revocations lists each revocation request.
Revocations []Revocation
// Scopes lists the scope parameter of each authorization and device
// authorization request, in order.
Scopes []string
// ClientIDs lists the client_id of each authorization and device
// authorization request, in order.
ClientIDs []string
// contains filtered or unexported fields
}
FakeOAuth is an OAuth 2.0 authorization server for tests, shaped like AudD's: RFC 8414 metadata, the pre-registered public client audd-cli, dynamic client registration, an /authorize endpoint that approves immediately (a 302 to the client's redirect URI), device authorization (RFC 8628) whose polls follow DeviceScript, a token endpoint with PKCE checks and single-use rotating refresh tokens, and a revocation endpoint that only revokes for the issuing client.
func NewFakeOAuth ¶
NewFakeOAuth starts a fake authorization server; it stops when the test ends.
func (*FakeOAuth) AccessScopes ¶
AccessScopes returns the scopes of a valid access token.
func (*FakeOAuth) DropAccess ¶
func (f *FakeOAuth) DropAccess()
DropAccess invalidates every access token but keeps refresh tokens, as when the server revokes access tokens early.
func (*FakeOAuth) ForgetClients ¶
func (f *FakeOAuth) ForgetClients()
ForgetClients drops every registered client, as when the server no longer knows a client ID the CLI cached.
func (*FakeOAuth) HasRefresh ¶
HasRefresh reports whether a refresh token is still valid.
func (*FakeOAuth) IssueAccess ¶
IssueAccess mints an access token directly (for MCP tests that skip login).
func (*FakeOAuth) IssueSession ¶
IssueSession mints a session for clientID directly, as a sign-in by an earlier version would have, and returns its access and refresh tokens.
func (*FakeOAuth) RegisterClient ¶
RegisterClient adds a registered client, as an earlier sign-in would have.
func (*FakeOAuth) RequestedClientIDs ¶
RequestedClientIDs returns the client_id of each authorization and device authorization request.
func (*FakeOAuth) RequestedScopes ¶
RequestedScopes returns the scope parameter of each authorization and device authorization request.
func (*FakeOAuth) RestrictClient ¶
RestrictClient limits the scopes a registered client may ask for.
func (*FakeOAuth) RevocationRequests ¶
func (f *FakeOAuth) RevocationRequests() []Revocation
RevocationRequests returns each revocation request.
func (*FakeOAuth) RevokeAll ¶
func (f *FakeOAuth) RevokeAll()
RevokeAll invalidates every access and refresh token (an ended session).
func (*FakeOAuth) RevokedTokens ¶
RevokedTokens returns tokens sent to the revocation endpoint.
func (*FakeOAuth) Snapshot ¶
func (f *FakeOAuth) Snapshot() FakeOAuthCounters
Snapshot returns a copy of the counters.
type FakeOAuthCounters ¶
type FakeOAuthCounters struct {
Register, Authorize, CodeExchange, Refresh, RefreshRejected, Revoke int
// DeviceAuthorize counts device authorization requests, DevicePoll
// device-code token requests, DeviceSuccess polls answered 200, and
// DevicePollAfterSuccess polls for a code that was already redeemed.
DeviceAuthorize, DevicePoll, DeviceSuccess, DevicePollAfterSuccess int
}
FakeOAuthCounters counts requests per endpoint.
type FakeRequest ¶
type FakeRequest struct {
Endpoint string
Token string
Form map[string]string // form fields except api_token and file
FileName string
FileSize int // bytes of the uploaded file; -1 when no file was sent
}
FakeRequest is one request the fake API received.
type FakeTool ¶
type FakeTool struct {
Name string
Scope string // tool is listed and callable only with this scope
InputSchema map[string]any
OutputSchema map[string]any
// Handle returns structuredContent (nil for text-only), text, and isError.
Handle func(args map[string]any) (structured map[string]any, text string, isError bool)
}
FakeTool is one tool served by FakeMCP.
func DefaultFakeTools ¶
func DefaultFakeTools() []FakeTool
DefaultFakeTools returns the AudD account tools with the live schemas and the recorded results.
type Main ¶
Main is the signature of cli.Main; tests pass it in, which keeps this package free of a dependency on internal/cli.
type Revocation ¶
type Revocation struct{ Token, ClientID string }
Revocation is one request to the revocation endpoint.