httpmock

package
v1.229.0 Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Overview

Package httpmock provides small, in-process mock HTTP servers standing in for GitHub (and GitHub-adjacent services like Artifactory) in tests, so the acceptance and unit-test suites never depend on live network access.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildTarGz added in v1.229.0

func BuildTarGz(files map[string]string) ([]byte, error)

BuildTarGz builds a minimal gzip-compressed tar archive containing files (archive path -> content), suitable for registering as a fake release asset via RegisterReleaseAsset or RegisterArchive. The result is a tiny stand-in for a real tool's release tarball: tests should assert atmos extracted/placed a file at the expected path, never execute it. Entries are written in sorted name order so identical inputs always produce identical archive bytes.

func BuildZip added in v1.229.0

func BuildZip(files map[string]string) ([]byte, error)

BuildZip builds a minimal zip archive containing files (archive path -> content), suitable for registering as a fake release asset via RegisterReleaseAsset. See BuildTarGz for the "never execute the fake binary" caveat and the sorted-write-order determinism rationale.

func IsolatedCacheEnv added in v1.229.0

func IsolatedCacheEnv(t *testing.T) []string

IsolatedCacheEnv returns environment entries that point atmos's XDG cache and data directories at a private temp dir for a subprocess driven against this mock. Without it, a subprocess `atmos toolchain install` fetches the mock's aqua registry index and installs the mock's fake release asset into the developer's REAL ~/.cache/atmos/toolchain, poisoning the registry index cache (24h TTL) and the toolchain bin directory for every atmos invocation on that machine until they expire or are removed. Append the result to cmd.Env alongside EnvForSubprocess.

Types

type AquaTool added in v1.229.0

type AquaTool struct {
	// Owner is repo_owner; Repo is repo_name.
	Owner string
	Repo  string
	// Name is the full registry package path (e.g. "jqlang/jq", or "kubernetes/kubernetes/kubectl"
	// for a monorepo binary). Defaults to "Owner/Repo" when empty.
	Name string
	// Type defaults to "github_release" when empty.
	Type              string
	Asset             string
	Format            string
	BinaryName        string
	SupportedEnvs     []string
	VersionConstraint string
	VersionPrefix     string
}

