summaryrefslogtreecommitdiffstatshomepage
path: root/tests/phpunit/includes
diff options
context:
space:
mode:
authorJohn Blackbourn <johnbillion@git.wordpress.org>2025-01-29 18:17:34 +0000
committerJohn Blackbourn <johnbillion@git.wordpress.org>2025-01-29 18:17:34 +0000
commit9acdbb9d8db4eba90d623eefd5ad312cde140593 (patch)
tree0a5df57bf951e925b509ea84b74f54b4884c4796 /tests/phpunit/includes
parent4863a926efbf210f0773b190d06765a5c731dfc3 (diff)
downloadwordpress-9acdbb9d8db4eba90d623eefd5ad312cde140593.tar.gz
wordpress-9acdbb9d8db4eba90d623eefd5ad312cde140593.zip
Build/Test Tools: Add a retry mechanism for tests that perform external HTTP requests.
While the `skipTestOnTimeout()` method will catch a timeout and prevent it from causing a test to fail, other errors such as a failed DNS lookup or HTTPS handshake can still cause a test to unnecessarily fail. This introduces a simple retry mechanism that will hopefully further reduce the flakiness of tests that perform HTTP API requests. Fixes #62830 git-svn-id: https://develop.svn.wordpress.org/trunk@59729 602fd350-edb4-49c9-b593-d223f7449a82
Diffstat (limited to 'tests/phpunit/includes')
-rw-r--r--tests/phpunit/includes/abstract-testcase.php115
1 files changed, 115 insertions, 0 deletions
diff --git a/tests/phpunit/includes/abstract-testcase.php b/tests/phpunit/includes/abstract-testcase.php
index 224929eb37..b6c82cc066 100644
--- a/tests/phpunit/includes/abstract-testcase.php
+++ b/tests/phpunit/includes/abstract-testcase.php
@@ -1694,4 +1694,119 @@ abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase {
touch( $file );
}
+
+ /**
+ * Wrapper for `wp_safe_remote_request()` that retries on error and skips the test on timeout.
+ *
+ * @param string $url URL to retrieve.
+ * @param array $args Optional. Request arguments. Default empty array.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ protected function wp_safe_remote_request( $url, $args = array() ) {
+ return self::retry_on_error( 'wp_safe_remote_request', $url, $args );
+ }
+
+ /**
+ * Wrapper for `wp_safe_remote_get()` that retries on error and skips the test on timeout.
+ *
+ * @param string $url URL to retrieve.
+ * @param array $args Optional. Request arguments. Default empty array.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ protected function wp_safe_remote_get( $url, $args = array() ) {
+ return self::retry_on_error( 'wp_safe_remote_get', $url, $args );
+ }
+
+ /**
+ * Wrapper for `wp_safe_remote_post()` that retries on error and skips the test on timeout.
+ *
+ * @param string $url URL to retrieve.
+ * @param array $args Optional. Request arguments. Default empty array.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ protected function wp_safe_remote_post( $url, $args = array() ) {
+ return self::retry_on_error( 'wp_safe_remote_post', $url, $args );
+ }
+
+ /**
+ * Wrapper for `wp_safe_remote_head()` that retries on error and skips the test on timeout.
+ *
+ * @param string $url URL to retrieve.
+ * @param array $args Optional. Request arguments. Default empty array.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ protected function wp_safe_remote_head( $url, $args = array() ) {
+ return self::retry_on_error( 'wp_safe_remote_head', $url, $args );
+ }
+
+ /**
+ * Wrapper for `wp_remote_request()` that retries on error and skips the test on timeout.
+ *
+ * @param string $url URL to retrieve.
+ * @param array $args Optional. Request arguments. Default empty array.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ protected function wp_remote_request( $url, $args = array() ) {
+ return self::retry_on_error( 'wp_remote_request', $url, $args );
+ }
+
+ /**
+ * Wrapper for `wp_remote_get()` that retries on error and skips the test on timeout.
+ *
+ * @param string $url URL to retrieve.
+ * @param array $args Optional. Request arguments. Default empty array.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ protected function wp_remote_get( $url, $args = array() ) {
+ return self::retry_on_error( 'wp_remote_get', $url, $args );
+ }
+
+ /**
+ * Wrapper for `wp_remote_post()` that retries on error and skips the test on timeout.
+ *
+ * @param string $url URL to retrieve.
+ * @param array $args Optional. Request arguments. Default empty array.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ protected function wp_remote_post( $url, $args = array() ) {
+ return self::retry_on_error( 'wp_remote_post', $url, $args );
+ }
+
+ /**
+ * Wrapper for `wp_remote_head()` that retries on error and skips the test on timeout.
+ *
+ * @param string $url URL to retrieve.
+ * @param array $args Optional. Request arguments. Default empty array.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ protected function wp_remote_head( $url, $args = array() ) {
+ return self::retry_on_error( 'wp_remote_head', $url, $args );
+ }
+
+ /**
+ * Retries an HTTP API request up to three times and skips the test on timeout.
+ *
+ * @param callable $callback The HTTP API request function to call.
+ * @param string $url URL to retrieve.
+ * @param array $args Request arguments.
+ * @return array|WP_Error The response or WP_Error on failure.
+ */
+ private function retry_on_error( callable $callback, $url, $args ) {
+ $attempts = 0;
+
+ while ( $attempts < 3 ) {
+ $result = call_user_func( $callback, $url, $args );
+
+ if ( ! is_wp_error( $result ) ) {
+ return $result;
+ }
+
+ ++$attempts;
+ sleep( 5 );
+ }
+
+ $this->skipTestOnTimeout( $result );
+
+ return $result;
+ }
}