Skip to content

Commit 86c5d6f

Browse files
committed
Add tags for scenarios that need a stable release or a database socket
Scenarios that verify an installation against the checksums published by WordPress.org cannot pass against a build WordPress.org knows nothing about, and scenarios that connect to the database through a socket cannot pass when the database server runs in a container and is only reachable over TCP. Both currently fail for reasons unrelated to what they test. `@require-wp-stable` is filtered out when `WP_CLI_TEST_CORE_ZIP` is set and when `WP_VERSION` is `trunk` or `nightly`. `@require-mysql-socket` is filtered out when no socket can be found, looking in the same locations as the scenarios that use one. Following `@require-extension-` and the operating system tags, both are only filtered out when a feature file actually carries them, so that the filter stays limited to what the suite being run uses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CE81GsxUY597AdaMP1NXzk
1 parent ff95ded commit 86c5d6f

4 files changed

Lines changed: 222 additions & 0 deletions

File tree

‎.readme-partials/USING.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,20 @@ WP_VERSION=6.4.2 WP_CLI_TEST_CORE_ZIP=~/Downloads/wordpress-6.4.2.zip composer b
148148
Note that steps requesting an explicit version, such as `Given a WP 6.4.2 installation`, keep
149149
downloading that version from WordPress.org and ignore the archive.
150150
151+
#### Environment-specific scenarios
152+
153+
Some scenarios can only run in certain environments. Tagging them makes the test framework
154+
filter them out everywhere else, rather than having them fail for reasons unrelated to what
155+
they test.
156+
157+
* `@require-wp-stable` — the scenario needs a version of WordPress that WordPress.org knows
158+
about, such as one verifying an installation against the published checksums. It is
159+
skipped when `WP_CLI_TEST_CORE_ZIP` is set, and when `WP_VERSION` is `trunk` or `nightly`.
160+
* `@require-mysql-socket` — the scenario connects to the database through a socket. It is
161+
skipped when there is none, which is the case when the database server runs in a
162+
container and is only reachable over TCP. Set `WP_CLI_TEST_DBSOCKET` to point at the
163+
socket if it lives somewhere unusual.
164+
151165
#### WP-CLI Binary
152166
153167
You can run the tests against a specific WP-CLI binary, instead of using the one that has been built in your project's `vendor/bin` folder.

‎README.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,20 @@ WP_VERSION=6.4.2 WP_CLI_TEST_CORE_ZIP=~/Downloads/wordpress-6.4.2.zip composer b
159159
Note that steps requesting an explicit version, such as `Given a WP 6.4.2 installation`, keep
160160
downloading that version from WordPress.org and ignore the archive.
161161
162+
#### Environment-specific scenarios
163+
164+
Some scenarios can only run in certain environments. Tagging them makes the test framework
165+
filter them out everywhere else, rather than having them fail for reasons unrelated to what
166+
they test.
167+
168+
* `@require-wp-stable` — the scenario needs a version of WordPress that WordPress.org knows
169+
about, such as one verifying an installation against the published checksums. It is
170+
skipped when `WP_CLI_TEST_CORE_ZIP` is set, and when `WP_VERSION` is `trunk` or `nightly`.
171+
* `@require-mysql-socket` — the scenario connects to the database through a socket. It is
172+
skipped when there is none, which is the case when the database server runs in a
173+
container and is only reachable over TCP. Set `WP_CLI_TEST_DBSOCKET` to point at the
174+
socket if it lives somewhere unusual.
175+
162176
#### WP-CLI Binary
163177
164178
You can run the tests against a specific WP-CLI binary, instead of using the one that has been built in your project's `vendor/bin` folder.

