diff --git a/bin/install-package-tests b/bin/install-package-tests index 2646ebb1b..aa31ca68a 100755 --- a/bin/install-package-tests +++ b/bin/install-package-tests @@ -87,14 +87,16 @@ fi echo "Detecting database version..." -TYPE="MySQL" -CLIENT_VERSION=$(mysql --version 2>/dev/null) - -case "${CLIENT_VERSION}" in - *"MariaDB"*) - TYPE="MariaDB" - ;; -esac +# Detect which client binary is available. +CLIENT_BINARY="" +if command -v mysql >/dev/null 2>&1; then + CLIENT_BINARY="mysql" +elif command -v mariadb >/dev/null 2>&1; then + CLIENT_BINARY="mariadb" +else + echo "${C_RED}Error: Neither 'mysql' nor 'mariadb' client binary found.${NO_FORMAT}" + exit 1 +fi if [ -z "$PS1" ]; then # These vars are because github actions gave problems in the past. @@ -105,11 +107,16 @@ else MYSQL_WAIT=0 fi -if [ "${TYPE}" = "MySQL" ]; then - SERVER_VERSION=$(mysql -e "SELECT VERSION()" --skip-column-names ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}") -else - SERVER_VERSION=$(mariadb -e "SELECT VERSION()" --skip-column-names ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}") -fi +# Use the detected client binary to query the server version. +SERVER_VERSION=$(${CLIENT_BINARY} -e "SELECT VERSION()" --skip-column-names ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" 2>/dev/null) + +# Detect the database type from the server version string. +TYPE="MySQL" +case "${SERVER_VERSION}" in + *"MariaDB"*|*"mariadb"*) + TYPE="MariaDB" + ;; +esac VERSION=$(echo "${SERVER_VERSION}" | grep -o '^[^-]*') MAJOR=$(echo "${VERSION}" | cut -d. -f1) @@ -119,66 +126,49 @@ echo "Detected ${TYPE} at version ${MAJOR}.${MINOR}" echo 'Checking if database is ready...' -if [ "${TYPE}" = "MySQL" ]; then - while ! mysql ${HOST_STRING} --user="${USER}" "${PASSWORD_STRING}" --execute="SHOW DATABASES;" | grep 'information_schema' >/dev/null; - do - i=$((i+1)) - if [ "${MYSQL_TRIES}" -gt 1 ]; then - echo "Waiting for MySQL(${i}/${MYSQL_TRIES})..." - sleep ${MYSQL_WAIT} - fi - - if [ $i -ge $MYSQL_TRIES ]; then - echo "${C_RED}MySQL failed to start. Aborting.${NO_FORMAT}" - echo "Cannot connect to MySQL server. For all available variables, check the documentation at:" - echo " ${C_BLUE}https://github.com/wp-cli/wp-cli-tests?tab=readme-ov-file#the-database-credentials${NO_FORMAT}" - exit 1 - fi - done -else - while ! mariadb ${HOST_STRING} --user="${USER}" "${PASSWORD_STRING}" --execute="SHOW DATABASES;" | grep 'information_schema' >/dev/null; - do - i=$((i+1)) - if [ "${MYSQL_TRIES}" -gt 1 ]; then - echo "Waiting for MariaDB(${i}/${MYSQL_TRIES})..." - sleep ${MYSQL_WAIT} - fi +i=0 +while ! ${CLIENT_BINARY} ${HOST_STRING} --user="${USER}" "${PASSWORD_STRING}" --execute="SHOW DATABASES;" 2>/dev/null | grep 'information_schema' >/dev/null; +do + i=$((i+1)) + if [ "${MYSQL_TRIES}" -gt 1 ]; then + echo "Waiting for database server (${i}/${MYSQL_TRIES})..." + sleep ${MYSQL_WAIT} + fi - if [ $i -ge $MYSQL_TRIES ]; then - echo "${C_RED}MariaDB failed to start. Aborting.${NO_FORMAT}" - echo "Cannot connect to MariaDB server. For all available variables, check the documentation at:" - echo " ${C_BLUE}https://github.com/wp-cli/wp-cli-tests?tab=readme-ov-file#the-database-credentials${NO_FORMAT}" - exit 1 - fi - done -fi + if [ $i -ge $MYSQL_TRIES ]; then + echo "${C_RED}Database server failed to start. Aborting.${NO_FORMAT}" + echo "Cannot connect to database server. For all available variables, check the documentation at:" + echo " ${C_BLUE}https://github.com/wp-cli/wp-cli-tests?tab=readme-ov-file#the-database-credentials${NO_FORMAT}" + exit 1 + fi +done # Prepare the database for running the tests with a MySQL version 8.0 or higher. install_mysql_db_8_0_plus() { set -ex # print all the commands. - mysql -e "CREATE DATABASE IF NOT EXISTS \`${TEST_DB}\`;" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" - mysql -e "CREATE USER IF NOT EXISTS \`${TEST_USER}\`@'%' IDENTIFIED WITH caching_sha2_password BY '${TEST_PASSWORD}'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" - mysql -e "GRANT ALL PRIVILEGES ON \`${TEST_DB}\`.* TO '${TEST_USER}'@'%'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" - mysql -e "GRANT ALL PRIVILEGES ON \`${TEST_DB}_scaffold\`.* TO '${TEST_USER}'@'%'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "CREATE DATABASE IF NOT EXISTS \`${TEST_DB}\`;" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "CREATE USER IF NOT EXISTS \`${TEST_USER}\`@'%' IDENTIFIED WITH caching_sha2_password BY '${TEST_PASSWORD}'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "GRANT ALL PRIVILEGES ON \`${TEST_DB}\`.* TO '${TEST_USER}'@'%'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "GRANT ALL PRIVILEGES ON \`${TEST_DB}_scaffold\`.* TO '${TEST_USER}'@'%'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" { set +ex; } 2> /dev/null # stop printing the commands } # Prepare the database for running the tests with a MySQL version lower than 8.0. install_mysql_db_lower_than_8_0() { set -ex # print all the commands. - mysql -e "CREATE DATABASE IF NOT EXISTS \`${TEST_DB}\`;" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" - mysql -e "GRANT ALL ON \`${TEST_DB}\`.* TO '${TEST_USER}'@'%' IDENTIFIED BY '${TEST_PASSWORD}'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" - mysql -e "GRANT ALL ON \`${TEST_DB}_scaffold\`.* TO '${TEST_USER}'@'%' IDENTIFIED BY '${TEST_PASSWORD}'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "CREATE DATABASE IF NOT EXISTS \`${TEST_DB}\`;" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "GRANT ALL ON \`${TEST_DB}\`.* TO '${TEST_USER}'@'%' IDENTIFIED BY '${TEST_PASSWORD}'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "GRANT ALL ON \`${TEST_DB}_scaffold\`.* TO '${TEST_USER}'@'%' IDENTIFIED BY '${TEST_PASSWORD}'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" { set +ex; } 2> /dev/null # stop printing the commands } # Prepare the database for running the tests with MariaDB install_mariadb() { set -ex - mariadb -e "CREATE DATABASE IF NOT EXISTS \`${TEST_DB}\`;" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" - mariadb -e "CREATE USER IF NOT EXISTS \`${TEST_USER}\`@'%' IDENTIFIED BY '${TEST_PASSWORD}'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" - mariadb -e "GRANT ALL PRIVILEGES ON \`${TEST_DB}\`.* TO '${TEST_USER}'@'%'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" - mariadb -e "GRANT ALL PRIVILEGES ON \`${TEST_DB}_scaffold\`.* TO '${TEST_USER}'@'%'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "CREATE DATABASE IF NOT EXISTS \`${TEST_DB}\`;" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "CREATE USER IF NOT EXISTS \`${TEST_USER}\`@'%' IDENTIFIED BY '${TEST_PASSWORD}'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "GRANT ALL PRIVILEGES ON \`${TEST_DB}\`.* TO '${TEST_USER}'@'%'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" + ${CLIENT_BINARY} -e "GRANT ALL PRIVILEGES ON \`${TEST_DB}_scaffold\`.* TO '${TEST_USER}'@'%'" ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}" } if [ "${TYPE}" = "MariaDB" ]; then @@ -189,5 +179,5 @@ else install_mysql_db_lower_than_8_0 fi -echo "Succesfully prepared the database for running tests." +echo "Successfully prepared the database for running tests." echo "This command does not have to be run again." diff --git a/utils/behat-tags.php b/utils/behat-tags.php index c6fa9833e..4da5af53a 100644 --- a/utils/behat-tags.php +++ b/utils/behat-tags.php @@ -40,10 +40,88 @@ function version_tags( return $skip_tags; } -function get_db_version() { - $version_string = exec( getenv( 'WP_CLI_TEST_DBTYPE' ) === 'mariadb' ? 'mariadb --version' : 'mysql -V' ); +function get_db_type_and_version() { + // Detect which client binary is available. + $client_binary = null; + $output = array(); + exec( 'command -v mysql 2>/dev/null', $output, $mysql_exit_code ); + if ( 0 === $mysql_exit_code ) { + $client_binary = 'mysql'; + } else { + $output = array(); + exec( 'command -v mariadb 2>/dev/null', $output, $mariadb_exit_code ); + if ( 0 === $mariadb_exit_code ) { + $client_binary = 'mariadb'; + } + } + + if ( null === $client_binary ) { + // No client binary found, return defaults. + return array( + 'type' => 'mysql', + 'version' => '', + ); + } + + // Build connection parameters from environment variables. + $host = getenv( 'WP_CLI_TEST_DBHOST' ) ?: 'localhost'; + $user = getenv( 'WP_CLI_TEST_DBROOTUSER' ) ?: 'root'; + $pass = getenv( 'WP_CLI_TEST_DBROOTPASS' ); + + // Build the command to get the server version. + $host_parts = explode( ':', $host ); + $host_arg = '-h' . escapeshellarg( $host_parts[0] ); + + $port_arg = ''; + if ( isset( $host_parts[1] ) ) { + // Check if it's a port number or socket path. + if ( is_numeric( $host_parts[1] ) ) { + $port_arg = ' --port=' . escapeshellarg( $host_parts[1] ) . ' --protocol=tcp'; + } else { + $port_arg = ' --socket=' . escapeshellarg( $host_parts[1] ) . ' --protocol=socket'; + } + } + + $pass_arg = false !== $pass && '' !== $pass ? '-p' . escapeshellarg( $pass ) : ''; + + $cmd = sprintf( + '%s %s %s -u%s %s -e "SELECT VERSION()" --skip-column-names 2>/dev/null', + escapeshellcmd( $client_binary ), + $host_arg, + $port_arg, + escapeshellarg( $user ), + $pass_arg + ); + + $output = array(); + $return_code = 0; + exec( $cmd, $output, $return_code ); + $version_string = isset( $output[0] ) ? $output[0] : ''; + + // If the connection failed, fall back to client binary version. + if ( 0 !== $return_code || empty( $version_string ) ) { + $client_version_cmd = sprintf( '%s --version 2>/dev/null', escapeshellcmd( $client_binary ) ); + $version_string = exec( $client_version_cmd ); + } + + // Detect database type from server version string. + $db_type = 'mysql'; + if ( false !== stripos( $version_string, 'mariadb' ) ) { + $db_type = 'mariadb'; + } + preg_match( '@[0-9]+\.[0-9]+\.[0-9]+@', $version_string, $version ); - return $version[0]; + $db_version = isset( $version[0] ) ? $version[0] : ''; + + return array( + 'type' => $db_type, + 'version' => $db_version, + ); +} + +function get_db_version() { + $db_info = get_db_type_and_version(); + return $db_info['version']; } $features_folder = getenv( 'BEHAT_FEATURES_FOLDER' ) ?: 'features'; @@ -85,9 +163,13 @@ function get_db_version() { $skip_tags[] = '@broken-trunk'; } -$db_version = get_db_version(); +$db_info = get_db_type_and_version(); +$db_version = $db_info['version']; +// Use detected database type from server, unless WP_CLI_TEST_DBTYPE is 'sqlite'. +$env_db_type = getenv( 'WP_CLI_TEST_DBTYPE' ); +$db_type = 'sqlite' === $env_db_type ? 'sqlite' : $db_info['type']; -switch ( getenv( 'WP_CLI_TEST_DBTYPE' ) ) { +switch ( $db_type ) { case 'mariadb': $skip_tags = array_merge( $skip_tags,