Skip to content
85 changes: 67 additions & 18 deletions bin/install-package-tests
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
is_numeric() {
case $1 in
''|*[!0-9]*) return 1;; # returns 1 if not numeric
*) return 0;; # returns 0 if numeric
*) return 0;; # returns 0 if numeric
esac
}
# Promt color vars.
C_RED="\033[31m"
C_BLUE="\033[34m"
NO_FORMAT="\033[0m"

HOST=localhost
PORT=""
Expand All @@ -28,36 +32,57 @@ if [ -n "${WP_CLI_TEST_DBHOST}" ]; then
if [ -n "${PORT}" ]; then
# If the port is not numeric, then we assume it is a socket path.
if is_numeric "${PORT}"; then
echo "Connecting to custom host: ${C_BLUE}${HOST}${NO_FORMAT} on port ${C_BLUE}${PORT}${NO_FORMAT}"
HOST_STRING="${HOST_STRING} --port=${PORT} --protocol=tcp"
else
echo "Connecting to custom host: ${C_BLUE}${HOST}${NO_FORMAT} on socket ${C_BLUE}${PORT}${NO_FORMAT}"
HOST_STRING="${HOST_STRING} --socket=${PORT} --protocol=socket"
fi
else
echo "Connecting to custom host: ${C_BLUE}${HOST}${NO_FORMAT}"
fi
else
echo "Connecting to default host: ${C_BLUE}${HOST}${NO_FORMAT}"
fi

USER=root
if [ -n "${WP_CLI_TEST_DBROOTUSER}" ]; then
USER="${WP_CLI_TEST_DBROOTUSER}"
echo "Connecting with custom root user: ${C_BLUE}${WP_CLI_TEST_DBROOTUSER}${NO_FORMAT}"
USER="${WP_CLI_TEST_DBROOTUSER}"
else
echo "Connecting with default root user: ${C_BLUE}${USER}${NO_FORMAT}"
fi

PASSWORD_STRING=""
if [ -n "${WP_CLI_TEST_DBROOTPASS}" ]; then
PASSWORD_STRING="-p${WP_CLI_TEST_DBROOTPASS}"
echo "Connecting with custom root password: ${C_BLUE}${WP_CLI_TEST_DBROOTPASS}${NO_FORMAT}"
PASSWORD_STRING="-p${WP_CLI_TEST_DBROOTPASS}"
else
echo "Connecting with default root password: ${C_BLUE}empty${NO_FORMAT}"
fi

TEST_DB=wp_cli_test
if [ -n "${WP_CLI_TEST_DBNAME}" ]; then
TEST_DB="${WP_CLI_TEST_DBNAME}"
echo "Using custom test database: ${C_BLUE}${WP_CLI_TEST_DBNAME}${NO_FORMAT}"
TEST_DB="${WP_CLI_TEST_DBNAME}"
else
echo "Using default test database: ${C_BLUE}${TEST_DB}${NO_FORMAT}"
fi

TEST_USER=wp_cli_test
if [ -n "${WP_CLI_TEST_DBUSER}" ]; then
TEST_USER="${WP_CLI_TEST_DBUSER}"
echo "Using custom test user: ${C_BLUE}${WP_CLI_TEST_DBUSER}${NO_FORMAT}"
TEST_USER="${WP_CLI_TEST_DBUSER}"
else
echo "Using default test user: ${C_BLUE}${TEST_USER}${NO_FORMAT}"
fi

TEST_PASSWORD=password1
if [ -n "${WP_CLI_TEST_DBPASS}" ]; then
TEST_PASSWORD="${WP_CLI_TEST_DBPASS}"
echo "Using custom test password: ${C_BLUE}${WP_CLI_TEST_DBPASS}${NO_FORMAT}"
TEST_PASSWORD="${WP_CLI_TEST_DBPASS}"
else
echo "Using default test password: ${C_BLUE}${TEST_PASSWORD}${NO_FORMAT}"
fi

echo "Detecting database version..."
Expand All @@ -71,6 +96,15 @@ case "${CLIENT_VERSION}" in
;;
esac

if [ -z "$PS1" ]; then
# These vars are because github actions gave problems in the past.
MYSQL_TRIES=36
MYSQL_WAIT=5
else
MYSQL_TRIES=1
MYSQL_WAIT=0
fi

if [ "${TYPE}" = "MySQL" ]; then
SERVER_VERSION=$(mysql -e "SELECT VERSION()" --skip-column-names ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}")
else
Expand All @@ -88,42 +122,54 @@ 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
echo 'Waiting for database...'
sleep 5
i=$((i+1))
if [ $i -gt 36 ]; then
echo 'Database failed to start. Aborting.'
exit 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
echo 'Waiting for database...'
sleep 5
i=$((i+1))
if [ $i -gt 36 ]; then
echo 'Database failed to start. Aborting.'
exit 1
if [ "${MYSQL_TRIES}" -gt 1 ]; then
echo "Waiting for MariaDB(${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