‎tests/tests/TestBehatTags.php‎

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,4 +459,118 @@ public function test_behat_tags_skip_db_type(): void {
459459

460460
putenv( false === $env_github_token ? 'GITHUB_TOKEN' : "GITHUB_TOKEN=$env_github_token" );
461461
}
462+
463+
/**
464+
* Write a feature file carrying the given tag.
465+
*
466+
* @param string $tag
467+
*/
468+
private function write_tagged_feature( $tag ): void {
469+
file_put_contents(
470+
$this->temp_dir . DIRECTORY_SEPARATOR . 'features' . DIRECTORY_SEPARATOR . 'tagged.feature',
471+
$tag . "\nFeature: Tagged\n"
472+
);
473+
}
474+
475+
/**
476+
* Run the script with the given environment, restoring it afterwards.
477+
*
478+
* @param array<string, ?string> $env Variables to set, or null to unset.
479+
* @return string|false
480+
*/
481+
private function run_with_env( array $env ) {
482+
$previous = array();
483+
484+
foreach ( $env as $name => $value ) {
485+
$current = getenv( $name );
486+
$previous[ $name ] = false === $current ? null : $current;
487+
488+
putenv( null === $value ? $name : "{$name}={$value}" );
489+
}
490+
491+
try {
492+
return $this->run_behat_tags_script();
493+
} finally {
494+
foreach ( $previous as $name => $value ) {
495+
putenv( null === $value ? $name : "{$name}={$value}" );
496+
}
497+
}
498+
}
499+
500+
public function test_require_wp_stable_is_skipped_for_an_archive(): void {
501+
$this->write_tagged_feature( '@require-wp-stable' );
502+
503+
$output = $this->run_with_env(
504+
array(
505+
'WP_VERSION' => '6.4.2',
506+
'WP_CLI_TEST_CORE_ZIP' => $this->temp_dir . DIRECTORY_SEPARATOR . 'wordpress.zip',
507+
)
508+
);
509+
510+
$this->assertStringContainsString( '~@require-wp-stable', (string) $output );
511+
}
512+
513+
public function test_require_wp_stable_is_skipped_on_trunk(): void {
514+
$this->write_tagged_feature( '@require-wp-stable' );
515+
516+
$output = $this->run_with_env(
517+
array(
518+
'WP_VERSION' => 'trunk',
519+
'WP_CLI_TEST_CORE_ZIP' => null,
520+
)
521+
);
522+
523+
$this->assertStringContainsString( '~@require-wp-stable', (string) $output );
524+
}
525+
526+
public function test_require_wp_stable_runs_on_a_release(): void {
527+
$this->write_tagged_feature( '@require-wp-stable' );
528+
529+
$output = $this->run_with_env(
530+
array(
531+
'WP_VERSION' => '6.4.2',
532+
'WP_CLI_TEST_CORE_ZIP' => null,
533+
)
534+
);
535+
536+
$this->assertStringNotContainsString( '@require-wp-stable', (string) $output );
537+
}
538+
539+
public function test_require_mysql_socket_is_skipped_without_a_socket(): void {
540+
$this->write_tagged_feature( '@require-mysql-socket' );
541+
542+
$output = $this->run_with_env(
543+
array( 'WP_CLI_TEST_DBSOCKET' => $this->temp_dir . DIRECTORY_SEPARATOR . 'missing.sock' )
544+
);
545+
546+
$this->assertStringContainsString( '~@require-mysql-socket', (string) $output );
547+
}
548+
549+
public function test_require_mysql_socket_runs_with_a_socket(): void {
550+
$this->write_tagged_feature( '@require-mysql-socket' );
551+
552+
$socket = $this->temp_dir . DIRECTORY_SEPARATOR . 'mysql.sock';
553+
touch( $socket );
554+
555+
$output = $this->run_with_env( array( 'WP_CLI_TEST_DBSOCKET' => $socket ) );
556+
557+
$this->assertStringNotContainsString( '@require-mysql-socket', (string) $output );
558+
}
559+
560+
/**
561+
* Tags no scenario carries do not need to be filtered out.
562+
*/
563+
public function test_unused_tags_are_not_filtered_out(): void {
564+
$this->write_tagged_feature( '@some-other-tag' );
565+
566+
$output = $this->run_with_env(
567+
array(
568+
'WP_VERSION' => 'trunk',
569+
'WP_CLI_TEST_DBSOCKET' => $this->temp_dir . DIRECTORY_SEPARATOR . 'missing.sock',
570+
)
571+
);
572+
573+
$this->assertStringNotContainsString( '@require-wp-stable', (string) $output );
574+
$this->assertStringNotContainsString( '@require-mysql-socket', (string) $output );
575+
}
462576
}

