# Databases the test suite talks to. # # Several tests are only meaningful against a real server: what a string # literal means, how a driver converts a value, whether a collation orders the # way Go does. Those are exactly the questions a fake would define away, so # they skip unless the matching environment variable is set — which meant, for # a long time, that they only ever ran on one developer's machine. # # docker compose -f docker-compose.test.yml up -d # export BROKOLI_TEST_POSTGRES_URL='postgres://brokoli:brokoli@localhost:55532/brokoli_test?sslmode=disable' # export BROKOLI_TEST_MYSQL_URL='mysql://brokoli:br@k:li/pw#1@tcp(localhost:55533)/brokoli_test' # export BROKOLI_TEST_MYSQL_ROOT_URL='mysql://root:rootpw@tcp(localhost:55533)/brokoli_test' # export BROKOLI_TEST_CLICKHOUSE_URL='clickhouse://brokoli:brokoli@localhost:55534/brokoli_test' # export BROKOLI_TEST_SQLSERVER_URL='sqlserver://sa:Brokoli%2112345@localhost:55535?database=master&encrypt=disable' # export BROKOLI_TEST_S3_ENDPOINT='http://localhost:55536' # export BROKOLI_TEST_S3_ACCESS_KEY='brokoli-test' # export BROKOLI_TEST_S3_SECRET_KEY='brokoli-test-secret' # export BROKOLI_BIGQUERY_ENDPOINT='http://localhost:55538' # export BROKOLI_OUTBOUND_ALLOW_LOOPBACK='true' # MinIO is bound to localhost # go test ./... # # Ports are in an unusual range so this does not collide with a database # someone already has running — 5543x is taken on at least one machine here, # which is how that lesson was learned. The data is tmpfs — these are scratch # servers, and a test that depends on state surviving a restart is a test # that will fail mysteriously in CI. services: gcs: # fake-gcs-server (MIT), pinned like every other service here. The public # host and external URL keep resumable uploads on this address: without # them the emulator hands back a session URL on storage.googleapis.com. image: fsouza/fake-gcs-server:1.56.1 command: ["-scheme", "http", "-port", "4443", "-backend", "memory", "-public-host", "127.0.0.1:55543", "-external-url", "http://127.0.0.1:55543"] ports: - "55543:4443" openbao: # OpenBao (MPL-2.0) speaks Vault's HTTP API, so the vault secret-store # provider is tested against it. Dev mode: in-memory, unsealed, a KV v2 # mount at secret/, and a fixed root token the tests use to configure # policies and auth methods. image: openbao/openbao:2.4.1 command: ["server", "-dev", "-dev-root-token-id=brokoli-test-root", "-dev-listen-address=0.0.0.0:8200"] cap_add: ["IPC_LOCK"] ports: - "55547:8200" bigquery: # Pinned, like every other service here. goccy/bigquery-emulator is a # community project (MIT); 0.8.1 is its release of 2026-06-13. image: ghcr.io/goccy/bigquery-emulator:0.8.1 command: ["--project=test", "--dataset=brokoli_test"] ports: - "55538:9050" postgres: image: postgres:16-alpine environment: POSTGRES_USER: brokoli POSTGRES_PASSWORD: brokoli POSTGRES_DB: brokoli_test ports: - "55532:5432" tmpfs: - /var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U brokoli -d brokoli_test"] interval: 2s timeout: 3s retries: 30 mysql: image: mysql:8.4 environment: MYSQL_ROOT_PASSWORD: rootpw MYSQL_USER: brokoli MYSQL_PASSWORD: br@k:li/pw#1 MYSQL_DATABASE: brokoli_test ports: - "55533:3306" tmpfs: - /var/lib/mysql command: # local_infile is off by default in MySQL 8 and is what a bulk-load # path would need; enabling it here means the capability can be tested # rather than assumed available. - --local-infile=1 healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-prootpw"] interval: 3s timeout: 5s retries: 30 clickhouse: # 25.3 is an LTS release, pinned per ADR-027 phase 0. The exposed port # is the NATIVE protocol (9000) -- clickhouse-go's decision path; the # HTTP port stays unexposed because the ADR defers the HTTP fallback. # # The password is deliberately plain for now: hostile-credential # coverage belongs to phase 1, when the URI builder that has to carry # it exists (the MySQL password above is hostile because #338's DSN # builder is what it proves). image: clickhouse/clickhouse-server:25.3-alpine environment: CLICKHOUSE_USER: brokoli CLICKHOUSE_PASSWORD: brokoli CLICKHOUSE_DB: brokoli_test # Lets the test user CREATE USER, which the hostile-credential # round-trip test needs. Scratch server, tmpfs data. CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: "1" ports: - "55534:9000" tmpfs: - /var/lib/clickhouse ulimits: # The server refuses to start under the default container nofile # limit on some hosts; this is the value its own docs use. nofile: soft: 262144 hard: 262144 healthcheck: # /ping answers unauthenticated on the HTTP port inside the # container, so the check needs no credentials. test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8123/ping"] interval: 3s timeout: 5s retries: 30 # Oracle Database Free, from gvenzl/oracle-free (Apache-2.0 image build of # Oracle's free edition), pinned by digest: the 23-slim tag moves with # each Oracle release. It is a 2 GB image, so it sits behind a profile and # a plain `up -d` does not pull it; naming it starts it: # # docker compose -f docker-compose.test.yml up -d --wait oracle # export BROKOLI_TEST_ORACLE_URL='oracle://brokoli:p%40ss%2Fw%3Ard%231@127.0.0.1:55544/FREEPDB1' # # The application user's password carries @, /, : and # on purpose, so # the tests prove a connection's URI survives URL syntax in a credential. oracle: image: gvenzl/oracle-free:23-slim@sha256:6d61d267a3b978c24c5ac1790e62e927416a0aec446bd86e4b3a1527562757bd profiles: ["oracle"] environment: ORACLE_PASSWORD: "Brokoli_sys1" APP_USER: brokoli APP_USER_PASSWORD: "p@ss/w:rd#1" ports: - "55544:1521" tmpfs: - /opt/oracle/oradata healthcheck: # The image's own check: the database is open and the PDB is up. test: ["CMD", "healthcheck.sh"] interval: 5s timeout: 5s retries: 60 start_period: 10s sqlserver: image: mcr.microsoft.com/mssql/server:2022-latest environment: ACCEPT_EULA: "Y" MSSQL_SA_PASSWORD: "Brokoli!12345" MSSQL_PID: Developer ports: - "55535:1433" tmpfs: # The 2022 image runs as the non-root mssql user. Docker creates a # tmpfs mount as root unless its ownership is explicit, which prevents # the image from creating /.system during startup. - /var/opt/mssql:rw,uid=10001,gid=0,mode=1770 healthcheck: test: ["CMD-SHELL", "timeout 1 bash -c '&1 | grep -qE "HTTP/1.1 [0-9]{3}"' interval: 2s timeout: 5s retries: 30 minio: image: chrislusf/seaweedfs:3.80 command: server -s3 -s3.port=8333 -s3.config=/etc/seaweedfs/s3.json -dir=/data volumes: - ./testdata/seaweedfs-s3.json:/etc/seaweedfs/s3.json:ro ports: - "55536:8333" tmpfs: - /data healthcheck: # 403 is the correct answer from an S3 endpoint to an unauthenticated # GET, and it is the first moment the API is actually serving, so it # is the readiness signal. `curl -f` would treat it as failure. # wget, not curl: this image is minimal and has no curl, which the # first version of this healthcheck discovered the slow way. test: - CMD-SHELL - 'wget -q -S -O /dev/null http://127.0.0.1:8333/ 2>&1 | grep -qE "HTTP/1.1 (200|403)"' # The master, volume and S3 components converge in about 35s on a # cold runner, so the window is wider than MinIO's single process # needed. interval: 3s timeout: 5s retries: 40 start_period: 10s localstack: # The aws_secrets_manager and aws_ssm secret-store providers (ADR-041) # are tested against LocalStack's Secrets Manager, SSM and STS. 4.4 is # the community edition and runs without an auth token; pinned by digest # so a later image that requires one cannot arrive silently. image: localstack/localstack:4.4@sha256:b52c16663c70b7234f217cb993a339b46686e30a1a5d9279cb5feeb2202f837c environment: SERVICES: secretsmanager,ssm,sts ports: - "55545:4566" healthcheck: test: - CMD-SHELL - 'curl -s http://127.0.0.1:4566/_localstack/health | grep -q "\"secretsmanager\": \"available\""' interval: 2s timeout: 5s retries: 60