From a0b90f7035e0501052491dbcfc84e4d1d0d00954 Mon Sep 17 00:00:00 2001 From: Jan-Willem Oostendorp Date: Thu, 13 Jun 2024 14:23:22 +0200 Subject: [PATCH 1/9] Add prepare-tests info When running composer prepare-tests and there is an errro, no usefull information is shown. Now It diesplays all the variables it uses. And when giving an error, display where to find the documentation. --- bin/install-package-tests | 59 +++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/bin/install-package-tests b/bin/install-package-tests index b683a7bfb..867544d0a 100755 --- a/bin/install-package-tests +++ b/bin/install-package-tests @@ -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="" @@ -28,65 +32,93 @@ 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 'Checking if MySQL is ready...' + +MYSQL_TRIES=36 +MYSQL_WAIT=5 while ! mysql ${HOST_STRING} --user="${USER}" "${PASSWORD_STRING}" --execute="SHOW DATABASES;" | grep 'information_schema' >/dev/null; do - echo 'Waiting for MySQL...' - sleep 5 + echo "Waiting for MySQL(${i}/${MYSQL_TRIES})..." + sleep ${MYSQL_WAIT} i=$((i+1)) - if [ $i -gt 36 ]; then - echo 'MySQL failed to start. Aborting.' + if [ $i -gt $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 # 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 mysql_native_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 } VERSION_STRING=$(mysql -e "SELECT VERSION()" --skip-column-names ${HOST_STRING} -u"${USER}" "${PASSWORD_STRING}") @@ -108,3 +140,6 @@ if [ "${TYPE}" != "MariaDB" ] && [ "${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." From bc262e29383ea3c6a24a154f108ec09f93e0db4a Mon Sep 17 00:00:00 2001 From: Jan-Willem Oostendorp Date: Thu, 13 Jun 2024 15:04:50 +0200 Subject: [PATCH 2/9] prepare tests don't do multiple attemps local. --- bin/install-package-tests | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/bin/install-package-tests b/bin/install-package-tests index 867544d0a..ae6055ee5 100755 --- a/bin/install-package-tests +++ b/bin/install-package-tests @@ -87,19 +87,29 @@ fi echo 'Checking if MySQL is ready...' -MYSQL_TRIES=36 -MYSQL_WAIT=5 +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 + while ! mysql ${HOST_STRING} --user="${USER}" "${PASSWORD_STRING}" --execute="SHOW DATABASES;" | grep 'information_schema' >/dev/null; do - echo "Waiting for MySQL(${i}/${MYSQL_TRIES})..." - sleep ${MYSQL_WAIT} - i=$((i+1)) - if [ $i -gt $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 + 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 # Prepare the database for running the tests with a MySQL version 8.0 or higher. @@ -134,7 +144,6 @@ esac echo "Detected ${TYPE} at version ${MAJOR}.${MINOR}" - if [ "${TYPE}" != "MariaDB" ] && [ "${MAJOR}" -ge 8 ]; then install_mysql_db_8_0_plus else From 928405c7a28a574fd26be99aceb63b8409b13ccd Mon Sep 17 00:00:00 2001 From: Jan-Willem Oostendorp Date: Thu, 13 Jun 2024 16:49:34 +0200 Subject: [PATCH 3/9] Add a db connection test before behat runs. --- src/Context/FeatureContext.php | 37 +++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Context/FeatureContext.php b/src/Context/FeatureContext.php index 8ceea8792..d9635e916 100644 --- a/src/Context/FeatureContext.php +++ b/src/Context/FeatureContext.php @@ -8,6 +8,7 @@ use Behat\Testwork\Hook\Scope\AfterSuiteScope; use Behat\Testwork\Hook\Scope\BeforeSuiteScope; use RuntimeException; +use WP_CLI; use WP_CLI\Process; use WP_CLI\Utils; @@ -639,6 +640,7 @@ public function __construct() { $this->variables['CORE_CONFIG_SETTINGS'] = Utils\assoc_args_to_str( self::$db_settings ); + $this->test_connection(); $this->drop_db(); $this->set_cache_dir(); } @@ -842,6 +844,8 @@ private function set_cache_dir() { * @param string $sql_cmd Command to run. * @param array $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. */ private static function run_sql( $sql_cmd, $assoc_args = [], $add_database = false ) { $default_assoc_args = [ @@ -852,11 +856,22 @@ private static function run_sql( $sql_cmd, $assoc_args = [], $add_database = fal 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'] ); + } + $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 ); if ( self::$log_run_times ) { self::log_proc_method_run_time( 'run_sql ' . $sql_cmd, $start_time ); } + return [ + 'stdout' => $result[0], + 'stderr' => $result[1], + 'exit_code' => $result[2], + ]; } public function create_db() { @@ -868,6 +883,26 @@ public function create_db() { self::run_sql( 'mysql --no-defaults', [ 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ] ); } + /** + * Test if the database connection is working. + */ + public function test_connection() { + $sql_result = self::run_sql( + 'mysql --no-defaults', + [ + 'execute' => 'SELECT 1', + 'send_to_shell' => false, + ] + ); + if ( ! empty( $sql_result['stderr'] ) ) { + # WP_CLI output functions are suppressed in behat context. + echo 'There was an error connecting to the database:' . \PHP_EOL; + echo ' ' . trim( $sql_result['stderr'] ) . \PHP_EOL; + echo 'run `composer prepare-tests` to connect to the database.' . \PHP_EOL; + die( 1 ); + } + } + public function drop_db() { if ( 'sqlite' === self::$db_type ) { return; From 32f9287da2d37cd89a606ff5e3a02d1dc15eb3f9 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 17 May 2025 14:12:16 +0200 Subject: [PATCH 4/9] use `array_combine` --- src/Context/FeatureContext.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Context/FeatureContext.php b/src/Context/FeatureContext.php index a8569ce4c..443b71d55 100644 --- a/src/Context/FeatureContext.php +++ b/src/Context/FeatureContext.php @@ -1084,8 +1084,9 @@ private function set_cache_dir(): void { * @param string $sql_cmd Command to run. * @param array $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 ) { $default_assoc_args = [ 'host' => self::$db_settings['dbhost'], 'user' => self::$db_settings['dbuser'], @@ -1105,11 +1106,8 @@ private static function run_sql( $sql_cmd, $assoc_args = [], $add_database = fal if ( self::$log_run_times ) { self::log_proc_method_run_time( 'run_sql ' . $sql_cmd, $start_time ); } - return [ - 'stdout' => $result[0], - 'stderr' => $result[1], - 'exit_code' => $result[2], - ]; + + return array_combine( [ 'stdout', 'stderr', 'exit_code' ], $result ); } public function create_db(): void { @@ -1124,7 +1122,7 @@ public function create_db(): void { /** * Test if the database connection is working. */ - public function test_connection() { + public function test_connection(): void { $sql_result = self::run_sql( 'mysql --no-defaults', [ From 82cd428a45bc0f46761627cf151881b777b0ba2a Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 17 May 2025 14:16:54 +0200 Subject: [PATCH 5/9] Don't test connection when using sqlite --- src/Context/FeatureContext.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Context/FeatureContext.php b/src/Context/FeatureContext.php index 443b71d55..6c712417b 100644 --- a/src/Context/FeatureContext.php +++ b/src/Context/FeatureContext.php @@ -1123,6 +1123,10 @@ public function create_db(): void { * Test if the database connection is working. */ public function test_connection(): void { + if ( 'sqlite' === self::$db_type ) { + return; + } + $sql_result = self::run_sql( 'mysql --no-defaults', [ From 90c4cbd16645ab6a2cc8dd42f4a4a099fdb27640 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 17 May 2025 14:17:47 +0200 Subject: [PATCH 6/9] No hardcoded binary --- src/Context/FeatureContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Context/FeatureContext.php b/src/Context/FeatureContext.php index 6c712417b..f406d7d22 100644 --- a/src/Context/FeatureContext.php +++ b/src/Context/FeatureContext.php @@ -1128,7 +1128,7 @@ public function test_connection(): void { } $sql_result = self::run_sql( - 'mysql --no-defaults', + self::$mysql_binary . '--no-defaults', [ 'execute' => 'SELECT 1', 'send_to_shell' => false, From 24d41ed6e6167891eca82b8a74468db889349bc0 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 17 May 2025 14:19:36 +0200 Subject: [PATCH 7/9] Add missing space --- src/Context/FeatureContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Context/FeatureContext.php b/src/Context/FeatureContext.php index f406d7d22..4896142fc 100644 --- a/src/Context/FeatureContext.php +++ b/src/Context/FeatureContext.php @@ -1128,7 +1128,7 @@ public function test_connection(): void { } $sql_result = self::run_sql( - self::$mysql_binary . '--no-defaults', + self::$mysql_binary . ' --no-defaults', [ 'execute' => 'SELECT 1', 'send_to_shell' => false, From e8754ff0ec74104f2bf146dd3fd41772ffe49099 Mon Sep 17 00:00:00 2001 From: Jan-Willem Oostendorp Date: Thu, 5 Jun 2025 11:38:14 +0200 Subject: [PATCH 8/9] Made a distinction between errors and warnings when checking the DB command. --- src/Context/FeatureContext.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Context/FeatureContext.php b/src/Context/FeatureContext.php index 4896142fc..d959907ca 100644 --- a/src/Context/FeatureContext.php +++ b/src/Context/FeatureContext.php @@ -1134,12 +1134,19 @@ public function test_connection(): void { 'send_to_shell' => false, ] ); - if ( ! empty( $sql_result['stderr'] ) ) { + + if ( $sql_result['exit_code'] !== 0 ) { # WP_CLI output functions are suppressed in behat context. echo 'There was an error connecting to the database:' . \PHP_EOL; - echo ' ' . trim( $sql_result['stderr'] ) . \PHP_EOL; + if ( ! empty( $sql_result['stderr'] ) ) { + echo ' ' . trim( $sql_result['stderr'] ) . \PHP_EOL; + } echo 'run `composer prepare-tests` to connect to the database.' . \PHP_EOL; - die( 1 ); + die( $sql_result['exit_code'] ); + } elseif ( ! empty( $sql_result['stderr'] ) ) { + // There is "error" output but not an exit code. + // Probably a warning, still display it. + echo trim( $sql_result['stderr'] ) . \PHP_EOL; } } From 3e53b1963943b5f0a32279ada235bd5f567e51b4 Mon Sep 17 00:00:00 2001 From: Jan-Willem Oostendorp Date: Thu, 5 Jun 2025 11:59:12 +0200 Subject: [PATCH 9/9] Yoda I must --- src/Context/FeatureContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Context/FeatureContext.php b/src/Context/FeatureContext.php index d959907ca..a721cf16b 100644 --- a/src/Context/FeatureContext.php +++ b/src/Context/FeatureContext.php @@ -1135,7 +1135,7 @@ public function test_connection(): void { ] ); - if ( $sql_result['exit_code'] !== 0 ) { + if ( 0 !== $sql_result['exit_code'] ) { # 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'] ) ) {