agentproxytest

package
v1.166.0-beta.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package agentproxytest fakes the DigitalOcean Hosted Agents session HTTP API (see github.com/digitalocean/godo's hosted_agents.go) behind an httptest.Server, so agentproxy tests can drive a real do.HostedAgentsService end to end without a live harness backend.

Nothing outside this package's own tests (or other packages' _test.go files) should ever import it: it's test scaffolding, not production code, even though it lives in an ordinary buildable package rather than a _test.go file — that's what lets other packages' tests (e.g. internal/agentproxy/codex's) import it across package boundaries.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Event

type Event struct {
	// Type is the wire "type" discriminator, e.g. "run.started",
	// "run.token_delta", "run.completed", "run.failed".
	Type string
	// Data is the event-specific payload. A nil Data marshals as "{}".
	Data json.RawMessage
	// WaitForHITL, if set, blocks this event (and every one after it) from
	// being sent until handleHITL records a resolution for this hitl_id.
	// Needed for any test where a queued event (e.g. run.tool_call_completed
	// for a gated call) must not be observed to happen before the HITL that
	// gates it is actually resolved: naively pre-queuing every event with no
	// gating, the way QueueRun otherwise works, races a Facade's
	// asynchronous approval-handling goroutine instead of modeling the real
	// harness's behavior of only continuing a gated run after the decision
	// arrives.
	WaitForHITL string
	// RunID overrides the run id this event is tagged with, for
	// QueueReplayHistory only: replayed history can span several distinct
	// past runs, unlike QueueRun's single live run sharing one runID for its
	// whole queue. Empty means "use the harness's current runID," which is
	// all QueueRun ever needs.
	RunID string
}

Event is one canned SSE event the harness streams back from GET /v2/agents/sessions/{id}/stream, matching the event-specific part of godo.HostedAgentEvent's wire shape (see HostedAgentEventKind's doc comment for the canonical type strings).

type HITLResolution

type HITLResolution struct {
	RequestID string
	Outcome   string
	Reason    string
	Source    string
}

HITLResolution is one POST .../hitl/{requestID} call the harness received, recorded so a test can assert not just that ResolveHITL was called, but that it resolved the right request with the right outcome.

type Harness

type Harness struct {
	Server *httptest.Server
	// contains filtered or unexported fields
}

Harness fakes the four Hosted Agents session routes an agentproxy test needs: session lookup, SSE stream, send-input, and HITL resolve. Point a *godo.Client at it with godo.SetBaseURL(h.Server.URL+"/") — do's NewHostedAgentsService wraps that client directly, so a Facade built against it talks to this harness exactly as it would a real backend.

func New

func New(t *testing.T, sessionID string) *Harness

New starts the fake harness and registers its shutdown via t.Cleanup. sessionID is the session id every route responds under — a test's Facade.SessionID should match it.

func (*Harness) DropConnectionAfterEvents

func (h *Harness) DropConnectionAfterEvents(n int)

DropConnectionAfterEvents makes the very next GET .../stream call return after sending only the first n queued events (a clean end, no error — exactly how a genuine mid-stream drop/idle-timeout looks from the client's side) instead of the whole list, then resets to 0 so any later connection serves normally. One-shot: simulates a real drop-and-resume for a test verifying a reconnect actually resumes (via replay_from) and dedups whatever prefix gets redelivered, rather than only ever seeing a stream that's already run to completion.

func (*Harness) ExpectNoHITLResolution

func (h *Harness) ExpectNoHITLResolution(t *testing.T, wait time.Duration)

ExpectNoHITLResolution asserts no POST .../hitl call arrives within wait — used by --replay tests to confirm historical HITLs are not re-resolved.

func (*Harness) HangStreamAfterEvents

func (h *Harness) HangStreamAfterEvents(hang bool)

HangStreamAfterEvents controls whether handleStream blocks on the request's context after sending all queued events instead of returning immediately once they're exhausted (the default). Needed for tests that must distinguish "the stream ended because ctx was canceled" from "the stream ended because it ran out of pre-queued events" — the latter would happen regardless of whether a connection-lifecycle fix actually works.

func (*Harness) NextHITLResolution

func (h *Harness) NextHITLResolution(t *testing.T, timeout time.Duration) HITLResolution

NextHITLResolution blocks (up to timeout) for the next POST .../hitl call the harness received, failing the test rather than hanging the suite if none arrives — same discipline as notifierRecorder.next in the codex package's tests.

func (*Harness) QueueReplayHistory

func (h *Harness) QueueReplayHistory(events ...Event)

QueueReplayHistory arranges for a GET .../stream call carrying replay_only=true to return these events instead of whatever QueueRun set up, then end — mirrors harness-api's own handleStreamSession, which never continues a replay_only request into a live tail (see streamsvc.Service.SubscribeEvents). Each event's own RunID is used as-is (unlike QueueRun's events, which all share one runID), since replayed history can span several distinct past runs.

func (*Harness) QueueRun

func (h *Harness) QueueRun(runID string, events ...Event)

QueueRun arranges for the next POST .../input call to return runID, and for GET .../stream to then emit events (in order, tagged with runID), flushing after each one so a concurrent reader observes them incrementally rather than all at once at EOF.

One (runID, events) pair is enough for a single-turn sequence test; queue again before the next turn/start if a future test drives more than one turn over the same harness.

func (*Harness) SetStreamErrorStatus

func (h *Harness) SetStreamErrorStatus(status, times int)

SetStreamErrorStatus makes GET .../stream return status immediately (instead of opening an SSE stream) for the next `times` calls, then resume normal behavior (serving whatever's queued via QueueRun) — simulating a StreamSession failure rather than a mid-stream drop. times <= 0 means permanent: every call fails until this is changed again — for a test verifying a terminal error (401/403/404/409) makes the caller give up immediately, with no retries. times > 0 fails exactly that many calls before clearing automatically — for a test verifying reconnect-with-backoff actually recovers after N transient failures.

func (*Harness) SetStreamErrorStatusAfter

func (h *Harness) SetStreamErrorStatusAfter(skip, status, times int)

SetStreamErrorStatusAfter is SetStreamErrorStatus, but the first `skip` stream opens succeed normally before the injected failures begin. Needed once turn/start opens the stream synchronously before SendInput (ensureEventLoop): a reconnect-path test must let that first attach succeed, then fail subsequent opens, rather than failing turn/start itself.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL