testutil

package
v0.68.0 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package testutil provides shared constants for testing across go-bricks. These constants eliminate repeated string literals in test files and ensure consistency.

Index

Constants

View Source
const (
	// TestError is a generic error message for test error scenarios.
	// Used across multiple test files (10+ occurrences).
	TestError = "test error"

	// TestConnectionRefused is the common network error message for connection failures.
	// Used in error handling tests across config, cache, database, and httpclient packages.
	TestConnectionRefused = "connection refused"
)
View Source
const (
	// TestHost is the standard localhost hostname for test environments.
	TestHost = "localhost"

	// TestHostWithPort is localhost with a common test port.
	TestHostWithPort = "localhost:8080"
)
View Source
const (
	// TestTenantID is a generic tenant identifier for single-tenant tests.
	TestTenantID = "test-tenant"

	// TestTenantAcme is a fictional company tenant for multi-tenant tests.
	TestTenantAcme = "acme"

	// TestTenantGlobex is another fictional company tenant for multi-tenant tests.
	TestTenantGlobex = "globex"
)
View Source
const (
	// TestConfigKey is a generic configuration key for testing.
	TestConfigKey = "test.key"

	// TestConfigPort is a common port number used in test configurations.
	TestConfigPort = "8080"
)
View Source
const (
	PostgresServiceHost = socketHost
	PostgresServicePort = 6543
)

PostgresServiceHost and PostgresServicePort are what PostgresServiceFileBody's service sets: a unix-socket host, so a DSN that resolves through it dials the socket with TLS skipped, and a port no fixture DSN names, so pgx's port shows whether it read the service at all.

View Source
const PostgresServiceFileBody = "[" + serviceName + "]\nhost=" + PostgresServiceHost + "\nport=6543\nuser=u\n" +
	"[]\nhost=" + PostgresServiceHost + "\nport=6543\nuser=u\n"

PostgresServiceFileBody is the service file the pgx oracle writes: a named service, and an unnamed [] section, which pgservicefile files under "" and so answers an empty service=.

Variables

View Source
var PostgresDSNHostCases = []PostgresDSNHostCase{
	{Name: "keyword_tcp_host", DSN: tcpHostUserDSN, Host: tcpHost, HostSet: true},
	{Name: "keyword_socket_host_tls_material_never_read", DSN: "host=" + socketHost + sslModeKey + sslModeVerifyFull + userPair, Host: socketHost, HostSet: true},
	{Name: "keyword_socket_host_no_claim", DSN: socketUserDSN, Host: socketHost, HostSet: true},

	{Name: "keyword_windows_drive_tcp_host", DSN: `host=C:\pg sslmode=` + sslModeRequire + userPair, Host: "C:pg", HostSet: true},

	{Name: "keyword_windows_drive_socket_host", DSN: `host=C:\\pg sslmode=` + sslModeRequire + userPair, Host: `C:\pg`, HostSet: true},
	{Name: "uri_tcp_host", DSN: "postgres://u@" + tcpHost + "/db", Host: tcpHost, HostSet: true},
	{Name: "uri_percent_encoded_socket_host", DSN: "postgres://u@%2Fvar%2Frun%2Fpostgresql/db?sslmode=" + sslModeRequire, Host: socketHost, HostSet: true},
	{Name: "uri_ipv6_host", DSN: "postgres://u@[::1]/db", Host: "::1", HostSet: true},
	{Name: "uri_query_host_overrides_authority", DSN: "postgres://u@a/db?host=c", Host: "c", HostSet: true},

	{Name: "keyword_unknown_key_is_a_runtime_param", DSN: "foo=1 host=h user=u", Host: "h", HostSet: true},
}
View Source
var PostgresSSLEnvTLSCases = []PostgresSSLEnvTLSCase{
	{Name: "socket_pgsslmode_verify_full", DSN: socketUserDSN, Env: [][2]string{{envPGSSLMODE, sslModeVerifyFull}}, Refuse: true},
	{Name: "socket_pgsslmode_require", DSN: socketUserDSN, Env: [][2]string{{envPGSSLMODE, sslModeRequire}}, Refuse: true},
	{Name: "socket_pgsslmode_verify_ca", DSN: socketUserDSN, Env: [][2]string{{envPGSSLMODE, "verify-ca"}}, Refuse: true},
	{Name: "socket_pgsslrootcert", DSN: socketUserDSN, Env: [][2]string{{"PGSSLROOTCERT", "/etc/pg/ca.crt"}}, Refuse: true},

	{Name: "socket_pgsslrootcert_system", DSN: socketUserDSN, Env: [][2]string{{"PGSSLROOTCERT", "system"}}, Refuse: true},
	{Name: "socket_pgsslcert", DSN: socketUserDSN, Env: [][2]string{{envPGSSLCERT, "/etc/pg/client.crt"}}, Refuse: true},
	{Name: "socket_pgsslkey", DSN: socketUserDSN, Env: [][2]string{{"PGSSLKEY", "/etc/pg/client.key"}}, Refuse: true},
	{Name: "socket_pgsslnegotiation_direct", DSN: socketUserDSN, Env: [][2]string{{"PGSSLNEGOTIATION", "direct"}}, Refuse: true},
	{Name: "socket_pgsslmode_prefer", DSN: socketUserDSN, Env: [][2]string{{envPGSSLMODE, "prefer"}}},
	{Name: "socket_pgsslmode_allow", DSN: socketUserDSN, Env: [][2]string{{envPGSSLMODE, "allow"}}},
	{Name: "socket_pgsslmode_disable", DSN: socketUserDSN, Env: [][2]string{{envPGSSLMODE, "disable"}}},
	{Name: "socket_empty_pgsslmode", DSN: socketUserDSN, Env: [][2]string{{envPGSSLMODE, ""}}},
	{Name: "socket_empty_pgsslcert", DSN: socketUserDSN, Env: [][2]string{{envPGSSLCERT, ""}}},
	{Name: "dsn_sslmode_disable_shadows_pgsslmode", DSN: "host=" + socketHost + " sslmode=disable user=u", Env: [][2]string{{envPGSSLMODE, sslModeVerifyFull}}},
	{Name: "dsn_empty_sslcert_shadows_pgsslcert", DSN: "host=" + socketHost + " sslcert='' user=u", Env: [][2]string{{envPGSSLCERT, "/x"}}},
	{Name: "tcp_pgsslmode_require", DSN: tcpHostUserDSN, Env: [][2]string{{envPGSSLMODE, sslModeRequire}}, WantPgxTLS: true},
	{Name: "tcp_pgsslmode_verify_full", DSN: tcpHostUserDSN, Env: [][2]string{{envPGSSLMODE, sslModeVerifyFull}}, WantPgxTLS: true},
	{Name: "tcp_pgsslnegotiation_direct", DSN: tcpHostUserDSN, Env: [][2]string{{"PGSSLNEGOTIATION", "direct"}}, WantPgxTLS: true},
	{Name: "pghost_socket_pgsslmode_require", DSN: "user=u", Env: [][2]string{{envPGHOST, socketHost}, {envPGSSLMODE, sslModeRequire}}, Refuse: true},
}

PostgresSSLEnvTLSCases is shared between config's rule-2 tests and database/postgresql's pgconn.ParseConfig oracle so the env-under-DSN merge cannot silently drift from a pgx bump.

View Source
var PostgresServiceCases = []PostgresServiceCase{
	{Name: "dsn_service_without_pghost", DSN: serviceClaimDSN, RefusedBy: serviceDSNSource, PgxHost: PostgresServiceHost},
	{Name: "dsn_service_over_tcp_pghost", DSN: serviceClaimDSN, Env: [][2]string{{envPGHOST, tcpHost}}, RefusedBy: serviceDSNSource, PgxHost: PostgresServiceHost},
	{Name: "pgservice_without_pghost", DSN: serviceEnvClaimDSN, Env: [][2]string{{envPGSERVICE, serviceName}}, RefusedBy: envPGSERVICE, PgxHost: PostgresServiceHost},
	{Name: "pgservice_over_tcp_pghost", DSN: serviceEnvClaimDSN, Env: [][2]string{{envPGSERVICE, serviceName}, {envPGHOST, tcpHost}}, RefusedBy: envPGSERVICE, PgxHost: PostgresServiceHost},

	{Name: "dsn_service_beside_pgservice", DSN: serviceClaimDSN, Env: [][2]string{{envPGSERVICE, "other"}}, RefusedBy: serviceDSNSource, PgxHost: PostgresServiceHost},
	{Name: "uri_query_service", DSN: "postgres:///db?service=" + serviceName + "&sslmode=" + sslModeRequire, RefusedBy: serviceDSNSource, PgxHost: PostgresServiceHost},

	{Name: "dsn_host_beside_dsn_service", DSN: "host=" + tcpHost + " service=" + serviceName, RefusedBy: serviceDSNSource, PgxHost: tcpHost},

	{Name: "empty_dsn_service_over_tcp_pghost", DSN: "service='' sslmode=" + sslModeRequire, Env: [][2]string{{envPGHOST, tcpHost}}, RefusedBy: serviceDSNSource, PgxHost: PostgresServiceHost},
	{Name: "uri_empty_query_service_over_tcp_pghost", DSN: "postgres:///db?service=&sslmode=" + sslModeRequire, Env: [][2]string{{envPGHOST, tcpHost}}, RefusedBy: serviceDSNSource, PgxHost: PostgresServiceHost},

	{Name: "empty_dsn_service_shadows_pgservice", DSN: tcpHostUserDSN + " service=''", Env: [][2]string{{envPGSERVICE, serviceName}}, RefusedBy: serviceDSNSource, PgxHost: tcpHost},

	{Name: "empty_service_swallows_next_pair", DSN: "service= " + tcpHostUserDSN, Env: [][2]string{{envPGSERVICE, serviceName}}, RefusedBy: serviceDSNSource},
	{Name: "dsn_servicefile_without_service", DSN: "servicefile=/x/pg_service.conf " + tcpHostUserDSN, PgxHost: tcpHost},
	{Name: "pgservicefile_without_service", DSN: tcpHostUserDSN, Env: [][2]string{{"PGSERVICEFILE", "/x"}}, PgxHost: tcpHost},
}