# Prepare the database for running the tests with a MySQL version 8.0 or higher.
install_mysql_db_8_0_plus() {
set -ex
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}"
{ 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
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}"
{ set +ex; } 2> /dev/null # stop printing the commands
}

# Prepare the database for running the tests with MariaDB
Expand All @@ -142,3 +188,6 @@ elif [ "${MAJOR}" -ge 8 ]; then
else
install_mysql_db_lower_than_8_0
fi

echo "Succesfully prepared the database for running tests."
echo "This command does not have to be run again."
46 changes: 44 additions & 2 deletions src/Context/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\Environment\Runtime;
use RuntimeException;
use WP_CLI;
use DirectoryIterator;
use WP_CLI\Process;
use WP_CLI\ProcessRun;
Expand Down Expand Up @@ -866,6 +867,7 @@

$this->variables['CORE_CONFIG_SETTINGS'] = Utils\assoc_args_to_str( self::$db_settings );

$this->test_connection();

Check warning on line 870 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L870

Added line #L870 was not covered by tests
$this->drop_db();
$this->set_cache_dir();
}
Expand Down Expand Up @@ -1110,8 +1112,9 @@
* @param string $sql_cmd Command to run.
* @param array<string, string> $assoc_args Optional. Associative array of options. Default empty.
* @param bool $add_database Optional. Whether to add dbname to the $sql_cmd. Default false.
* @return array{stdout: string, stderr: string, exit_code: int}
*/
private static function run_sql( $sql_cmd, $assoc_args = [], $add_database = false ): void {
private static function run_sql( $sql_cmd, $assoc_args = [], $add_database = false ) {

Check warning on line 1117 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1117

Added line #L1117 was not covered by tests
$default_assoc_args = [
'host' => self::$db_settings['dbhost'],
'user' => self::$db_settings['dbuser'],
Expand All @@ -1120,11 +1123,19 @@
if ( $add_database ) {
$sql_cmd .= ' ' . escapeshellarg( self::$db_settings['dbname'] );
}
$send_to_shell = true;
if ( isset( $assoc_args['send_to_shell'] ) ) {
$send_to_shell = (bool) $assoc_args['send_to_shell'];
unset( $assoc_args['send_to_shell'] );

Check warning on line 1129 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1126-L1129

Added lines #L1126 - L1129 were not covered by tests
}

$start_time = microtime( true );
Utils\run_mysql_command( $sql_cmd, array_merge( $assoc_args, $default_assoc_args ) );
$result = Utils\run_mysql_command( $sql_cmd, array_merge( $assoc_args, $default_assoc_args ), null, $send_to_shell );

Check warning on line 1133 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1133

Added line #L1133 was not covered by tests
if ( self::$log_run_times ) {
self::log_proc_method_run_time( 'run_sql ' . $sql_cmd, $start_time );
}

return array_combine( [ 'stdout', 'stderr', 'exit_code' ], $result );

Check warning on line 1138 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1138

Added line #L1138 was not covered by tests
}

public function create_db(): void {
Expand All @@ -1136,6 +1147,37 @@
self::run_sql( self::$mysql_binary . ' --no-defaults', [ 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ] );
}

/**
* Test if the database connection is working.
*/
public function test_connection(): void {
if ( 'sqlite' === self::$db_type ) {
return;

Check warning on line 1155 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1153-L1155

Added lines #L1153 - L1155 were not covered by tests
}

$sql_result = self::run_sql(
self::$mysql_binary . ' --no-defaults',
[
'execute' => 'SELECT 1',
'send_to_shell' => false,
]
);

Check warning on line 1164 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1158-L1164

Added lines #L1158 - L1164 were not covered by tests

if ( 0 !== $sql_result['exit_code'] ) {

Check warning on line 1166 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1166

Added line #L1166 was not covered by tests
# WP_CLI output functions are suppressed in behat context.
echo 'There was an error connecting to the database:' . \PHP_EOL;
if ( ! empty( $sql_result['stderr'] ) ) {
echo ' ' . trim( $sql_result['stderr'] ) . \PHP_EOL;

Check warning on line 1170 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1168-L1170

Added lines #L1168 - L1170 were not covered by tests
}
echo 'run `composer prepare-tests` to connect to the database.' . \PHP_EOL;
die( $sql_result['exit_code'] );
} elseif ( ! empty( $sql_result['stderr'] ) ) {

Check warning on line 1174 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1172-L1174

Added lines #L1172 - L1174 were not covered by tests
// There is "error" output but not an exit code.
// Probably a warning, still display it.
echo trim( $sql_result['stderr'] ) . \PHP_EOL;

Check warning on line 1177 in src/Context/FeatureContext.php

View check run for this annotation

Codecov / codecov/patch

src/Context/FeatureContext.php#L1177

Added line #L1177 was not covered by tests
}
}

public function drop_db(): void {
if ( 'sqlite' === self::$db_type ) {
return;
Expand Down