AquaTool describes a fake aqua-registry package the mock serves from its aqua-registry endpoints ({aquaPrefix}/registry.yaml and {aquaPrefix}/pkgs/{path}/registry.yaml). Field names mirror the subset of aquaproj/aqua-registry YAML keys that pkg/toolchain/registry/aqua consumes (see aquaPackageYAML's yaml tags).

Checksum verification is intentionally not modeled here: leaving it unset (the zero value) means the registered package has no checksum config, so the installer's checksum verification -- which is opt-in per package -- never activates. This keeps the mock from having to fake a matching checksum file, without weakening production verification: real registry entries that do configure a checksum are unaffected, and callers who genuinely need to exercise checksum verification would extend this struct rather than route around it.

type ArtifactoryMockServer added in v1.205.1

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

ArtifactoryMockServer provides a mock HTTP server that implements enough of the JFrog Artifactory Generic repository API to test the Atmos Artifactory store integration.

func NewArtifactoryMockServer added in v1.205.1

func NewArtifactoryMockServer(t *testing.T) *ArtifactoryMockServer

NewArtifactoryMockServer creates a mock Artifactory server. The server is automatically cleaned up when the test completes.

func (*ArtifactoryMockServer) Clear added in v1.205.1

func (m *ArtifactoryMockServer) Clear()

Clear removes all files from the mock store.

func (*ArtifactoryMockServer) GetFile added in v1.205.1

func (m *ArtifactoryMockServer) GetFile(path string) ([]byte, bool)

GetFile retrieves a file from the mock store (useful for test assertions).

func (*ArtifactoryMockServer) ListFiles added in v1.205.1

func (m *ArtifactoryMockServer) ListFiles() map[string][]byte

ListFiles returns all files currently stored in the mock.

func (*ArtifactoryMockServer) SetFile added in v1.205.1

func (m *ArtifactoryMockServer) SetFile(path string, content []byte)

SetFile directly sets a file in the mock store (useful for test setup).

func (*ArtifactoryMockServer) URL added in v1.205.1

func (m *ArtifactoryMockServer) URL() string

URL returns the mock server URL.

type GitHubMockServer

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

GitHubMockServer is a small GitHub HTTP façade for tests. It started as a raw-content-only mock (suffix-matched files served over what looked like raw.githubusercontent.com) and has grown path-prefix handlers for the toolchain/registry/raw-fetch surface that pkg/github.Endpoints, pkg/toolchain/registry/aqua, and pkg/toolchain/installer talk to:

  • GET /api/v3/repos/{owner}/{repo}/releases[?page=&per_page=]
  • GET /api/v3/repos/{owner}/{repo}/releases/latest
  • GET /api/v3/repos/{owner}/{repo}/tags[?per_page=]
  • GET /{owner}/{repo}/releases/download/{tag}/{asset}
  • GET /{owner}/{repo}/archive/refs/tags/{tag}.tar.gz
  • GET /raw/{owner}/{repo}/{ref}/{path} (GitHub Enterprise Server raw-content shape)
  • GET {aquaPrefix}/registry.yaml (aqua-registry package index)
  • GET {aquaPrefix}/pkgs/{path}/registry.yaml (aqua-registry per-package file)

Legacy suffix-matched raw files (RegisterFile, Transport, HTTPClient, HttpGetter) keep working unchanged: the new path-prefix routes are tried first, and any request that misses all of them falls through to the original suffix-match loop.

func NewGitHubMockServer

func NewGitHubMockServer(t *testing.T) *GitHubMockServer

NewGitHubMockServer creates a mock server that intercepts GitHub requests. The server is automatically cleaned up when the test completes.

func NewGitHubMockServerStandalone added in v1.229.0

func NewGitHubMockServerStandalone() (mock *GitHubMockServer, closeServer func())

NewGitHubMockServerStandalone creates a mock server without requiring a *testing.T, returning a close func the caller must invoke itself. For use in contexts with no *testing.T available, such as TestMain, where NewGitHubMockServer cannot be called.

func (*GitHubMockServer) EnvForSubprocess added in v1.229.0

func (m *GitHubMockServer) EnvForSubprocess() map[string]string

EnvForSubprocess returns the environment variables a subprocess needs to route GitHub, toolchain, and aqua-registry traffic at this mock: GITHUB_SERVER_URL/GITHUB_API_URL (the repo endpoints resolved by pkg/github.RepoEndpoints), ATMOS_TOOLCHAIN_GITHUB_URL/ ATMOS_TOOLCHAIN_GITHUB_API_URL (pkg/github.ToolchainEndpoints), and ATMOS_TOOLCHAIN_AQUA_REGISTRY_URL (pkg/github.AquaRegistryURL).

func (*GitHubMockServer) FailWith added in v1.229.0

func (m *GitHubMockServer) FailWith(pathPrefix string, status int)

FailWith makes every request whose path starts with pathPrefix fail with status, indefinitely, instead of being routed normally. Use FailWithTimes for a failure that recovers after N hits (e.g. to test an unauthenticated-retry path).

func (*GitHubMockServer) FailWithHeaders added in v1.229.0

func (m *GitHubMockServer) FailWithHeaders(pathPrefix string, status int, headers map[string]string)

FailWithHeaders makes every request whose path starts with pathPrefix fail with status, indefinitely, carrying the given extra response headers -- e.g. a secondary GitHub rate limit, which signals via `Retry-After` rather than `X-RateLimit-Remaining: 0`:

mock.FailWithHeaders("/api/v3/repos/owner/repo", http.StatusForbidden, map[string]string{"Retry-After": "30"})

A copy of headers is stored, not the caller-owned map: matchFailure/applyFailureInjection read it later, outside any lock the caller might (or might not) hold, so mutating the map after registration must never change the response or race with a request being served.

func (*GitHubMockServer) FailWithTimes added in v1.229.0

func (m *GitHubMockServer) FailWithTimes(pathPrefix string, status, times int)

FailWithTimes makes the first `times` requests whose path starts with pathPrefix fail with status; subsequent requests are routed normally. Useful for testing a retry-without-auth path: the first hit returns 403, the retry (a fresh, unauthenticated request) succeeds.

times must be non-negative: matchFailure treats a negative `remaining` as the -1 sentinel reserved for FailWith/FailWithHeaders (an unlimited failure), so a negative times here would otherwise silently become an unlimited failure instead of erroring loudly. This is a test helper with no *testing.T to fail through, so a caller mistake panics instead.

func (*GitHubMockServer) HTTPClient

func (m *GitHubMockServer) HTTPClient() *http.Client

HTTPClient returns an http.Client that intercepts GitHub URLs. Use this with go-getter's HttpGetter or any HTTP client that needs to have GitHub requests redirected to the mock server.

func (*GitHubMockServer) HttpGetter

func (m *GitHubMockServer) HttpGetter() *getter.HttpGetter

HttpGetter returns a go-getter HttpGetter configured to use the mock. Use this when you need to inject a custom getter into go-getter's client.

func (*GitHubMockServer) RegisterAquaTool added in v1.229.0

func (m *GitHubMockServer) RegisterAquaTool(tool *AquaTool)

RegisterAquaTool registers a fake aqua-registry package, servable at both {aquaPrefix}/registry.yaml (as one index entry) and {aquaPrefix}/pkgs/{path}/registry.yaml (the full per-package file).

A copy of tool is stored (including its SupportedEnvs slice), not the caller-owned pointer: mutating the struct or slice the caller passed in after registration must never change what the mock serves, and must never race with the handler goroutine reading it.

func (*GitHubMockServer) RegisterArchive added in v1.229.0

func (m *GitHubMockServer) RegisterArchive(owner, repo, tag string, data []byte)

RegisterArchive registers data to be served at /{owner}/{repo}/archive/refs/tags/{tag}.tar.gz. The bytes are copied so that later mutations to the caller's slice (e.g. a reused test buffer) never change what is served.

func (*GitHubMockServer) RegisterFile

func (m *GitHubMockServer) RegisterFile(pathSuffix, content string)

RegisterFile registers content to be served for a given path suffix. The path suffix is matched against the end of incoming request paths. For example, RegisterFile("stacks/deploy/nonprod.yaml", content) will match requests to /cloudposse/atmos/main/tests/fixtures/scenarios/stack-templates-2/stacks/deploy/nonprod.yaml.

func (*GitHubMockServer) RegisterRawFile added in v1.229.0

func (m *GitHubMockServer) RegisterRawFile(owner, repo, ref, path, content string)

RegisterRawFile registers content to be served at /raw/{owner}/{repo}/{ref}/{path}, the GitHub Enterprise Server raw-content shape pkg/github.Endpoints.RawURL builds when GITHUB_SERVER_URL resolves to a non-default (non-github.com) host. Unlike the legacy RegisterFile suffix match, this is an exact match on owner/repo/ref/path.

func (*GitHubMockServer) RegisterRelease added in v1.229.0

func (m *GitHubMockServer) RegisterRelease(owner, repo string, spec ReleaseSpec)

RegisterRelease appends one fake release for owner/repo, in the order GitHub's "most recent first" release list is normally returned in: register newest first for GetLatestVersion/ GetLatestRelease-style "first non-draft, non-prerelease wins" semantics to behave as expected.

func (*GitHubMockServer) RegisterReleaseAsset added in v1.229.0

func (m *GitHubMockServer) RegisterReleaseAsset(owner, repo, tag, asset string, data []byte)

RegisterReleaseAsset registers data to be served at /{owner}/{repo}/releases/download/{tag}/{asset}. The bytes are copied so that later mutations to the caller's slice (e.g. a reused test buffer) never change what is served.

func (*GitHubMockServer) RegisterTag added in v1.229.0

func (m *GitHubMockServer) RegisterTag(owner, repo, name string)

RegisterTag appends one fake tag name for owner/repo.

func (*GitHubMockServer) RequestCount added in v1.229.0

func (m *GitHubMockServer) RequestCount(pathPrefix string) int

RequestCount returns how many logged requests have a path starting with pathPrefix.

func (*GitHubMockServer) Requests added in v1.229.0

func (m *GitHubMockServer) Requests() []RequestLogEntry

Requests returns a copy of every request the mock has received so far, in order.

func (*GitHubMockServer) SetAquaPrefix added in v1.229.0

func (m *GitHubMockServer) SetAquaPrefix(prefix string)

SetAquaPrefix overrides the path prefix used for the aqua-registry endpoints (default "/aqua"). Must be called before any RegisterAquaTool/aqua request. The prefix is normalized to have a leading slash and no trailing slash (e.g. "registry" and "/registry/" both become "/registry"), except an empty prefix, which is preserved as-is to mean the server root -- tryAqua's path matching and EnvForSubprocess's URL construction both require this shape.

func (*GitHubMockServer) SetRateLimit added in v1.229.0

func (m *GitHubMockServer) SetRateLimit(remaining int, reset time.Time)

SetRateLimit configures the core rate-limit budget the mock reports: `remaining` requests left out of a 5,000 budget, resetting at `reset`. Call with remaining=0 and a past `reset` to simulate an already-recovered exhausted limit (WaitForRateLimit returns immediately); call with remaining=0 and a future `reset` to simulate a still-active primary limit.

func (*GitHubMockServer) Setenv added in v1.229.0

func (m *GitHubMockServer) Setenv(t *testing.T)

Setenv applies EnvForSubprocess via t.Setenv, for in-process tests (or tests that build the atmos binary in-process via exec.Command inheriting os.Environ()).

func (*GitHubMockServer) Transport

func (m *GitHubMockServer) Transport() http.RoundTripper

Transport returns an http.RoundTripper that intercepts GitHub URLs. Can be used to replace http.DefaultTransport in tests to intercept all HTTP requests to GitHub without modifying the code under test.

func (*GitHubMockServer) URL

func (m *GitHubMockServer) URL() string

URL returns the mock server URL.

type ReleaseSpec added in v1.229.0

type ReleaseSpec struct {
	TagName    string
	Prerelease bool
	Draft      bool
}

ReleaseSpec describes one fake GitHub release served by the mock's /api/v3/repos/{owner}/{repo}/releases[/latest] endpoints.

type RequestLogEntry added in v1.229.0

type RequestLogEntry struct {
	Method string
	Path   string
}

RequestLogEntry records one request the mock received, for egress/routing assertions.

Jump to

Keyboard shortcuts

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