PostgresServiceCases is shared between config's service-rule tests and database/postgresql's pgconn.ParseConfig oracle, so the service merge cannot silently drift from a pgx bump.

View Source
var UntokenizablePostgresDSNs = []string{
	"host='" + socketHost + sslModeKey + sslModeRequire,
	`host='/a\' user=u`,
	`host='/a\`,
	"host",
	"host=a user",
	"=a",
	"ho st=a",
	"host=a\x00",
	"POSTGRES://h/db",
	"postgres://[::1/db",
	"postgres://[]/db",
	"postgres://[::1]x/db",
	"postgres://%zz/db",
	"postgres://h%00/db",
	"postgresql://a b/db",
	"postgres://h\x00/db",
	"postgres://h/db?sslmode",
	"postgres://h/db?sslmode=a=b",
	"postgres://h/db?&sslmode=" + sslModeRequire,
	"postgres://h/db?ssl%zz=1",
	"postgres://h/db?sslmode=re%zz",
	"postgres://h/db?host=a b",
}

UntokenizablePostgresDSNs are connection strings pgx v5 refuses to parse, so a scanner that cannot tokenize them may pass them through unjudged.

Functions

func GoroutineDump added in v0.68.0

func GoroutineDump() string

GoroutineDump returns every goroutine's stack, growing the buffer until the dump fits so no entry is truncated away.

func ParkedInSelect added in v0.68.0

func ParkedInSelect(frame string) int

ParkedInSelect counts the goroutines parked in a select inside frame, a function as the runtime prints it, such as "server.(*Server).checkApplicationListener(".

func ReserveFreePort added in v0.68.0

func ReserveFreePort(t *testing.T) int

ReserveFreePort returns a loopback TCP port that was free a moment ago. Another process may take it before the caller binds, so use it only where a collision fails loudly.

func SetEnv added in v0.66.0

func SetEnv(t testing.TB, env [][2]string)

SetEnv applies each fixture env pair with t.Setenv.

Types

type BlockedCreate added in v0.66.0

type BlockedCreate struct {
	Started <-chan struct{}
	// contains filtered or unexported fields
}

BlockedCreate parks a create callback after it has started, then releases it. Arrive signals Started once and blocks until Release (or test cleanup). Tests use it to order Remove against an in-flight Get / GetOrCreate.

func NewBlockedCreate added in v0.66.0

func NewBlockedCreate(t *testing.T) *BlockedCreate

NewBlockedCreate returns a gate whose Release runs on cleanup so a failed test cannot leave a create goroutine blocked on Arrive.

func (*BlockedCreate) Arrive added in v0.66.0

func (b *BlockedCreate) Arrive()

Arrive signals that the create has started, then waits for Release.

func (*BlockedCreate) Release added in v0.66.0

func (b *BlockedCreate) Release()

Release unblocks every Arrive. Idempotent.

type PostgresDSNHostCase added in v0.65.0

type PostgresDSNHostCase struct {
	Name    string
	DSN     string
	Host    string
	HostSet bool
}

PostgresDSNHostCase pins one DSN's host resolution, shared between the config package's own scanner unit test and database/postgresql's pgconn.ParseConfig oracle test, so the mirror cannot silently drift from a pgx bump. Two exclusions shape the fixture list: every entry names a SINGLE host, because pgconn.ParseConfig resolves only fallbacks[0] into Config.Host and a comma-joined host string cannot be compared against it; and every entry carries an explicit user, so parsing never depends on the OS account running the test.

type PostgresSSLEnvTLSCase added in v0.66.0

type PostgresSSLEnvTLSCase struct {
	Name       string
	DSN        string
	Env        [][2]string
	Refuse     bool
	WantPgxTLS bool
}

PostgresSSLEnvTLSCase is one DSN+env combination the [C66.1] rule and pgx ParseConfig must agree on: a socket host with a TLS claim is refused here and yields TLSConfig == nil from pgx; a TCP host with a claim pgx honors yields a non-nil TLSConfig. Env entries are applied with t.Setenv on a hermetic PG* env.

type PostgresServiceCase added in v0.66.0

type PostgresServiceCase struct {
	Name      string
	DSN       string
	Env       [][2]string
	RefusedBy string
	PgxHost   string
}

PostgresServiceCase is one DSN+env combination whose libpq service resolution pgx and the config seam must agree on. RefusedBy is the source the config refusal names as carrying the service (service= or PGSERVICE), empty when the seam accepts; every row pgx resolves through a service is refused. PgxHost is the host pgconn.ParseConfig resolves under PostgresServiceFileBody, empty when pgx refuses the DSN. Env entries are applied with SetEnv on a hermetic PG* env.

Jump to

Keyboard shortcuts

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