‎utils/behat-tags.php‎

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,68 @@ function get_db_version() {
131131
return $db_info['version'];
132132
}
133133

134+
/**
135+
* Whether any feature file uses the given tag.
136+
*
137+
* Tags that no scenario carries do not need to be filtered out, and leaving them
138+
* out keeps the filter to what the suite being run actually uses.
139+
*
140+
* @param string $tag
141+
* @param string $features_folder
142+
* @return bool
143+
*/
144+
function tag_in_use( $tag, $features_folder = 'features' ) {
145+
$feature_files = glob( $features_folder . DIRECTORY_SEPARATOR . '*.feature' );
146+
147+
if ( empty( $feature_files ) ) {
148+
return false;
149+
}
150+
151+
foreach ( $feature_files as $feature_file ) {
152+
if ( false !== strpos( (string) file_get_contents( $feature_file ), $tag ) ) {
153+
return true;
154+
}
155+
}
156+
157+
return false;
158+
}
159+
160+
/**
161+
* Whether the database server can be reached through a socket.
162+
*
163+
* A database server running in a container is only reachable over TCP, so the
164+
* scenarios that connect through a socket cannot run against one. The locations
165+
* checked here are the same ones those scenarios look in.
166+
*
167+
* @return bool
168+
*/
169+
function has_mysql_socket() {
170+
$socket = getenv( 'WP_CLI_TEST_DBSOCKET' );
171+
172+
if ( is_string( $socket ) && '' !== $socket ) {
173+
return file_exists( $socket );
174+
}
175+
176+
// Anything but a port number after the colon in the host is a socket path.
177+
$host = getenv( 'WP_CLI_TEST_DBHOST' );
178+
179+
if ( is_string( $host ) && false !== strpos( $host, ':' ) ) {
180+
$after_colon = substr( $host, strrpos( $host, ':' ) + 1 );
181+
182+
if ( '' !== $after_colon && ! is_numeric( $after_colon ) ) {
183+
return file_exists( $after_colon );
184+
}
185+
}
186+
187+
foreach ( array( '/var/run/mysqld/mysqld.sock', '/tmp/mysql.sock' ) as $location ) {
188+
if ( file_exists( $location ) ) {
189+
return true;
190+
}
191+
}
192+
193+
return false;
194+
}
195+
134196
$features_folder = getenv( 'BEHAT_FEATURES_FOLDER' ) ?: 'features';
135197
$wp_version = getenv( 'WP_VERSION' );
136198
$wp_version_reqs = array();
@@ -176,6 +238,24 @@ function get_db_version() {
176238
$skip_tags[] = '@broken-trunk';
177239
}
178240

241+
// Some scenarios need a version of WordPress that WordPress.org knows about, such
242+
// as the ones verifying an installation against the published checksums. Neither a
243+
// development build nor an archive supplied through WP_CLI_TEST_CORE_ZIP qualifies.
244+
$core_zip = getenv( 'WP_CLI_TEST_CORE_ZIP' );
245+
if (
246+
tag_in_use( '@require-wp-stable', $features_folder )
247+
&& (
248+
( false !== $core_zip && '' !== $core_zip )
249+
|| in_array( $wp_version, array( 'nightly', 'trunk' ), true )
250+
)
251+
) {
252+
$skip_tags[] = '@require-wp-stable';
253+
}
254+
255+
if ( tag_in_use( '@require-mysql-socket', $features_folder ) && ! has_mysql_socket() ) {
256+
$skip_tags[] = '@require-mysql-socket';
257+
}
258+
179259
$db_info = get_db_type_and_version();
180260
$db_version = $db_info['version'];
181261
// Use detected database type from server, unless WP_CLI_TEST_DBTYPE is 'sqlite'.

0 commit comments

Comments
 (0)