testutil

package
v0.66.0 Latest Latest
Warning

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

Go to latest
Published: Sep 19, 2026 License: MIT Imports: 2 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 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