Help us shape the future of Go! Take the 2026 Go Developer Survey

chtest

package
v1.35.0 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2026 License: MIT Imports: 31 Imported by: 0

Documentation

Overview

Package chtest starts digest-pinned ClickHouse containers through the rudder-go-kit ClickHouse resource and puts a fault-injecting proxy in front of them. It is for tests only.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Image

func Image(tag string) string

Image returns the digest-pinned reference for a tag listed in images.json. It panics for any other tag, so a test can never run an unpinned image.

Types

type Balancer

type Balancer struct {
	// contains filtered or unexported fields
}

Balancer is a TCP front that alternates upstreams per connection, as a load balancer in front of a cluster does. It ends TLS with the front certificate, which the server's CA pool trusts, and relays the plain bytes to each upstream port on 127.0.0.1. An upstream is a plain HTTP port: a server's HTTPPort or a PlainHTTP proxy, which lets a test fake a second host with one container.

func NewBalancer

func NewBalancer(t *testing.T, srv *Server, upstreams ...int) *Balancer

NewBalancer starts a balancer on 127.0.0.1 that ends TLS with the front certificate and alternates the upstream ports.

func (*Balancer) Port

func (b *Balancer) Port() int

Port returns the balancer's port on 127.0.0.1.

type Options

type Options struct {
	Tag       string // a key of images.json, e.g. "26.3"
	Timezone  string // the server TZ, UTC when empty
	ConfigXML string // an extra config.d document, optional
}

Options configure Start.

type Proxy

type Proxy struct {
	// contains filtered or unexported fields
}

Proxy sits between a client and a Server's plain HTTP port and injects one-shot faults.

func NewProxy

func NewProxy(t *testing.T, srv *Server, o ProxyOptions) *Proxy

NewProxy starts a proxy on 127.0.0.1 that forwards to srv's plain HTTP port. It serves TLS with the front certificate unless o.PlainHTTP is set.

func (*Proxy) DropResponseOnce

func (p *Proxy) DropResponseOnce(match func(Request) bool)

DropResponseOnce forwards the first matching request, reads the whole answer, then closes the connection without writing a response.

func (*Proxy) InjectOnce

func (p *Proxy) InjectOnce(match func(Request) bool, status int, header http.Header, body string)

InjectOnce answers the first matching request with status, header and body, without forwarding it.

func (*Proxy) OnRequest

func (p *Proxy) OnRequest(hook func(Request))

OnRequest calls hook with every request whose body the proxy has read, before it answers or forwards the request.

func (*Proxy) Port

func (p *Proxy) Port() int

Port returns the proxy's port on 127.0.0.1.

func (*Proxy) Requests

func (p *Proxy) Requests() []Request

Requests returns a copy of the recorded requests in arrival order.

func (*Proxy) ResetAfterForwardOnce

func (p *Proxy) ResetAfterForwardOnce(match func(Request) bool)

ResetAfterForwardOnce forwards the first matching request, reads the whole answer, then resets the client TCP connection: ECONNRESET after the server ran the statement.

func (*Proxy) ResetBeforeBodyOnce

func (p *Proxy) ResetBeforeBodyOnce(match func(Request) bool)

ResetBeforeBodyOnce matches when the request headers arrive, before the proxy reads any body byte; match sees Query and Header, and SQL is empty. It resets the connection while the client still writes the body, so the server never sees the statement.

func (*Proxy) ResetOnce

func (p *Proxy) ResetOnce(match func(Request) bool)

ResetOnce resets the TCP connection of the first matching request before forwarding it: a transport error with no server work.

type ProxyOptions

type ProxyOptions struct {
	IdleTimeout time.Duration // the proxy's server-side keep-alive timeout, 0 for the net/http default
	PlainHTTP   bool          // serve plain HTTP instead of TLS with the front certificate
	// RewriteSQL, when set, replaces the statement text (body or "query"
	// parameter) before the proxy forwards it.
	RewriteSQL func(string) string
}

ProxyOptions configure NewProxy.

type QueryLogRow

type QueryLogRow struct {
	QueryID  string
	Query    string
	Kind     string            // query_kind, such as Select or Create
	Settings map[string]string // only the settings the statement changed
	IsHello  bool              // the query the driver sends when it opens a connection
}

QueryLogRow is one finished statement in system.query_log.

type Request

type Request struct {
	ConnID int
	Path   string
	Query  url.Values
	// SQL is the "query" parameter when present, else the body; empty for
	// ResetBeforeBodyOnce matches. It is not redacted, so tests must not log it.
	SQL        string
	At         time.Time
	IdleBefore time.Duration // the idle gap on this connection before the request, 0 for the first one
	Header     http.Header
}

Request is one request the proxy received. Credentials are redacted.

type Running

type Running struct {
	// contains filtered or unexported fields
}

Running is a statement that StartAs sent in the background.

func (*Running) Wait

func (r *Running) Wait(t *testing.T)

Wait blocks until the statement ends and fails the test unless it succeeded.

type Server

