diff --git a/.github/workflows/ci-bats-unix-remote.yaml b/.github/workflows/ci-bats-unix-remote.yaml index d2a543eef9f..8d710e5ac41 100644 --- a/.github/workflows/ci-bats-unix-remote.yaml +++ b/.github/workflows/ci-bats-unix-remote.yaml @@ -109,5 +109,5 @@ jobs: PARQUET_RUNTIME_JAR: ${{ steps.parquet_cli.outputs.runtime_jar }} BATS_TEST_RETRIES: "3" run: | - bats --tap . + bats --print-output-on-failure --tap . working-directory: ./integration-tests/bats diff --git a/.github/workflows/ci-bats-unix.yaml b/.github/workflows/ci-bats-unix.yaml index 01a895646f5..9a46592910f 100644 --- a/.github/workflows/ci-bats-unix.yaml +++ b/.github/workflows/ci-bats-unix.yaml @@ -132,7 +132,7 @@ jobs: PARQUET_RUNTIME_JAR: ${{ steps.parquet_cli.outputs.runtime_jar }} BATS_TEST_RETRIES: "3" run: | - bats --tap $BATS_FILTER . + bats --print-output-on-failure --tap $BATS_FILTER . working-directory: ./integration-tests/bats - name: Test all Unix, SQL_ENGINE=remote-engine # If we have AWS credentials, we run these remote-engine tests here instead of in the separate job. @@ -142,5 +142,5 @@ jobs: PARQUET_RUNTIME_JAR: ${{ steps.parquet_cli.outputs.runtime_jar }} BATS_TEST_RETRIES: "3" run: | - bats --tap $BATS_FILTER . + bats --print-output-on-failure --tap $BATS_FILTER . working-directory: ./integration-tests/bats diff --git a/go/go.mod b/go/go.mod index 886f0aa3d34..d757b69a9e1 100644 --- a/go/go.mod +++ b/go/go.mod @@ -13,7 +13,7 @@ require ( github.com/dolthub/fslock v0.0.0-20251215194149-ef20baba2318 github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718 github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 - github.com/dolthub/vitess v0.0.0-20260225173707-20566e4abe9e + github.com/dolthub/vitess v0.0.0-20260304224106-95dd8eda10b0 github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.13.0 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 @@ -64,7 +64,7 @@ require ( github.com/dolthub/dolt-mcp v0.3.4 github.com/dolthub/eventsapi_schema v0.0.0-20260205214132-a7a3c84c84a1 github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 - github.com/dolthub/go-mysql-server v0.20.1-0.20260303014403-876f8caeb661 + github.com/dolthub/go-mysql-server v0.20.1-0.20260304235552-80791ce5e625 github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 github.com/edsrzf/mmap-go v1.2.0 github.com/esote/minmaxheap v1.0.0 diff --git a/go/go.sum b/go/go.sum index b283598d796..b73747dc41b 100644 --- a/go/go.sum +++ b/go/go.sum @@ -212,8 +212,8 @@ github.com/dolthub/fslock v0.0.0-20251215194149-ef20baba2318 h1:n+vdH5G5Db+1qnDC github.com/dolthub/fslock v0.0.0-20251215194149-ef20baba2318/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0= github.com/dolthub/go-icu-regex v0.0.0-20250916051405-78a38d478790 h1:zxMsH7RLiG+dlZ/y0LgJHTV26XoiSJcuWq+em6t6VVc= github.com/dolthub/go-icu-regex v0.0.0-20250916051405-78a38d478790/go.mod h1:F3cnm+vMRK1HaU6+rNqQrOCyR03HHhR1GWG2gnPOqaE= -github.com/dolthub/go-mysql-server v0.20.1-0.20260303014403-876f8caeb661 h1:QA2+NhLCzDJyEf7Gz9wKI4NQlacayQBXxnRlFIiUTH4= -github.com/dolthub/go-mysql-server v0.20.1-0.20260303014403-876f8caeb661/go.mod h1:ckzY4FS7Z12b3uSYLTGIVAJOGFG/khj0KU6gEL1kkxY= +github.com/dolthub/go-mysql-server v0.20.1-0.20260304235552-80791ce5e625 h1:pOKtS6gYJ5HiwdRb5KlRia0CRQjym6yyuvQE7auYOOw= +github.com/dolthub/go-mysql-server v0.20.1-0.20260304235552-80791ce5e625/go.mod h1:8zqJ7NgJ7GEISN7VkYEmrrW3DodmHHMCEjIH72BkoEU= github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 h1:OAsXLAPL4du6tfbBgK0xXHZkOlos63RdKYS3Sgw/dfI= github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63/go.mod h1:lV7lUeuDhH5thVGDCKXbatwKy2KW80L4rMT46n+Y2/Q= github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718 h1:lT7hE5k+0nkBdj/1UOSFwjWpNxf+LCApbRHgnCA17XE= @@ -222,8 +222,8 @@ github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 h1:bMGS25NWAGTE github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71/go.mod h1:2/2zjLQ/JOOSbbSboojeg+cAwcRV0fDLzIiWch/lhqI= github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 h1:7/v8q9XGFa6q5Ap4Z/OhNkAMBaK5YeuEzwJt+NZdhiE= github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81/go.mod h1:siLfyv2c92W1eN/R4QqG/+RjjX5W2+gCTRjZxBjI3TY= -github.com/dolthub/vitess v0.0.0-20260225173707-20566e4abe9e h1:ZrRCF8F8Iq8RP0OBowkYpOwd/1NTFU34Ydp0MZ2qTq4= -github.com/dolthub/vitess v0.0.0-20260225173707-20566e4abe9e/go.mod h1:eLLslh1CSPMf89pPcaMG4yM72PQbTN9OUYJeAy0fAis= +github.com/dolthub/vitess v0.0.0-20260304224106-95dd8eda10b0 h1:zw8xnAPxlLoCGWiTbXVjPvLBBBX+b104WFCGJ0FEbSM= +github.com/dolthub/vitess v0.0.0-20260304224106-95dd8eda10b0/go.mod h1:eLLslh1CSPMf89pPcaMG4yM72PQbTN9OUYJeAy0fAis= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= diff --git a/go/libraries/doltcore/sqle/binlogreplication/binlog_replication_test.go b/go/libraries/doltcore/sqle/binlogreplication/binlog_replication_test.go index 78311cf17b1..bedc3258583 100644 --- a/go/libraries/doltcore/sqle/binlogreplication/binlog_replication_test.go +++ b/go/libraries/doltcore/sqle/binlogreplication/binlog_replication_test.go @@ -350,7 +350,7 @@ func TestBinlogSystemUserIsLocked(t *testing.T) { // Before starting replication, the system account does not exist err = db.Ping() require.Error(t, err) - require.ErrorContains(t, err, "No authentication") + require.ErrorContains(t, err, "Access denied for user") // After starting replication, the system account is locked h.startReplicationAndCreateTestDb(h.mySqlPort) diff --git a/integration-tests/bats/caching_sha2_password.bats b/integration-tests/bats/caching_sha2_password.bats index fb852afa5aa..df1443b0c09 100644 --- a/integration-tests/bats/caching_sha2_password.bats +++ b/integration-tests/bats/caching_sha2_password.bats @@ -54,7 +54,7 @@ EOF # Invalid account run mysql -uinvalid --port $PORT --protocol TCP --default-auth=caching_sha2_password -pwrong [ "$status" -ne 0 ] - [[ "$output" =~ "No authentication methods available for authentication" ]] || false + [[ "$output" =~ "Access denied for user 'invalid'" ]] || false } # The mysql command line client is not available in Lambda diff --git a/integration-tests/bats/cli-hosted.bats b/integration-tests/bats/cli-hosted.bats index 29aff494144..09778fb1dcf 100644 --- a/integration-tests/bats/cli-hosted.bats +++ b/integration-tests/bats/cli-hosted.bats @@ -90,7 +90,7 @@ teardown() { @test "cli-hosted: bogus user rejected" { run dolt $TLS --host $HST --port $PRT --user bogus sql -q "create database bats_test_cli_hosted" [ "$status" -eq 1 ] - [[ $output =~ "No authentication" ]] || false + [[ $output =~ "Access denied for user 'bogus'" ]] || false } # This test will not work if you change DOLT_CLI_USER above. Be aware if you run against a hosted instance. diff --git a/integration-tests/bats/sql-privs.bats b/integration-tests/bats/sql-privs.bats index e292e054a1f..f04b4f0303b 100644 --- a/integration-tests/bats/sql-privs.bats +++ b/integration-tests/bats/sql-privs.bats @@ -697,7 +697,7 @@ teardown() { # Assert that using the test account results in an authentication error, since only test@10.10.10.10 exists now run dolt -u test sql -q "show tables" [ $status -ne 0 ] - [[ "$output" =~ "No authentication methods available for authentication" ]] || false + [[ "$output" =~ "Access denied for user 'test'" ]] || false } @test "sql-privs: creating user identified by password" { diff --git a/integration-tests/mysql-client-tests/Dockerfile b/integration-tests/mysql-client-tests/Dockerfile index 94bdf721dc4..cac7c3c0202 100644 --- a/integration-tests/mysql-client-tests/Dockerfile +++ b/integration-tests/mysql-client-tests/Dockerfile @@ -132,6 +132,14 @@ WORKDIR /build/swift/ RUN swift build -c release --static-swift-stdlib RUN mkdir -p /build/bin && cp .build/release/MariaDBTest /build/bin/mariadb-swift-test +FROM debian:bookworm-slim AS mariadb_clients +RUN apt-get update && apt-get install -y ca-certificates curl tar && rm -rf /var/lib/apt/lists/* +COPY dolt/integration-tests/mysql-client-tests/mariadb-install.sh /usr/local/mariadb-install.sh +WORKDIR /usr/local +RUN chmod +x ./mariadb-install.sh +RUN ./mariadb-install.sh -o mariadb-10.11.tar.gz -d mariadb-10.11 "10.11.16" +RUN ./mariadb-install.sh -o mariadb-11.8.tar.gz -d mariadb-11.8 "11.8.3" + FROM php:8.3-bookworm AS runtime RUN apt-get update && apt-get install -y \ libmysqlcppconn-dev \ @@ -155,6 +163,9 @@ COPY --from=node_clients_build /usr/local/bin/node /usr/local/bin/ COPY --from=ruby_clients_build /usr/local/bin/ruby /usr/local/bin/ COPY --from=ruby_clients_build /usr/local/lib/ /usr/local/lib/ COPY --from=ruby_clients_build /usr/local/bundle/ /usr/local/bundle/ +COPY --from=mariadb_clients /usr/local/mariadb-10.11/ /usr/local/mariadb-10.11/ +COPY --from=mariadb_clients /usr/local/mariadb-11.8/ /usr/local/mariadb-11.8/ +RUN ln -vsfn /usr/local/mariadb-10.11 /usr/local/mariadb RUN docker-php-ext-install mysqli pdo_mysql && \ R -e "install.packages('DBI', repos='https://cloud.r-project.org/')" && \ diff --git a/integration-tests/mysql-client-tests/README.md b/integration-tests/mysql-client-tests/README.md index 418be13868a..7e3b9263374 100644 --- a/integration-tests/mysql-client-tests/README.md +++ b/integration-tests/mysql-client-tests/README.md @@ -1,31 +1,62 @@ ## MySQL Client Tests -We created smoke tests for Dolt's MySQL client integrations and we run these tests through GitHub Actions -on pull requests. +This suite contains smoke tests for Dolt's MySQL and MariaDB client integrations. +It runs in GitHub Actions on pull requests. -These tests can be run locally using Docker. Before you can build the image, you also need to copy the go folder -into the integration-tests folder; unfortunately just symlinking doesn't seem to work. From the -integration-tests directory of the dolt repo, run: +## Run Locally With Docker +Build from the workspace root that contains the `dolt/` directory. The Dockerfile copies files using +paths like `dolt/go/...`, so the build context must include that root. You can skip all the commands by using the GoLand's built-in Docker extension. ```bash -$ cp -r ../go . -$ docker build -t mysql-client-tests -f MySQLDockerfile . +$ cd +$ docker build -t mysql-client-tests -f dolt/integration-tests/mysql-client-tests/Dockerfile . $ docker run mysql-client-tests:latest ``` -The `docker build` step will take a few minutes to complete as it needs to install all the dependencies in the image. +The `docker build` step can take several minutes because it installs toolchains and +client dependencies for multiple languages. + +Running the built container produces BATS output similar to: -Running the built container will produce output like: ```bash $ docker run mysql-client-tests:latest -updating dolt config for tests: +Updating dolt config for tests: Config successfully updated. Config successfully updated. Config successfully updated. Config successfully updated. Running mysql-client-tests: -1..4 -ok 1 python mysql.connector client -ok 2 python pymysql client -ok 3 mysql-connector-java client -ok 4 node mysql client +... +``` + +You can compile local directories by appending another `COPY` right before `go mod install` in the `dolt_build` stage. Make sure to copy the repository (i.e., `go-mysql-server`) into the stage's `/build/` directory. As long as `dolt` references the dependency, it'll automatically resolve. +```dockerfile +COPY dolt/go/go.mod /build/dolt/go/ +# COPY go-mysql-server /build/go-mysql-server +WORKDIR /build/dolt/go/ +RUN go mod download +``` + +## Target Specific Stages + +When iterating on one area (for example MariaDB CLI behavior), use `--target` to avoid +rebuilding the full multi-stage image. + +Build only the MariaDB client stage: + +```bash +$ cd +$ docker build \ + --target mariadb_clients \ + -t mysql-client-tests:mariadb-clients \ + -f dolt/integration-tests/mysql-client-tests/Dockerfile . +``` + +Inspect and validate that stage manually: + +```bash +$ docker run --rm -it --entrypoint /bin/bash mysql-client-tests:mariadb-clients +# ls -la /usr/local +# /usr/local/mariadb-10.11/bin/mariadb --version +# /usr/local/mariadb-11.8/bin/mariadb --version +# ldd /usr/local/mariadb-11.8/bin/mariadb ``` diff --git a/integration-tests/mysql-client-tests/helpers.bash b/integration-tests/mysql-client-tests/helpers.bash index afb13a5ce38..c78d5167ccf 100644 --- a/integration-tests/mysql-client-tests/helpers.bash +++ b/integration-tests/mysql-client-tests/helpers.bash @@ -1,8 +1,8 @@ setup_dolt_repo() { REPO_NAME="dolt_repo_$$" - mkdir $REPO_NAME - cd $REPO_NAME + mkdir "$REPO_NAME" + cd "$REPO_NAME" || exit dolt init @@ -13,13 +13,11 @@ setup_dolt_repo() { PORT=$( definePORT ) USER="dolt" - dolt sql -q "CREATE USER dolt@'%'; GRANT ALL ON *.* TO dolt@'%';" - dolt sql-server --host 0.0.0.0 --port=$PORT --loglevel=trace & + dolt sql -q "CREATE USER dolt@'%' IDENTIFIED BY ''; GRANT ALL ON *.* TO dolt@'%';" + dolt sql-server --host 0.0.0.0 --port="$PORT" --loglevel=trace & SERVER_PID=$! # Give the server a chance to start sleep 1 - - export MYSQL_PWD="" } teardown_dolt_repo() { @@ -28,12 +26,15 @@ teardown_dolt_repo() { } definePORT() { - getPORT="" + local portInUse + local getPORT="" + local i + for i in {0..9} do - let getPORT="($$ + $i) % (65536-1024) + 1024" - portinuse=$(lsof -i -P -n | grep LISTEN | grep $attemptedPORT | wc -l) - if [ $portinuse -eq 0 ] + ((getPORT = ($$ + i) % (65536 - 1024) + 1024)) + portInUse="$(lsof -i -P -n | grep LISTEN | grep -c "$getPORT")" + if [[ "$portInUse" -eq 0 ]] || false then echo "$getPORT" break diff --git a/integration-tests/mysql-client-tests/mariadb-install.sh b/integration-tests/mysql-client-tests/mariadb-install.sh new file mode 100644 index 00000000000..d9b6d1a0f48 --- /dev/null +++ b/integration-tests/mysql-client-tests/mariadb-install.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail +if [[ "${TRACE-0}" == "1" ]]; then + set -o xtrace +fi + +usage() { + cat <<'EOF' +Usage: mariadb-install.sh [-o output_file] [-d install_dir] + +Downloads a MariaDB bintar archive from archive.mariadb.org. +If -d is provided, the script also extracts and installs the archive directory. + +Examples: + mariadb-install.sh 11.8.3 + mariadb-install.sh -o mariadb-11.8.3.tar.gz 11.8.3 + mariadb-install.sh -o mariadb-11.8.3.tar.gz -d mariadb-11.8 11.8.3 +EOF +} + +main() { + local output_file="" + local install_dir="" + local version="" + + while getopts ":o:d:h" opt; do + case "$opt" in + o) output_file="$OPTARG" ;; + d) install_dir="$OPTARG" ;; + h) + usage + exit 0 + ;; + :) + echo "Missing value for -$OPTARG." >&2 + usage >&2 + exit 1 + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + usage >&2 + exit 1 + ;; + esac + done + shift $((OPTIND - 1)) + + if [[ "${1-}" == "" || "${2-}" != "" ]]; then + usage >&2 + exit 1 + fi + version="$1" + + local archive_name + archive_name="mariadb-${version}-linux-systemd-x86_64.tar.gz" + local url + url="https://archive.mariadb.org/mariadb-${version}/bintar-linux-systemd-x86_64/${archive_name}" + + # Use the URL basename when -o is not provided. + if [[ -z "$output_file" ]]; then + output_file="$archive_name" + fi + + curl --fail --location --silent --show-error --output "$output_file" "$url" + + # When an install directory is provided, perform extract, rename, and cleanup. + if [[ -n "$install_dir" ]]; then + local extracted_dir + extracted_dir="mariadb-${version}-linux-systemd-x86_64" + + tar -xzf "$output_file" + if [[ ! -d "$extracted_dir" ]]; then + echo "Expected extracted directory '$extracted_dir' was not found." >&2 + exit 1 + fi + if [[ -e "$install_dir" ]]; then + echo "Install directory '$install_dir' already exists." >&2 + exit 1 + fi + + mv "$extracted_dir" "$install_dir" + rm "$output_file" + fi +} + +main "$@" diff --git a/integration-tests/mysql-client-tests/mysql-client-tests-entrypoint.sh b/integration-tests/mysql-client-tests/mysql-client-tests-entrypoint.sh index fc882b109ba..a686b91fdf2 100755 --- a/integration-tests/mysql-client-tests/mysql-client-tests-entrypoint.sh +++ b/integration-tests/mysql-client-tests/mysql-client-tests-entrypoint.sh @@ -2,7 +2,7 @@ status=0 run_bats() { - bats "$1" || status=1 + bats "$@" --print-output-on-failure || status=1 } echo "Updating dolt config for tests:" diff --git a/integration-tests/mysql-client-tests/mysql-client-tests.bats b/integration-tests/mysql-client-tests/mysql-client-tests.bats index 1fbd1d4d0da..19a38a43c4c 100644 --- a/integration-tests/mysql-client-tests/mysql-client-tests.bats +++ b/integration-tests/mysql-client-tests/mysql-client-tests.bats @@ -12,6 +12,9 @@ load helpers.bash setup() { setup_dolt_repo + + export MYSQL_TCP_PORT=$PORT + export MYSQL_HOST=127.0.0.1 } teardown() { @@ -25,6 +28,42 @@ teardown() { fi } +switch_mariadb_version() { + local version="$1" + run ln -vsfn "/usr/local/mariadb-$version" /usr/local/mariadb +} + +mariadb() { + /usr/local/mariadb/bin/mariadb --protocol=tcp -vvv --show-warnings "$@" +} + +assert_mariadb_version_auth_and_db_selection() { + local version="$1" + + switch_mariadb_version "$version" + + run mariadb --version + [ "$status" -eq 0 ] + [[ "$output" =~ "$version" ]] || false + + run mariadb -e "SELECT 1;" + [ "$status" -ne 0 ] + [[ "$output" =~ "Access denied for user 'root'" ]] || false + + run mariadb --user="$USER" "$REPO_NAME" -e "SELECT 1" + [ "$status" -eq 0 ] + [[ "$output" =~ "1" ]] || false + + run mariadb --user="$USER" "$REPO_NAME" -e "SELECT DATABASE();" + [ "$status" -eq 0 ] + [[ "$output" =~ "$REPO_NAME" ]] || false +} + +@test "mariadb auth" { + assert_mariadb_version_auth_and_db_selection "10.11" + assert_mariadb_version_auth_and_db_selection "11.8" +} + @test "go go-sql-driver/mysql" { /build/bin/go/sql-driver-mysql-test $USER $PORT $REPO_NAME }