diff --git a/test.sh b/test.sh index fe9faf2a3e..2a40b90b4d 100755 --- a/test.sh +++ b/test.sh @@ -1,17 +1,64 @@ -#!/bin/sh -docker compose -f tests/docker-compose.yml run -it -p 5432:5432 --name postgres_16 postgres_16 -DATABASE_URL="postgres://postgres@localhost:5432/sqlx?sslmode=verify-ca&sslrootcert=./tests/certs/ca.crt&sslcert=./tests/certs/client.crt&sslkey=./tests/keys/client.key" cargo test --features any,postgres,macros,all-types,rustls -- +#!/usr/bin/env bash +set -euo pipefail +cd -- "$(dirname -- "${BASH_SOURCE[0]}")" -docker compose -f tests/docker-compose.yml run -it -p 1433:1433 --rm --name mssql_2022 mssql_2022 -DATABASE_URL='mssql://sa:Password123!@localhost/sqlx' cargo test --features any,mssql,macros,all-types,rustls -- +backend=${1:-all} +if [[ $backend == all ]]; then + for backend in postgres mssql mysql sqlite odbc; do + bash ./test.sh "$backend" + done + exit 0 +fi -docker compose -f tests/docker-compose.yml run -it -p 3306:3306 --name mysql_8 mysql_8 -DATABASE_URL='mysql://root:password@localhost/sqlx' cargo test --features any,mysql,macros,all-types,rustls -- +features="any,macros,all-types,rustls" +case "$backend" in + sqlite) + sqlite_dir=$(mktemp -d "${TMPDIR:-/tmp}/sqlx-local-sqlite.XXXXXX") + trap 'rm -rf -- "$sqlite_dir"' EXIT + cp tests/sqlite/sqlite.db "$sqlite_dir/sqlite.db" + export DATABASE_URL="sqlite://$sqlite_dir/sqlite.db" + cargo test --locked --no-default-features --features "$features,sqlite,migrate" + exit + ;; + postgres) service=postgres_14; port=5432 ;; + mysql) service=mysql_8; port=3306 ;; + mssql) service=mssql_2022; port=1433 ;; + odbc) service=postgres_16_no_ssl; port=5432 ;; + *) + echo "Usage: $0 [all|sqlite|postgres|mysql|mssql|odbc]" >&2 + exit 2 + ;; +esac -DATABASE_URL='sqlite://./tests/sqlite/sqlite.db' cargo test --features any,sqlite,macros,all-types,rustls -- +project="sqlx-local-test-$$-$RANDOM" +unset SQLX_POSTGRES_PORT SQLX_MYSQL_PORT SQLX_MSSQL_PORT +cleanup() { + status=$? + docker compose -p "$project" -f tests/docker-compose.yml \ + down --volumes --remove-orphans >/dev/null 2>&1 || true + exit "$status" +} +trap cleanup EXIT +# Each invocation owns one disposable container and a random loopback-only port. +docker compose -p "$project" -f tests/docker-compose.yml \ + up --wait --wait-timeout 120 "$service" +address=$(docker compose -p "$project" -f tests/docker-compose.yml port "$service" "$port") +host_port=${address##*:} +if [[ ! $host_port =~ ^[0-9]+$ ]]; then + echo "Could not determine the database's published port: $address" >&2 + exit 1 +fi -# Copy odbc config from tests/odbc.ini to ~/.odbc.ini and run ODBC tests against Postgres -cp tests/odbc.ini ~/.odbc.ini -docker compose -f tests/docker-compose.yml run -p 5432:5432 --name postgres_16_no_ssl -it postgres_16_no_ssl -DATABASE_URL='DSN=SNOWFLAKE' cargo test --no-default-features --features any,odbc,all-types,macros,rustls \ No newline at end of file +case "$backend" in + postgres) DATABASE_URL="postgres://postgres:password@127.0.0.1:$host_port/sqlx" ;; + mysql) DATABASE_URL="mysql://root:password@127.0.0.1:$host_port/sqlx" ;; + mssql) DATABASE_URL="mssql://sa:Password123!@127.0.0.1:$host_port/sqlx" ;; + odbc) + # Use only the container we started; do not overwrite ~/.odbc.ini or use a saved DSN. + DATABASE_URL="Driver={PostgreSQL Unicode};Servername=127.0.0.1;Port=$host_port;Database=sqlx;Uid=postgres;Pwd=password" + ;; +esac +export DATABASE_URL +if [[ $backend != odbc ]]; then features+=",migrate"; fi +cargo test --locked --no-default-features --features "$features,$backend" diff --git a/tests/README.md b/tests/README.md index 60b60fccdf..e585410f3a 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,18 +1,32 @@ - - -### Running Tests -SQLx uses docker to run many compatible database systems for integration testing. You'll need to [install docker](https://docs.docker.com/engine/) to run the full suite. You can validate your docker installation with: - - $ docker run hello-world - -Start the databases with `docker-compose` before running tests: - - $ docker-compose up - -Run all tests against all supported databases using: - - $ ./x.py - -If you see test failures, or want to run a more specific set of tests against a specific database, you can specify both the features to be tests and the DATABASE_URL. e.g. - - $ DATABASE_URL=mysql://root:password@127.0.0.1:49183/sqlx cargo test --no-default-features --features macros,offline,any,all-types,mysql,native-tls +# Running tests + +Install Rust through rustup and [Docker Compose](https://docs.docker.com/compose/install/). +Run the local test script from any directory: + +```sh +./test.sh # all backends, stopping at the first failure +./test.sh sqlite # SQLite only; no Docker needed +./test.sh postgres # PostgreSQL 14 +./test.sh mysql # MySQL 8 +./test.sh mssql # SQL Server 2022 +./test.sh odbc # ODBC against local PostgreSQL 16 +``` + +Each database run starts a disposable container, waits for its test schema, and +publishes a randomly assigned port on loopback. The script uses that container's +connection string and removes it when the test command exits, including failures. +SQLite runs against a temporary copy of its fixture database. +The script does not use an existing `DATABASE_URL`, a saved ODBC DSN, or modify `~/.odbc.ini`. +The ODBC run requires unixODBC and the **PostgreSQL Unicode** driver on the host. + +The PostgreSQL client-certificate authentication configuration is tested separately +by the **Postgres with SSL client cert** CI job. + +For custom databases, set `DATABASE_URL` explicitly when invoking Cargo. These tests +create and modify database objects: use a disposable test database. + +```sh +DATABASE_URL=mysql://root:password@127.0.0.1:3306/sqlx \ + cargo test --locked --no-default-features \ + --features macros,offline,any,all-types,mysql,native-tls +```