type Server struct {
	Host      string // "localhost": a name that both certificates carry
	HTTPSPort int    // the server's own HTTPS port, with the go-kit certificate
	HTTPPort  int    // the server's own plain HTTP port on 127.0.0.1
	// CA holds the one fixture CA. It signs the server certificate and the
	// front certificate that proxies and balancers present.
	CA            *x509.CertPool
	AdminUser     string
	AdminPassword string
	// contains filtered or unexported fields
}

Server is a running ClickHouse container.

func Start

func Start(t *testing.T, o Options) *Server

Start runs a container of the pinned image for o.Tag, waits until it answers and removes it when the test ends.

func (*Server) AdminExec

func (s *Server) AdminExec(t *testing.T, sql string)

AdminExec runs one statement as the admin over plain HTTP on loopback.

func (*Server) AdminQuery

func (s *Server) AdminQuery(t *testing.T, sql string) [][]string

AdminQuery runs one query as the admin and returns the TSV rows.

func (*Server) Config

func (s *Server) Config(user, password, database string, secure bool) json.RawMessage

Config returns the eight account fields for the driver. HTTPS uses the host "localhost" so the fixture certificate matches.

func (*Server) CreateScopedUser

func (s *Server) CreateScopedUser(t *testing.T, name, password, customerDB, rudderDB string, syncLog bool)

CreateScopedUser provisions a runtime user with the customer grant set, customerGrants. syncLog also creates the working database's sync_log table.

func (*Server) CreateUserWithConstraint

func (s *Server) CreateUserWithConstraint(t *testing.T, setting, value string) User

CreateUserWithConstraint creates a user whose settings profile pins setting to value with a CONST constraint, so a statement that sends another value fails with server code 452.

func (*Server) CreateUserWithProfile

func (s *Server) CreateUserWithProfile(t *testing.T, settings map[string]string) User

CreateUserWithProfile creates a user whose settings profile sets each setting to its value, quoted as a string literal.

func (*Server) DropProbes

func (s *Server) DropProbes(t *testing.T)

DropProbes drops every validation probe table in _rudderstack.

func (*Server) FlushLogs

func (s *Server) FlushLogs(t *testing.T)

FlushLogs writes the buffered system log tables, such as system.query_log.

func (*Server) ImageDigest

func (s *Server) ImageDigest(t *testing.T) string

ImageDigest returns the digest of the running container's image, read from Docker and not from images.json.

func (*Server) KillStatements

func (s *Server) KillStatements(t *testing.T) []string

KillStatements flushes the logs and returns the text of every KILL statement the Go driver sent.

func (*Server) LatestHello

func (s *Server) LatestHello(t *testing.T) QueryLogRow

LatestHello returns the most recent connection-open query.

func (*Server) ProbeTables

func (s *Server) ProbeTables(t *testing.T) []string

ProbeTables returns the names of the validation probe tables in _rudderstack.

func (*Server) ProcessCount

func (s *Server) ProcessCount(t *testing.T, queryID string) int

ProcessCount returns the number of system.processes rows with the query id, for every user.

func (*Server) QueryAs

func (s *Server) QueryAs(t *testing.T, u User, sql string) string

QueryAs runs one statement as u over plain HTTP on loopback and returns the TSV body.

func (*Server) QueryLogCount

func (s *Server) QueryLogCount(t *testing.T, queryID string) int

QueryLogCount returns the number of finished statements with the query id.

func (*Server) QueryLogCountLike

func (s *Server) QueryLogCountLike(t *testing.T, pattern, kind string) int

QueryLogCountLike counts the finished driver statements of one query_kind whose text matches the LIKE pattern.

func (*Server) QueryLogKind

func (s *Server) QueryLogKind(t *testing.T, queryID string) string

QueryLogKind returns the query_kind of the finished statement with the query id.

func (*Server) QueryLogLike

func (s *Server) QueryLogLike(t *testing.T, pattern string) []QueryLogRow

QueryLogLike returns every finished driver statement whose text matches the LIKE pattern.

func (*Server) QueryLogSettings

func (s *Server) QueryLogSettings(t *testing.T, queryID string) map[string]string

QueryLogSettings returns the settings of the finished statement with the query id. Call FlushLogs first.

func (*Server) QueryLogSince

func (s *Server) QueryLogSince(t *testing.T, since time.Time) []QueryLogRow

QueryLogSince returns every finished driver statement that started at or after since.

func (*Server) RawHTTPS

func (s *Server) RawHTTPS(t *testing.T, sql string, q url.Values) string

RawHTTPS runs one statement as the admin over the HTTPS port with the fixture CA and returns the raw response body. It sets no driver settings, so a test can see what the server answers without the driver in between.

func (*Server) Show

func (s *Server) Show(t *testing.T, table string) string

Show returns SHOW CREATE TABLE for table, run as the admin. table is "db.name"; both parts are quoted.

func (*Server) StartAs

func (s *Server) StartAs(t *testing.T, user, password, queryID, sql string) *Running

StartAs sends sql as user under queryID in the background and returns once system.processes shows the statement.

type User

type User struct {
	Name, Password string
}

User is a runtime user that a test created.

Jump to

Keyboard shortcuts

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