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 ¶
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" )
const ( // TestHost is the standard localhost hostname for test environments. TestHost = "localhost" // TestHostWithPort is localhost with a common test port. TestHostWithPort = "localhost:8080" )
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" )
const ( // TestConfigKey is a generic configuration key for testing. TestConfigKey = "test.key" // TestConfigPort is a common port number used in test configurations. TestConfigPort = "8080" )
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.
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 ¶
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}, }
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.
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.
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 ¶
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
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.