Ticket #43218: 43218.3.diff
| File 43218.3.diff, 95.5 KB (added by , 8 years ago) |
|---|
-
phpunit.xml.dist
1 <phpunit 2 bootstrap="tests/phpunit/includes/bootstrap.php" 3 backupGlobals="false" 4 colors="true" 5 beStrictAboutTestsThatDoNotTestAnything="true" 6 > 7 <testsuites> 8 <!-- Default test suite to run all tests --> 9 <testsuite> 10 <directory suffix=".php">tests/phpunit/tests</directory> 11 <exclude>tests/phpunit/tests/actions/closures.php</exclude> 12 <exclude>tests/phpunit/tests/image/editor.php</exclude> 13 <exclude>tests/phpunit/tests/image/editorGd.php</exclude> 14 <exclude>tests/phpunit/tests/image/editorImagick.php</exclude> 15 <exclude>tests/phpunit/tests/oembed/headers.php</exclude> 16 <file phpVersion="5.3.0">tests/phpunit/tests/actions/closures.php</file> 17 <file phpVersion="5.3.0">tests/phpunit/tests/image/editor.php</file> 18 <file phpVersion="5.3.0">tests/phpunit/tests/image/editorGd.php</file> 19 <file phpVersion="5.3.0">tests/phpunit/tests/image/editorImagick.php</file> 20 <file phpVersion="5.3.0">tests/phpunit/tests/oembed/headers.php</file> 21 </testsuite> 22 </testsuites> 23 <groups> 24 <exclude> 25 <group>ajax</group> 26 <group>ms-files</group> 27 <group>ms-required</group> 28 <group>external-http</group> 29 </exclude> 30 </groups> 31 <logging> 32 <log type="junit" target="tests/phpunit/build/logs/junit.xml" logIncompleteSkipped="false"/> 33 </logging> 34 <php> 35 <const name="WP_RUN_CORE_TESTS" value="1" /> 36 </php> 37 <listeners> 38 <listener class="SpeedTrapListener" file="tests/phpunit/includes/ speed-trap-listener.php">39 <arguments> 40 <array> 41 <element key="slowThreshold"> 42 <integer>150</integer> 43 </element> 44 </array> 45 </arguments> 46 </listener> 47 </listeners> 48 <filter> 49 <whitelist addUncoveredFilesFromWhitelist="true"> 50 <directory suffix=".php">src</directory> 51 <exclude> 52 <!-- Third party library exclusions --> 53 <file>src/wp-admin/includes/class-ftp*</file> 54 <file>src/wp-admin/includes/class-pclzip.php</file> 55 <file>src/wp-admin/includes/deprecated.php</file> 56 <file>src/wp-admin/includes/ms-deprecated.php</file> 57 58 <file>src/wp-includes/atomlib.php</file> 59 <file>src/wp-includes/class-IXR.php</file> 60 <file>src/wp-includes/class-json.php</file> 61 <file>src/wp-includes/class-phpass.php</file> 62 <file>src/wp-includes/class-phpmailer.php</file> 63 <file>src/wp-includes/class-pop3.php</file> 64 <file>src/wp-includes/class-requests.php</file> 65 <file>src/wp-includes/class-simplepie.php</file> 66 <file>src/wp-includes/class-smtp.php</file> 67 <file>src/wp-includes/class-snoopy.php</file> 68 <file>src/wp-includes/deprecated.php</file> 69 <file>src/wp-includes/ms-deprecated.php</file> 70 <file>src/wp-includes/pluggable-deprecated.php</file> 71 <file>src/wp-includes/rss.php</file> 72 73 <directory suffix=".php">src/wp-includes/ID3</directory> 74 <directory suffix=".php">src/wp-includes/IXR</directory> 75 <directory suffix=".php">src/wp-includes/random_compat</directory> 76 <directory suffix=".php">src/wp-includes/Requests</directory> 77 <directory suffix=".php">src/wp-includes/SimplePie</directory> 78 <directory suffix=".php">src/wp-includes/Text</directory> 79 </exclude> 80 </whitelist> 81 </filter> 82 </phpunit> 1 <phpunit 2 bootstrap="tests/phpunit/includes/bootstrap.php" 3 backupGlobals="false" 4 colors="true" 5 beStrictAboutTestsThatDoNotTestAnything="true" 6 > 7 <testsuites> 8 <!-- Default test suite to run all tests --> 9 <testsuite> 10 <directory suffix=".php">tests/phpunit/tests</directory> 11 <exclude>tests/phpunit/tests/actions/closures.php</exclude> 12 <exclude>tests/phpunit/tests/image/editor.php</exclude> 13 <exclude>tests/phpunit/tests/image/editorGd.php</exclude> 14 <exclude>tests/phpunit/tests/image/editorImagick.php</exclude> 15 <exclude>tests/phpunit/tests/oembed/headers.php</exclude> 16 <file phpVersion="5.3.0">tests/phpunit/tests/actions/closures.php</file> 17 <file phpVersion="5.3.0">tests/phpunit/tests/image/editor.php</file> 18 <file phpVersion="5.3.0">tests/phpunit/tests/image/editorGd.php</file> 19 <file phpVersion="5.3.0">tests/phpunit/tests/image/editorImagick.php</file> 20 <file phpVersion="5.3.0">tests/phpunit/tests/oembed/headers.php</file> 21 </testsuite> 22 </testsuites> 23 <groups> 24 <exclude> 25 <group>ajax</group> 26 <group>ms-files</group> 27 <group>ms-required</group> 28 <group>external-http</group> 29 </exclude> 30 </groups> 31 <logging> 32 <log type="junit" target="tests/phpunit/build/logs/junit.xml" logIncompleteSkipped="false"/> 33 </logging> 34 <php> 35 <const name="WP_RUN_CORE_TESTS" value="1" /> 36 </php> 37 <listeners> 38 <listener class="SpeedTrapListener" file="tests/phpunit/includes/listener-loader.php"> 39 <arguments> 40 <array> 41 <element key="slowThreshold"> 42 <integer>150</integer> 43 </element> 44 </array> 45 </arguments> 46 </listener> 47 </listeners> 48 <filter> 49 <whitelist addUncoveredFilesFromWhitelist="true"> 50 <directory suffix=".php">src</directory> 51 <exclude> 52 <!-- Third party library exclusions --> 53 <file>src/wp-admin/includes/class-ftp*</file> 54 <file>src/wp-admin/includes/class-pclzip.php</file> 55 <file>src/wp-admin/includes/deprecated.php</file> 56 <file>src/wp-admin/includes/ms-deprecated.php</file> 57 58 <file>src/wp-includes/atomlib.php</file> 59 <file>src/wp-includes/class-IXR.php</file> 60 <file>src/wp-includes/class-json.php</file> 61 <file>src/wp-includes/class-phpass.php</file> 62 <file>src/wp-includes/class-phpmailer.php</file> 63 <file>src/wp-includes/class-pop3.php</file> 64 <file>src/wp-includes/class-requests.php</file> 65 <file>src/wp-includes/class-simplepie.php</file> 66 <file>src/wp-includes/class-smtp.php</file> 67 <file>src/wp-includes/class-snoopy.php</file> 68 <file>src/wp-includes/deprecated.php</file> 69 <file>src/wp-includes/ms-deprecated.php</file> 70 <file>src/wp-includes/pluggable-deprecated.php</file> 71 <file>src/wp-includes/rss.php</file> 72 73 <directory suffix=".php">src/wp-includes/ID3</directory> 74 <directory suffix=".php">src/wp-includes/IXR</directory> 75 <directory suffix=".php">src/wp-includes/random_compat</directory> 76 <directory suffix=".php">src/wp-includes/Requests</directory> 77 <directory suffix=".php">src/wp-includes/SimplePie</directory> 78 <directory suffix=".php">src/wp-includes/Text</directory> 79 </exclude> 80 </whitelist> 81 </filter> 82 </phpunit> -
tests/phpunit/includes/abstract-testcase.php
1 <?php 2 3 require_once dirname( __FILE__ ) . '/factory.php'; 4 require_once dirname( __FILE__ ) . '/trac.php'; 5 6 /** 7 * Defines a basic fixture to run multiple tests. 8 * 9 * Resets the state of the WordPress installation before and after every test. 10 * 11 * Includes utility functions and assertions useful for testing WordPress. 12 * 13 * All WordPress unit tests should inherit from this class. 14 */ 15 abstract class WP_UnitTestCase_Base extends PHPUnit_Framework_TestCase { 16 17 protected static $forced_tickets = array(); 18 protected $expected_deprecated = array(); 19 protected $caught_deprecated = array(); 20 protected $expected_doing_it_wrong = array(); 21 protected $caught_doing_it_wrong = array(); 22 23 protected static $hooks_saved = array(); 24 protected static $ignore_files; 25 26 function __isset( $name ) { 27 return 'factory' === $name; 28 } 29 30 function __get( $name ) { 31 if ( 'factory' === $name ) { 32 return self::factory(); 33 } 34 } 35 36 /** 37 * Fetches the factory object for generating WordPress fixtures. 38 * 39 * @return WP_UnitTest_Factory The fixture factory. 40 */ 41 protected static function factory() { 42 static $factory = null; 43 if ( ! $factory ) { 44 $factory = new WP_UnitTest_Factory(); 45 } 46 return $factory; 47 } 48 49 public static function get_called_class() { 50 if ( function_exists( 'get_called_class' ) ) { 51 return get_called_class(); 52 } 53 54 // PHP 5.2 only 55 $backtrace = debug_backtrace(); 56 // [0] WP_UnitTestCase::get_called_class() 57 // [1] WP_UnitTestCase::setUpBeforeClass() 58 if ( 'call_user_func' === $backtrace[2]['function'] ) { 59 return $backtrace[2]['args'][0][0]; 60 } 61 return $backtrace[2]['class']; 62 } 63 64 public static function setUpBeforeClass() { 65 global $wpdb; 66 67 $wpdb->suppress_errors = false; 68 $wpdb->show_errors = true; 69 $wpdb->db_connect(); 70 ini_set( 'display_errors', 1 ); 71 72 parent::setUpBeforeClass(); 73 74 $c = self::get_called_class(); 75 if ( ! method_exists( $c, 'wpSetUpBeforeClass' ) ) { 76 self::commit_transaction(); 77 return; 78 } 79 80 call_user_func( array( $c, 'wpSetUpBeforeClass' ), self::factory() ); 81 82 self::commit_transaction(); 83 } 84 85 public static function tearDownAfterClass() { 86 parent::tearDownAfterClass(); 87 88 _delete_all_data(); 89 self::flush_cache(); 90 91 $c = self::get_called_class(); 92 if ( ! method_exists( $c, 'wpTearDownAfterClass' ) ) { 93 self::commit_transaction(); 94 return; 95 } 96 97 call_user_func( array( $c, 'wpTearDownAfterClass' ) ); 98 99 self::commit_transaction(); 100 } 101 102 function setUp() { 103 set_time_limit( 0 ); 104 105 if ( ! self::$ignore_files ) { 106 self::$ignore_files = $this->scan_user_uploads(); 107 } 108 109 if ( ! self::$hooks_saved ) { 110 $this->_backup_hooks(); 111 } 112 113 global $wp_rewrite; 114 115 $this->clean_up_global_scope(); 116 117 /* 118 * When running core tests, ensure that post types and taxonomies 119 * are reset for each test. We skip this step for non-core tests, 120 * given the large number of plugins that register post types and 121 * taxonomies at 'init'. 122 */ 123 if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) { 124 $this->reset_post_types(); 125 $this->reset_taxonomies(); 126 $this->reset_post_statuses(); 127 $this->reset__SERVER(); 128 129 if ( $wp_rewrite->permalink_structure ) { 130 $this->set_permalink_structure( '' ); 131 } 132 } 133 134 $this->start_transaction(); 135 $this->expectDeprecated(); 136 add_filter( 'wp_die_handler', array( $this, 'get_wp_die_handler' ) ); 137 } 138 139 /** 140 * Detect post-test failure conditions. 141 * 142 * We use this method to detect expectedDeprecated and expectedIncorrectUsage annotations. 143 * 144 * @since 4.2.0 145 */ 146 protected function assertPostConditions() { 147 $this->expectedDeprecated(); 148 } 149 150 /** 151 * After a test method runs, reset any state in WordPress the test method might have changed. 152 */ 153 function tearDown() { 154 global $wpdb, $wp_query, $wp; 155 $wpdb->query( 'ROLLBACK' ); 156 if ( is_multisite() ) { 157 while ( ms_is_switched() ) { 158 restore_current_blog(); 159 } 160 } 161 $wp_query = new WP_Query(); 162 $wp = new WP(); 163 164 // Reset globals related to the post loop and `setup_postdata()`. 165 $post_globals = array( 'post', 'id', 'authordata', 'currentday', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages' ); 166 foreach ( $post_globals as $global ) { 167 $GLOBALS[ $global ] = null; 168 } 169 170 remove_theme_support( 'html5' ); 171 remove_filter( 'query', array( $this, '_create_temporary_tables' ) ); 172 remove_filter( 'query', array( $this, '_drop_temporary_tables' ) ); 173 remove_filter( 'wp_die_handler', array( $this, 'get_wp_die_handler' ) ); 174 $this->_restore_hooks(); 175 wp_set_current_user( 0 ); 176 } 177 178 function clean_up_global_scope() { 179 $_GET = array(); 180 $_POST = array(); 181 self::flush_cache(); 182 } 183 184 /** 185 * Allow tests to be skipped on some automated runs 186 * 187 * For test runs on Travis for something other than trunk/master 188 * we want to skip tests that only need to run for master. 189 */ 190 public function skipOnAutomatedBranches() { 191 // gentenv can be disabled 192 if ( ! function_exists( 'getenv' ) ) { 193 return false; 194 } 195 196 // https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables 197 $travis_branch = getenv( 'TRAVIS_BRANCH' ); 198 $travis_pull_request = getenv( 'TRAVIS_PULL_REQUEST' ); 199 200 if ( false !== $travis_pull_request && 'master' !== $travis_branch ) { 201 $this->markTestSkipped( 'For automated test runs, this test is only run on trunk/master' ); 202 } 203 } 204 205 /** 206 * Allow tests to be skipped when Multisite is not in use. 207 * 208 * Use in conjunction with the ms-required group. 209 */ 210 public function skipWithoutMultisite() { 211 if ( ! is_multisite() ) { 212 $this->markTestSkipped( 'Test only runs on Multisite' ); 213 } 214 } 215 216 /** 217 * Allow tests to be skipped when Multisite is in use. 218 * 219 * Use in conjunction with the ms-excluded group. 220 */ 221 public function skipWithMultisite() { 222 if ( is_multisite() ) { 223 $this->markTestSkipped( 'Test does not run on Multisite' ); 224 } 225 } 226 227 /** 228 * Unregister existing post types and register defaults. 229 * 230 * Run before each test in order to clean up the global scope, in case 231 * a test forgets to unregister a post type on its own, or fails before 232 * it has a chance to do so. 233 */ 234 protected function reset_post_types() { 235 foreach ( get_post_types( array(), 'objects' ) as $pt ) { 236 if ( empty( $pt->tests_no_auto_unregister ) ) { 237 _unregister_post_type( $pt->name ); 238 } 239 } 240 create_initial_post_types(); 241 } 242 243 /** 244 * Unregister existing taxonomies and register defaults. 245 * 246 * Run before each test in order to clean up the global scope, in case 247 * a test forgets to unregister a taxonomy on its own, or fails before 248 * it has a chance to do so. 249 */ 250 protected function reset_taxonomies() { 251 foreach ( get_taxonomies() as $tax ) { 252 _unregister_taxonomy( $tax ); 253 } 254 create_initial_taxonomies(); 255 } 256 257 /** 258 * Unregister non-built-in post statuses. 259 */ 260 protected function reset_post_statuses() { 261 foreach ( get_post_stati( array( '_builtin' => false ) ) as $post_status ) { 262 _unregister_post_status( $post_status ); 263 } 264 } 265 266 /** 267 * Reset `$_SERVER` variables 268 */ 269 protected function reset__SERVER() { 270 tests_reset__SERVER(); 271 } 272 273 /** 274 * Saves the action and filter-related globals so they can be restored later. 275 * 276 * Stores $merged_filters, $wp_actions, $wp_current_filter, and $wp_filter 277 * on a class variable so they can be restored on tearDown() using _restore_hooks(). 278 * 279 * @global array $merged_filters 280 * @global array $wp_actions 281 * @global array $wp_current_filter 282 * @global array $wp_filter 283 * @return void 284 */ 285 protected function _backup_hooks() { 286 $globals = array( 'wp_actions', 'wp_current_filter' ); 287 foreach ( $globals as $key ) { 288 self::$hooks_saved[ $key ] = $GLOBALS[ $key ]; 289 } 290 self::$hooks_saved['wp_filter'] = array(); 291 foreach ( $GLOBALS['wp_filter'] as $hook_name => $hook_object ) { 292 self::$hooks_saved['wp_filter'][ $hook_name ] = clone $hook_object; 293 } 294 } 295 296 /** 297 * Restores the hook-related globals to their state at setUp() 298 * so that future tests aren't affected by hooks set during this last test. 299 * 300 * @global array $merged_filters 301 * @global array $wp_actions 302 * @global array $wp_current_filter 303 * @global array $wp_filter 304 * @return void 305 */ 306 protected function _restore_hooks() { 307 $globals = array( 'wp_actions', 'wp_current_filter' ); 308 foreach ( $globals as $key ) { 309 if ( isset( self::$hooks_saved[ $key ] ) ) { 310 $GLOBALS[ $key ] = self::$hooks_saved[ $key ]; 311 } 312 } 313 if ( isset( self::$hooks_saved['wp_filter'] ) ) { 314 $GLOBALS['wp_filter'] = array(); 315 foreach ( self::$hooks_saved['wp_filter'] as $hook_name => $hook_object ) { 316 $GLOBALS['wp_filter'][ $hook_name ] = clone $hook_object; 317 } 318 } 319 } 320 321 static function flush_cache() { 322 global $wp_object_cache; 323 $wp_object_cache->group_ops = array(); 324 $wp_object_cache->stats = array(); 325 $wp_object_cache->memcache_debug = array(); 326 $wp_object_cache->cache = array(); 327 if ( method_exists( $wp_object_cache, '__remoteset' ) ) { 328 $wp_object_cache->__remoteset(); 329 } 330 wp_cache_flush(); 331 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details' ) ); 332 wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) ); 333 } 334 335 function start_transaction() { 336 global $wpdb; 337 $wpdb->query( 'SET autocommit = 0;' ); 338 $wpdb->query( 'START TRANSACTION;' ); 339 add_filter( 'query', array( $this, '_create_temporary_tables' ) ); 340 add_filter( 'query', array( $this, '_drop_temporary_tables' ) ); 341 } 342 343 /** 344 * Commit the queries in a transaction. 345 * 346 * @since 4.1.0 347 */ 348 public static function commit_transaction() { 349 global $wpdb; 350 $wpdb->query( 'COMMIT;' ); 351 } 352 353 function _create_temporary_tables( $query ) { 354 if ( 'CREATE TABLE' === substr( trim( $query ), 0, 12 ) ) { 355 return substr_replace( trim( $query ), 'CREATE TEMPORARY TABLE', 0, 12 ); 356 } 357 return $query; 358 } 359 360 function _drop_temporary_tables( $query ) { 361 if ( 'DROP TABLE' === substr( trim( $query ), 0, 10 ) ) { 362 return substr_replace( trim( $query ), 'DROP TEMPORARY TABLE', 0, 10 ); 363 } 364 return $query; 365 } 366 367 function get_wp_die_handler( $handler ) { 368 return array( $this, 'wp_die_handler' ); 369 } 370 371 function wp_die_handler( $message ) { 372 if ( ! is_scalar( $message ) ) { 373 $message = '0'; 374 } 375 376 throw new WPDieException( $message ); 377 } 378 379 function expectDeprecated() { 380 $annotations = $this->getAnnotations(); 381 foreach ( array( 'class', 'method' ) as $depth ) { 382 if ( ! empty( $annotations[ $depth ]['expectedDeprecated'] ) ) { 383 $this->expected_deprecated = array_merge( $this->expected_deprecated, $annotations[ $depth ]['expectedDeprecated'] ); 384 } 385 if ( ! empty( $annotations[ $depth ]['expectedIncorrectUsage'] ) ) { 386 $this->expected_doing_it_wrong = array_merge( $this->expected_doing_it_wrong, $annotations[ $depth ]['expectedIncorrectUsage'] ); 387 } 388 } 389 add_action( 'deprecated_function_run', array( $this, 'deprecated_function_run' ) ); 390 add_action( 'deprecated_argument_run', array( $this, 'deprecated_function_run' ) ); 391 add_action( 'deprecated_hook_run', array( $this, 'deprecated_function_run' ) ); 392 add_action( 'doing_it_wrong_run', array( $this, 'doing_it_wrong_run' ) ); 393 add_action( 'deprecated_function_trigger_error', '__return_false' ); 394 add_action( 'deprecated_argument_trigger_error', '__return_false' ); 395 add_action( 'deprecated_hook_trigger_error', '__return_false' ); 396 add_action( 'doing_it_wrong_trigger_error', '__return_false' ); 397 } 398 399 function expectedDeprecated() { 400 $errors = array(); 401 402 $not_caught_deprecated = array_diff( $this->expected_deprecated, $this->caught_deprecated ); 403 foreach ( $not_caught_deprecated as $not_caught ) { 404 $errors[] = "Failed to assert that $not_caught triggered a deprecated notice"; 405 } 406 407 $unexpected_deprecated = array_diff( $this->caught_deprecated, $this->expected_deprecated ); 408 foreach ( $unexpected_deprecated as $unexpected ) { 409 $errors[] = "Unexpected deprecated notice for $unexpected"; 410 } 411 412 $not_caught_doing_it_wrong = array_diff( $this->expected_doing_it_wrong, $this->caught_doing_it_wrong ); 413 foreach ( $not_caught_doing_it_wrong as $not_caught ) { 414 $errors[] = "Failed to assert that $not_caught triggered an incorrect usage notice"; 415 } 416 417 $unexpected_doing_it_wrong = array_diff( $this->caught_doing_it_wrong, $this->expected_doing_it_wrong ); 418 foreach ( $unexpected_doing_it_wrong as $unexpected ) { 419 $errors[] = "Unexpected incorrect usage notice for $unexpected"; 420 } 421 422 // Perform an assertion, but only if there are expected or unexpected deprecated calls or wrongdoings 423 if ( ! empty( $this->expected_deprecated ) || 424 ! empty( $this->expected_doing_it_wrong ) || 425 ! empty( $this->caught_deprecated ) || 426 ! empty( $this->caught_doing_it_wrong ) ) { 427 $this->assertEmpty( $errors, implode( "\n", $errors ) ); 428 } 429 } 430 431 /** 432 * Declare an expected `_deprecated_function()` or `_deprecated_argument()` call from within a test. 433 * 434 * @since 4.2.0 435 * 436 * @param string $deprecated Name of the function, method, class, or argument that is deprecated. Must match 437 * first parameter of the `_deprecated_function()` or `_deprecated_argument()` call. 438 */ 439 public function setExpectedDeprecated( $deprecated ) { 440 array_push( $this->expected_deprecated, $deprecated ); 441 } 442 443 /** 444 * Declare an expected `_doing_it_wrong()` call from within a test. 445 * 446 * @since 4.2.0 447 * 448 * @param string $deprecated Name of the function, method, or class that appears in the first argument of the 449 * source `_doing_it_wrong()` call. 450 */ 451 public function setExpectedIncorrectUsage( $doing_it_wrong ) { 452 array_push( $this->expected_doing_it_wrong, $doing_it_wrong ); 453 } 454 455 /** 456 * PHPUnit 6+ compatibility shim. 457 * 458 * @param mixed $exception 459 * @param string $message 460 * @param int|string $code 461 */ 462 public function setExpectedException( $exception, $message = '', $code = null ) { 463 if ( method_exists( 'PHPUnit_Framework_TestCase', 'setExpectedException' ) ) { 464 parent::setExpectedException( $exception, $message, $code ); 465 } else { 466 $this->expectException( $exception ); 467 if ( '' !== $message ) { 468 $this->expectExceptionMessage( $message ); 469 } 470 if ( null !== $code ) { 471 $this->expectExceptionCode( $code ); 472 } 473 } 474 } 475 476 function deprecated_function_run( $function ) { 477 if ( ! in_array( $function, $this->caught_deprecated ) ) { 478 $this->caught_deprecated[] = $function; 479 } 480 } 481 482 function doing_it_wrong_run( $function ) { 483 if ( ! in_array( $function, $this->caught_doing_it_wrong ) ) { 484 $this->caught_doing_it_wrong[] = $function; 485 } 486 } 487 488 function assertWPError( $actual, $message = '' ) { 489 $this->assertInstanceOf( 'WP_Error', $actual, $message ); 490 } 491 492 function assertNotWPError( $actual, $message = '' ) { 493 if ( is_wp_error( $actual ) && '' === $message ) { 494 $message = $actual->get_error_message(); 495 } 496 $this->assertNotInstanceOf( 'WP_Error', $actual, $message ); 497 } 498 499 function assertIXRError( $actual, $message = '' ) { 500 $this->assertInstanceOf( 'IXR_Error', $actual, $message ); 501 } 502 503 function assertNotIXRError( $actual, $message = '' ) { 504 if ( $actual instanceof IXR_Error && '' === $message ) { 505 $message = $actual->message; 506 } 507 $this->assertNotInstanceOf( 'IXR_Error', $actual, $message ); 508 } 509 510 function assertEqualFields( $object, $fields ) { 511 foreach ( $fields as $field_name => $field_value ) { 512 if ( $object->$field_name != $field_value ) { 513 $this->fail(); 514 } 515 } 516 } 517 518 function assertDiscardWhitespace( $expected, $actual ) { 519 $this->assertEquals( preg_replace( '/\s*/', '', $expected ), preg_replace( '/\s*/', '', $actual ) ); 520 } 521 522 /** 523 * Asserts that the contents of two un-keyed, single arrays are equal, without accounting for the order of elements. 524 * 525 * @since 3.5.0 526 * 527 * @param array $expected Expected array. 528 * @param array $actual Array to check. 529 */ 530 function assertEqualSets( $expected, $actual ) { 531 sort( $expected ); 532 sort( $actual ); 533 $this->assertEquals( $expected, $actual ); 534 } 535 536 /** 537 * Asserts that the contents of two keyed, single arrays are equal, without accounting for the order of elements. 538 * 539 * @since 4.1.0 540 * 541 * @param array $expected Expected array. 542 * @param array $actual Array to check. 543 */ 544 function assertEqualSetsWithIndex( $expected, $actual ) { 545 ksort( $expected ); 546 ksort( $actual ); 547 $this->assertEquals( $expected, $actual ); 548 } 549 550 /** 551 * Asserts that the given variable is a multidimensional array, and that all arrays are non-empty. 552 * 553 * @since 4.8.0 554 * 555 * @param array $array Array to check. 556 */ 557 function assertNonEmptyMultidimensionalArray( $array ) { 558 $this->assertTrue( is_array( $array ) ); 559 $this->assertNotEmpty( $array ); 560 561 foreach ( $array as $sub_array ) { 562 $this->assertTrue( is_array( $sub_array ) ); 563 $this->assertNotEmpty( $sub_array ); 564 } 565 } 566 567 /** 568 * Sets the global state to as if a given URL has been requested. 569 * 570 * This sets: 571 * - The super globals. 572 * - The globals. 573 * - The query variables. 574 * - The main query. 575 * 576 * @since 3.5.0 577 * 578 * @param string $url The URL for the request. 579 */ 580 function go_to( $url ) { 581 // note: the WP and WP_Query classes like to silently fetch parameters 582 // from all over the place (globals, GET, etc), which makes it tricky 583 // to run them more than once without very carefully clearing everything 584 $_GET = $_POST = array(); 585 foreach ( array( 'query_string', 'id', 'postdata', 'authordata', 'day', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages', 'pagenow' ) as $v ) { 586 if ( isset( $GLOBALS[ $v ] ) ) { 587 unset( $GLOBALS[ $v ] ); 588 } 589 } 590 $parts = parse_url( $url ); 591 if ( isset( $parts['scheme'] ) ) { 592 $req = isset( $parts['path'] ) ? $parts['path'] : ''; 593 if ( isset( $parts['query'] ) ) { 594 $req .= '?' . $parts['query']; 595 // parse the url query vars into $_GET 596 parse_str( $parts['query'], $_GET ); 597 } 598 } else { 599 $req = $url; 600 } 601 if ( ! isset( $parts['query'] ) ) { 602 $parts['query'] = ''; 603 } 604 605 $_SERVER['REQUEST_URI'] = $req; 606 unset( $_SERVER['PATH_INFO'] ); 607 608 self::flush_cache(); 609 unset( $GLOBALS['wp_query'], $GLOBALS['wp_the_query'] ); 610 $GLOBALS['wp_the_query'] = new WP_Query(); 611 $GLOBALS['wp_query'] = $GLOBALS['wp_the_query']; 612 613 $public_query_vars = $GLOBALS['wp']->public_query_vars; 614 $private_query_vars = $GLOBALS['wp']->private_query_vars; 615 616 $GLOBALS['wp'] = new WP(); 617 $GLOBALS['wp']->public_query_vars = $public_query_vars; 618 $GLOBALS['wp']->private_query_vars = $private_query_vars; 619 620 _cleanup_query_vars(); 621 622 $GLOBALS['wp']->main( $parts['query'] ); 623 } 624 625 /** 626 * Allows tests to be skipped on single or multisite installs by using @group annotations. 627 * 628 * This is a custom extension of the PHPUnit requirements handling. 629 * 630 * Contains legacy code for skipping tests that are associated with an open Trac ticket. Core tests no longer 631 * support this behaviour. 632 * 633 * @since 3.5.0 634 */ 635 protected function checkRequirements() { 636 parent::checkRequirements(); 637 638 $annotations = $this->getAnnotations(); 639 640 if ( ! empty( $annotations['group'] ) ) { 641 if ( in_array( 'ms-required', $annotations['group'], true ) ) { 642 $this->skipWithoutMultisite(); 643 } 644 if ( in_array( 'ms-excluded', $annotations['group'], true ) ) { 645 $this->skipWithMultisite(); 646 } 647 } 648 649 // Core tests no longer check against open Trac tickets, but others using WP_UnitTestCase may do so. 650 if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) { 651 return; 652 } 653 654 if ( WP_TESTS_FORCE_KNOWN_BUGS ) { 655 return; 656 } 657 $tickets = PHPUnit_Util_Test::getTickets( get_class( $this ), $this->getName( false ) ); 658 foreach ( $tickets as $ticket ) { 659 if ( is_numeric( $ticket ) ) { 660 $this->knownWPBug( $ticket ); 661 } elseif ( 'Plugin' == substr( $ticket, 0, 6 ) ) { 662 $ticket = substr( $ticket, 6 ); 663 if ( $ticket && is_numeric( $ticket ) ) { 664 $this->knownPluginBug( $ticket ); 665 } 666 } 667 } 668 } 669 670 /** 671 * Skips the current test if there is an open Trac ticket associated with it. 672 * 673 * @since 3.5.0 674 * 675 * @param int $ticket_id Ticket number. 676 */ 677 function knownWPBug( $ticket_id ) { 678 if ( WP_TESTS_FORCE_KNOWN_BUGS || in_array( $ticket_id, self::$forced_tickets ) ) { 679 return; 680 } 681 if ( ! TracTickets::isTracTicketClosed( 'https://core.trac.wordpress.org', $ticket_id ) ) { 682 $this->markTestSkipped( sprintf( 'WordPress Ticket #%d is not fixed', $ticket_id ) ); 683 } 684 } 685 686 /** 687 * Skips the current test if there is an open Unit Test Trac ticket associated with it. 688 * 689 * @since 3.5.0 690 * 691 * @deprecated No longer used since the Unit Test Trac was merged into the Core Trac. 692 * 693 * @param int $ticket_id Ticket number. 694 */ 695 function knownUTBug( $ticket_id ) { 696 return; 697 } 698 699 /** 700 * Skips the current test if there is an open Plugin Trac ticket associated with it. 701 * 702 * @since 3.5.0 703 * 704 * @param int $ticket_id Ticket number. 705 */ 706 function knownPluginBug( $ticket_id ) { 707 if ( WP_TESTS_FORCE_KNOWN_BUGS || in_array( 'Plugin' . $ticket_id, self::$forced_tickets ) ) { 708 return; 709 } 710 if ( ! TracTickets::isTracTicketClosed( 'https://plugins.trac.wordpress.org', $ticket_id ) ) { 711 $this->markTestSkipped( sprintf( 'WordPress Plugin Ticket #%d is not fixed', $ticket_id ) ); 712 } 713 } 714 715 /** 716 * Adds a Trac ticket number to the `$forced_tickets` property. 717 * 718 * @since 3.5.0 719 * 720 * @param int $ticket Ticket number. 721 */ 722 public static function forceTicket( $ticket ) { 723 self::$forced_tickets[] = $ticket; 724 } 725 726 /** 727 * Custom preparations for the PHPUnit process isolation template. 728 * 729 * When restoring global state between tests, PHPUnit defines all the constants that were already defined, and then 730 * includes included files. This does not work with WordPress, as the included files define the constants. 731 * 732 * This method defines the constants after including files. 733 * 734 * @param Text_Template $template 735 */ 736 function prepareTemplate( Text_Template $template ) { 737 $template->setVar( array( 'constants' => '' ) ); 738 $template->setVar( array( 'wp_constants' => PHPUnit_Util_GlobalState::getConstantsAsString() ) ); 739 parent::prepareTemplate( $template ); 740 } 741 742 /** 743 * Creates a unique temporary file name. 744 * 745 * The directory in which the file is created depends on the environment configuration. 746 * 747 * @since 3.5.0 748 * 749 * @return string|bool Path on success, else false. 750 */ 751 function temp_filename() { 752 $tmp_dir = ''; 753 $dirs = array( 'TMP', 'TMPDIR', 'TEMP' ); 754 foreach ( $dirs as $dir ) { 755 if ( isset( $_ENV[ $dir ] ) && ! empty( $_ENV[ $dir ] ) ) { 756 $tmp_dir = $dir; 757 break; 758 } 759 } 760 if ( empty( $tmp_dir ) ) { 761 $tmp_dir = '/tmp'; 762 } 763 $tmp_dir = realpath( $tmp_dir ); 764 return tempnam( $tmp_dir, 'wpunit' ); 765 } 766 767 /** 768 * Checks each of the WP_Query is_* functions/properties against expected boolean value. 769 * 770 * Any properties that are listed by name as parameters will be expected to be true; all others are 771 * expected to be false. For example, assertQueryTrue('is_single', 'is_feed') means is_single() 772 * and is_feed() must be true and everything else must be false to pass. 773 * 774 * @since 2.5.0 775 * @since 3.8.0 Moved from `Tests_Query_Conditionals` to `WP_UnitTestCase`. 776 * 777 * @param string $prop,... Any number of WP_Query properties that are expected to be true for the current request. 778 */ 779 function assertQueryTrue() { 780 global $wp_query; 781 $all = array( 782 'is_404', 783 'is_admin', 784 'is_archive', 785 'is_attachment', 786 'is_author', 787 'is_category', 788 'is_comment_feed', 789 'is_date', 790 'is_day', 791 'is_embed', 792 'is_feed', 793 'is_front_page', 794 'is_home', 795 'is_month', 796 'is_page', 797 'is_paged', 798 'is_post_type_archive', 799 'is_posts_page', 800 'is_preview', 801 'is_robots', 802 'is_search', 803 'is_single', 804 'is_singular', 805 'is_tag', 806 'is_tax', 807 'is_time', 808 'is_trackback', 809 'is_year', 810 ); 811 $true = func_get_args(); 812 813 foreach ( $true as $true_thing ) { 814 $this->assertContains( $true_thing, $all, "Unknown conditional: {$true_thing}." ); 815 } 816 817 $passed = true; 818 $message = ''; 819 820 foreach ( $all as $query_thing ) { 821 $result = is_callable( $query_thing ) ? call_user_func( $query_thing ) : $wp_query->$query_thing; 822 823 if ( in_array( $query_thing, $true ) ) { 824 if ( ! $result ) { 825 $message .= $query_thing . ' is false but is expected to be true. ' . PHP_EOL; 826 $passed = false; 827 } 828 } elseif ( $result ) { 829 $message .= $query_thing . ' is true but is expected to be false. ' . PHP_EOL; 830 $passed = false; 831 } 832 } 833 834 if ( ! $passed ) { 835 $this->fail( $message ); 836 } 837 } 838 839 /** 840 * Selectively deletes a file. 841 * 842 * Does not delete a file if its path is set in the `$ignore_files` property. 843 * 844 * @param string $file File path. 845 */ 846 function unlink( $file ) { 847 $exists = is_file( $file ); 848 if ( $exists && ! in_array( $file, self::$ignore_files ) ) { 849 //error_log( $file ); 850 unlink( $file ); 851 } elseif ( ! $exists ) { 852 $this->fail( "Trying to delete a file that doesn't exist: $file" ); 853 } 854 } 855 856 /** 857 * Selectively deletes files from a directory. 858 * 859 * Does not delete files if their paths are set in the `$ignore_files` property. 860 * 861 * @param string $path Directory path. 862 */ 863 function rmdir( $path ) { 864 $files = $this->files_in_dir( $path ); 865 foreach ( $files as $file ) { 866 if ( ! in_array( $file, self::$ignore_files ) ) { 867 $this->unlink( $file ); 868 } 869 } 870 } 871 872 /** 873 * Deletes files added to the `uploads` directory during tests. 874 * 875 * This method works in tandem with the `setUp()` and `rmdir()` methods: 876 * - `setUp()` scans the `uploads` directory before every test, and stores its contents inside of the 877 * `$ignore_files` property. 878 * - `rmdir()` and its helper methods only delete files that are not listed in the `$ignore_files` property. If 879 * called during `tearDown()` in tests, this will only delete files added during the previously run test. 880 */ 881 function remove_added_uploads() { 882 $uploads = wp_upload_dir(); 883 $this->rmdir( $uploads['basedir'] ); 884 } 885 886 /** 887 * Returns a list of all files contained inside a directory. 888 * 889 * @since 4.0.0 890 * 891 * @param string $dir Path to the directory to scan. 892 * 893 * @return array List of file paths. 894 */ 895 function files_in_dir( $dir ) { 896 $files = array(); 897 898 $iterator = new RecursiveDirectoryIterator( $dir ); 899 $objects = new RecursiveIteratorIterator( $iterator ); 900 foreach ( $objects as $name => $object ) { 901 if ( is_file( $name ) ) { 902 $files[] = $name; 903 } 904 } 905 906 return $files; 907 } 908 909 /** 910 * Returns a list of all files contained inside the `uploads` directory. 911 * 912 * @since 4.0.0 913 * 914 * @return array List of file paths. 915 */ 916 function scan_user_uploads() { 917 static $files = array(); 918 if ( ! empty( $files ) ) { 919 return $files; 920 } 921 922 $uploads = wp_upload_dir(); 923 $files = $this->files_in_dir( $uploads['basedir'] ); 924 return $files; 925 } 926 927 /** 928 * Deletes all directories contained inside a directory. 929 * 930 * @since 4.1.0 931 * 932 * @param string $path Path to the directory to scan. 933 */ 934 function delete_folders( $path ) { 935 $this->matched_dirs = array(); 936 if ( ! is_dir( $path ) ) { 937 return; 938 } 939 940 $this->scandir( $path ); 941 foreach ( array_reverse( $this->matched_dirs ) as $dir ) { 942 rmdir( $dir ); 943 } 944 rmdir( $path ); 945 } 946 947 /** 948 * Retrieves all directories contained inside a directory and stores them in the `$matched_dirs` property. Hidden 949 * directories are ignored. 950 * 951 * This is a helper for the `delete_folders()` method. 952 * 953 * @since 4.1.0 954 * 955 * @param string $dir Path to the directory to scan. 956 */ 957 function scandir( $dir ) { 958 foreach ( scandir( $dir ) as $path ) { 959 if ( 0 !== strpos( $path, '.' ) && is_dir( $dir . '/' . $path ) ) { 960 $this->matched_dirs[] = $dir . '/' . $path; 961 $this->scandir( $dir . '/' . $path ); 962 } 963 } 964 } 965 966 /** 967 * Converts a microtime string into a float. 968 * 969 * @since 4.1.0 970 * 971 * @param string $microtime Time string generated by `microtime()`. 972 * 973 * @return float `microtime()` output as a float. 974 */ 975 protected function _microtime_to_float( $microtime ) { 976 $time_array = explode( ' ', $microtime ); 977 return array_sum( $time_array ); 978 } 979 980 /** 981 * Deletes a user from the database in a Multisite-agnostic way. 982 * 983 * @since 4.3.0 984 * 985 * @param int $user_id User ID. 986 * 987 * @return bool True if the user was deleted. 988 */ 989 public static function delete_user( $user_id ) { 990 if ( is_multisite() ) { 991 return wpmu_delete_user( $user_id ); 992 } else { 993 return wp_delete_user( $user_id ); 994 } 995 } 996 997 /** 998 * Resets permalinks and flushes rewrites. 999 * 1000 * @since 4.4.0 1001 * 1002 * @global WP_Rewrite $wp_rewrite 1003 * 1004 * @param string $structure Optional. Permalink structure to set. Default empty. 1005 */ 1006 public function set_permalink_structure( $structure = '' ) { 1007 global $wp_rewrite; 1008 1009 $wp_rewrite->init(); 1010 $wp_rewrite->set_permalink_structure( $structure ); 1011 $wp_rewrite->flush_rules(); 1012 } 1013 1014 /** 1015 * Creates an attachment post from an uploaded file. 1016 * 1017 * @since 4.4.0 1018 * 1019 * @param array $upload Array of information about the uploaded file, provided by wp_upload_bits(). 1020 * @param int $parent_post_id Optional. Parent post ID. 1021 * 1022 * @return int|WP_Error The attachment ID on success. The value 0 or WP_Error on failure. 1023 */ 1024 function _make_attachment( $upload, $parent_post_id = 0 ) { 1025 $type = ''; 1026 if ( ! empty( $upload['type'] ) ) { 1027 $type = $upload['type']; 1028 } else { 1029 $mime = wp_check_filetype( $upload['file'] ); 1030 if ( $mime ) { 1031 $type = $mime['type']; 1032 } 1033 } 1034 1035 $attachment = array( 1036 'post_title' => basename( $upload['file'] ), 1037 'post_content' => '', 1038 'post_type' => 'attachment', 1039 'post_parent' => $parent_post_id, 1040 'post_mime_type' => $type, 1041 'guid' => $upload['url'], 1042 ); 1043 1044 $id = wp_insert_attachment( $attachment, $upload['file'], $parent_post_id ); 1045 wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) ); 1046 return $id; 1047 } 1048 1049 /** 1050 * Updates the modified and modified GMT date of a post in the database. 1051 * 1052 * @since 4.8.0 1053 * 1054 * @global wpdb $wpdb WordPress database abstraction object. 1055 * 1056 * @param int $post_id Post ID. 1057 * @param string $date Post date, in the format YYYY-MM-DD HH:MM:SS. 1058 * 1059 * @return int|false 1 on success, or false on error. 1060 */ 1061 protected function update_post_modified( $post_id, $date ) { 1062 global $wpdb; 1063 return $wpdb->update( 1064 $wpdb->posts, 1065 array( 1066 'post_modified' => $date, 1067 'post_modified_gmt' => $date, 1068 ), 1069 array( 1070 'ID' => $post_id, 1071 ), 1072 array( 1073 '%s', 1074 '%s', 1075 ), 1076 array( 1077 '%d', 1078 ) 1079 ); 1080 } 1081 } -
tests/phpunit/includes/bootstrap.php
108 108 // Delete any default posts & related data 109 109 _delete_all_posts(); 110 110 111 require dirname( __FILE__ ) . '/testcase.php'; 111 if ( version_compare( tests_get_phpunit_version(), '7.0', '>=' ) ) { 112 require dirname( __FILE__ ) . '/phpunit7/testcase.php'; 113 } else { 114 require dirname( __FILE__ ) . '/testcase.php'; 115 } 116 112 117 require dirname( __FILE__ ) . '/testcase-rest-api.php'; 113 118 require dirname( __FILE__ ) . '/testcase-rest-controller.php'; 114 119 require dirname( __FILE__ ) . '/testcase-rest-post-type-controller.php'; … … 132 137 * If WP_TESTS_FORCE_KNOWN_BUGS is already set in wp-tests-config.php, then 133 138 * how you call phpunit has no effect. 134 139 */ 135 class WP_PHPUnit_Util_Getopt extends PHPUnit_Util_Getopt{140 class WP_PHPUnit_Util_Getopt { 136 141 protected $longOptions = array( 137 142 'exclude-group=', 138 143 'group=', … … 145 150 next( $argv ); 146 151 try { 147 152 if ( strlen( $arg ) > 1 && $arg[0] === '-' && $arg[1] === '-' ) { 148 PHPUnit_Util_Getopt::parseLongOption( substr( $arg, 2 ), $this->longOptions, $options, $argv );153 self::parseLongOption( substr( $arg, 2 ), $this->longOptions, $options, $argv ); 149 154 } 150 155 } catch ( PHPUnit_Framework_Exception $e ) { 151 156 // Enforcing recognized arguments or correctly formed arguments is … … 196 201 echo PHP_EOL; 197 202 } 198 203 } 204 205 /** 206 * Copied from https://raw.githubusercontent.com/sebastianbergmann/phpunit/6.5.7/src/Util/Getopt.php 207 * 208 * @param $arg 209 * @param $long_options 210 * @param $opts 211 * @param $args 212 */ 213 protected static function parseLongOption( $arg, $long_options, &$opts, &$args ) { 214 $count = count( $long_options ); 215 $list = explode( '=', $arg ); 216 $opt = $list[0]; 217 $opt_arg = null; 218 219 if ( count( $list ) > 1 ) { 220 $opt_arg = $list[1]; 221 } 222 223 $opt_len = strlen( $opt ); 224 225 for ( $i = 0; $i < $count; $i++ ) { 226 $long_opt = $long_options[ $i ]; 227 $opt_start = substr( $long_opt, 0, $opt_len ); 228 229 if ( $opt_start != $opt ) { 230 continue; 231 } 232 233 $opt_rest = substr( $long_opt, $opt_len ); 234 235 if ( $opt_rest != '' && $opt[0] != '=' && $i + 1 < $count && 236 $opt == substr( $long_options[ $i + 1 ], 0, $opt_len ) ) { 237 throw new Exception( 238 "option --$opt is ambiguous" 239 ); 240 } 241 242 if ( substr( $long_opt, -1 ) == '=' ) { 243 if ( substr( $long_opt, -2 ) != '==' ) { 244 if ( ! strlen( $opt_arg ) ) { 245 if ( false === $opt_arg = current( $args ) ) { 246 throw new Exception( 247 "option --$opt requires an argument" 248 ); 249 } 250 next( $args ); 251 } 252 } 253 } elseif ( $opt_arg ) { 254 throw new Exception( 255 "option --$opt doesn't allow an argument" 256 ); 257 } 258 259 $full_option = '--' . preg_replace( '/={1,2}$/', '', $long_opt ); 260 $opts[] = array( $full_option, $opt_arg ); 261 262 return; 263 } 264 265 throw new Exception( "unrecognized option --$opt" ); 266 } 199 267 } 200 268 new WP_PHPUnit_Util_Getopt( $_SERVER['argv'] ); -
tests/phpunit/includes/functions.php
1 1 <?php 2 2 3 3 /** 4 * Retrieves PHPUnit runner version. 5 */ 6 function tests_get_phpunit_version() { 7 if ( class_exists( 'PHPUnit_Runner_Version' ) ) { 8 $version = PHPUnit_Runner_Version::id(); 9 } elseif ( class_exists( 'PHPUnit\Runner\Version' ) ) { 10 // Must be parsable by PHP 5.2.x. 11 $version = call_user_func( 'PHPUnit\Runner\Version::id' ); 12 } else { 13 $version = 0; 14 } 15 16 return $version; 17 } 18 19 /** 4 20 * Resets various `$_SERVER` variables that can get altered during tests. 5 21 */ 6 22 function tests_reset__SERVER() { -
tests/phpunit/includes/listener-loader.php
1 <?php 2 3 if ( version_compare( tests_get_phpunit_version(), '7.0', '>=' ) ) { 4 require dirname( __FILE__ ) . '/phpunit7/speed-trap-listener.php'; 5 } else { 6 require dirname( __FILE__ ) . '/speed-trap-listener.php'; 7 } -
tests/phpunit/includes/phpunit6-compat.php
15 15 class_alias( 'PHPUnit\Util\GlobalState', 'PHPUnit_Util_GlobalState' ); 16 16 class_alias( 'PHPUnit\Util\Getopt', 'PHPUnit_Util_Getopt' ); 17 17 18 class PHPUnit_Util_Test extends PHPUnit\Util\Test{18 class PHPUnit_Util_Test { 19 19 20 20 public static function getTickets( $className, $methodName ) { 21 $annotations = self::parseTestMethodAnnotations( $className, $methodName );21 $annotations = PHPUnit\Util\Test::parseTestMethodAnnotations( $className, $methodName ); 22 22 23 23 $tickets = array(); 24 24 -
tests/phpunit/includes/phpunit7/speed-trap-listener.php
1 <?php 2 3 /** 4 * A PHPUnit TestListener that exposes your slowest running tests by outputting 5 * results directly to the console. 6 */ 7 class SpeedTrapListener implements PHPUnit_Framework_TestListener { 8 9 /** 10 * Internal tracking for test suites. 11 * 12 * Increments as more suites are run, then decremented as they finish. All 13 * suites have been run when returns to 0. 14 * 15 * @var integer 16 */ 17 protected $suites = 0; 18 19 /** 20 * Time in milliseconds at which a test will be considered "slow" and be 21 * reported by this listener. 22 * 23 * @var int 24 */ 25 protected $slowThreshold; 26 27 /** 28 * Number of tests to report on for slowness. 29 * 30 * @var int 31 */ 32 protected $reportLength; 33 34 /** 35 * Collection of slow tests. 36 * 37 * @var array 38 */ 39 protected $slow = array(); 40 41 /** 42 * Construct a new instance. 43 * 44 * @param array $options 45 */ 46 public function __construct( array $options = array() ) { 47 $this->loadOptions( $options ); 48 } 49 50 /** 51 * An error occurred. 52 * 53 * @param PHPUnit_Framework_Test $test 54 * @param Exception $e 55 * @param float $time 56 */ 57 public function addError( PHPUnit\Framework\Test $test, Throwable $t, float $time ): void { 58 } 59 60 /** 61 * A warning occurred. 62 * 63 * @param PHPUnit_Framework_Test $test 64 * @param PHPUnit_Framework_Warning $e 65 * @param float $time 66 * @since Method available since Release 5.1.0 67 */ 68 public function addWarning( PHPUnit\Framework\Test $test, PHPUnit\Framework\Warning $e, float $time): void { 69 } 70 71 /** 72 * A failure occurred. 73 * 74 * @param PHPUnit_Framework_Test $test 75 * @param PHPUnit_Framework_AssertionFailedError $e 76 * @param float $time 77 */ 78 public function addFailure( PHPUnit\Framework\Test $test, PHPUnit\Framework\AssertionFailedError $e, float $time): void { 79 } 80 81 /** 82 * Incomplete test. 83 * 84 * @param PHPUnit_Framework_Test $test 85 * @param Exception $e 86 * @param float $time 87 */ 88 public function addIncompleteTest( PHPUnit\Framework\Test $test, Throwable $t, float $time): void { 89 } 90 91 /** 92 * Risky test. 93 * 94 * @param PHPUnit_Framework_Test $test 95 * @param Exception $e 96 * @param float $time 97 * @since Method available since Release 4.0.0 98 */ 99 public function addRiskyTest( PHPUnit\Framework\Test $test, Throwable $t, float $time): void { 100 } 101 102 /** 103 * Skipped test. 104 * 105 * @param PHPUnit_Framework_Test $test 106 * @param Exception $e 107 * @param float $time 108 */ 109 public function addSkippedTest( PHPUnit\Framework\Test $test, Throwable $t, float $time): void { 110 } 111 112 /** 113 * A test started. 114 * 115 * @param PHPUnit_Framework_Test $test 116 */ 117 public function startTest( PHPUnit\Framework\Test $test): void { 118 } 119 120 /** 121 * A test ended. 122 * 123 * @param PHPUnit_Framework_Test $test 124 * @param float $time 125 */ 126 public function endTest( PHPUnit\Framework\Test $test, float $time): void { 127 if ( ! $test instanceof PHPUnit_Framework_TestCase ) { 128 return; 129 } 130 131 $time = $this->toMilliseconds( $time ); 132 $threshold = $this->getSlowThreshold( $test ); 133 134 if ( $this->isSlow( $time, $threshold ) ) { 135 $this->addSlowTest( $test, $time ); 136 } 137 } 138 139 /** 140 * A test suite started. 141 * 142 * @param PHPUnit_Framework_TestSuite $suite 143 */ 144 public function startTestSuite( PHPUnit\Framework\TestSuite $suite): void { 145 $this->suites++; 146 } 147 148 /** 149 * A test suite ended. 150 * 151 * @param PHPUnit_Framework_TestSuite $suite 152 */ 153 public function endTestSuite( PHPUnit\Framework\TestSuite $suite): void { 154 $this->suites--; 155 156 if ( 0 === $this->suites && $this->hasSlowTests() ) { 157 arsort( $this->slow ); // Sort longest running tests to the top 158 159 $this->renderHeader(); 160 $this->renderBody(); 161 $this->renderFooter(); 162 } 163 } 164 165 /** 166 * Whether the given test execution time is considered slow. 167 * 168 * @param int $time Test execution time in milliseconds 169 * @param int $slowThreshold Test execution time at which a test should be considered slow (milliseconds) 170 * @return bool 171 */ 172 protected function isSlow( $time, $slowThreshold ) { 173 return $time >= $slowThreshold; 174 } 175 176 /** 177 * Stores a test as slow. 178 * 179 * @param PHPUnit_Framework_TestCase $test 180 * @param int $time Test execution time in milliseconds 181 */ 182 protected function addSlowTest( PHPUnit_Framework_TestCase $test, $time ) { 183 $label = $this->makeLabel( $test ); 184 185 $this->slow[ $label ] = $time; 186 } 187 188 /** 189 * Whether at least one test has been considered slow. 190 * 191 * @return bool 192 */ 193 protected function hasSlowTests() { 194 return ! empty( $this->slow ); 195 } 196 197 /** 198 * Convert PHPUnit's reported test time (microseconds) to milliseconds. 199 * 200 * @param float $time 201 * @return int 202 */ 203 protected function toMilliseconds( $time ) { 204 return (int) round( $time * 1000 ); 205 } 206 207 /** 208 * Label for describing a test. 209 * 210 * @param PHPUnit_Framework_TestCase $test 211 * @return string 212 */ 213 protected function makeLabel( PHPUnit_Framework_TestCase $test ) { 214 return sprintf( '%s:%s', get_class( $test ), $test->getName() ); 215 } 216 217 /** 218 * Calculate number of slow tests to report about. 219 * 220 * @return int 221 */ 222 protected function getReportLength() { 223 return min( count( $this->slow ), $this->reportLength ); 224 } 225 226 /** 227 * Find how many slow tests occurred that won't be shown due to list length. 228 * 229 * @return int Number of hidden slow tests 230 */ 231 protected function getHiddenCount() { 232 $total = count( $this->slow ); 233 $showing = $this->getReportLength( $this->slow ); 234 235 $hidden = 0; 236 if ( $total > $showing ) { 237 $hidden = $total - $showing; 238 } 239 240 return $hidden; 241 } 242 243 /** 244 * Renders slow test report header. 245 */ 246 protected function renderHeader() { 247 echo sprintf( "\n\nYou should really fix these slow tests (>%sms)...\n", $this->slowThreshold ); 248 } 249 250 /** 251 * Renders slow test report body. 252 */ 253 protected function renderBody() { 254 $slowTests = $this->slow; 255 256 $length = $this->getReportLength( $slowTests ); 257 for ( $i = 1; $i <= $length; ++$i ) { 258 $label = key( $slowTests ); 259 $time = array_shift( $slowTests ); 260 261 echo sprintf( " %s. %sms to run %s\n", $i, $time, $label ); 262 } 263 } 264 265 /** 266 * Renders slow test report footer. 267 */ 268 protected function renderFooter() { 269 if ( $hidden = $this->getHiddenCount( $this->slow ) ) { 270 echo sprintf( '...and there %s %s more above your threshold hidden from view', $hidden == 1 ? 'is' : 'are', $hidden ); 271 } 272 } 273 274 /** 275 * Populate options into class internals. 276 * 277 * @param array $options 278 */ 279 protected function loadOptions( array $options ) { 280 $this->slowThreshold = isset( $options['slowThreshold'] ) ? $options['slowThreshold'] : 500; 281 $this->reportLength = isset( $options['reportLength'] ) ? $options['reportLength'] : 10; 282 } 283 284 /** 285 * Get slow test threshold for given test. A TestCase can override the 286 * suite-wide slow threshold by using the annotation @slowThreshold with 287 * the threshold value in milliseconds. 288 * 289 * The following test will only be considered slow when its execution time 290 * reaches 5000ms (5 seconds): 291 * 292 * <code> 293 * 294 * @slowThreshold 5000 295 * public function testLongRunningProcess() {} 296 * </code> 297 * 298 * @param PHPUnit_Framework_TestCase $test 299 * @return int 300 */ 301 protected function getSlowThreshold( PHPUnit_Framework_TestCase $test ) { 302 $ann = $test->getAnnotations(); 303 304 return isset( $ann['method']['slowThreshold'][0] ) ? $ann['method']['slowThreshold'][0] : $this->slowThreshold; 305 } 306 } -
tests/phpunit/includes/phpunit7/testcase.php
1 <?php 2 3 require_once dirname(dirname( __FILE__ ) ) . '/abstract-testcase.php'; 4 5 /** 6 * Defines a basic fixture to run multiple tests. 7 * 8 * Resets the state of the WordPress installation before and after every test. 9 * 10 * Includes utility functions and assertions useful for testing WordPress. 11 * 12 * All WordPress unit tests should inherit from this class. 13 */ 14 class WP_UnitTestCase extends WP_UnitTestCase_Base { 15 /** 16 * Asserts that a condition is not false. 17 * 18 * This method has been backported from a more recent PHPUnit version, as tests running on PHP 5.2 use 19 * PHPUnit 3.6.x. 20 * 21 * @since 4.7.4 22 * 23 * @param bool $condition Condition to check. 24 * @param string $message Optional. Message to display when the assertion fails. 25 * 26 * @throws PHPUnit_Framework_AssertionFailedError 27 */ 28 public static function assertNotFalse( $condition, string $message = '' ): void { 29 self::assertThat( $condition, self::logicalNot( self::isFalse() ), $message ); 30 } 31 } -
tests/phpunit/includes/phpunit7/speed-trap-listener.php
1 <?php 2 3 /** 4 * A PHPUnit TestListener that exposes your slowest running tests by outputting 5 * results directly to the console. 6 */ 7 class SpeedTrapListener implements PHPUnit_Framework_TestListener { 8 9 /** 10 * Internal tracking for test suites. 11 * 12 * Increments as more suites are run, then decremented as they finish. All 13 * suites have been run when returns to 0. 14 * 15 * @var integer 16 */ 17 protected $suites = 0; 18 19 /** 20 * Time in milliseconds at which a test will be considered "slow" and be 21 * reported by this listener. 22 * 23 * @var int 24 */ 25 protected $slowThreshold; 26 27 /** 28 * Number of tests to report on for slowness. 29 * 30 * @var int 31 */ 32 protected $reportLength; 33 34 /** 35 * Collection of slow tests. 36 * 37 * @var array 38 */ 39 protected $slow = array(); 40 41 /** 42 * Construct a new instance. 43 * 44 * @param array $options 45 */ 46 public function __construct( array $options = array() ) { 47 $this->loadOptions( $options ); 48 } 49 50 /** 51 * An error occurred. 52 * 53 * @param PHPUnit_Framework_Test $test 54 * @param Exception $e 55 * @param float $time 56 */ 57 public function addError( PHPUnit\Framework\Test $test, Throwable $t, float $time ): void { 58 } 59 60 /** 61 * A warning occurred. 62 * 63 * @param PHPUnit_Framework_Test $test 64 * @param PHPUnit_Framework_Warning $e 65 * @param float $time 66 * @since Method available since Release 5.1.0 67 */ 68 public function addWarning( PHPUnit\Framework\Test $test, PHPUnit\Framework\Warning $e, float $time): void { 69 } 70 71 /** 72 * A failure occurred. 73 * 74 * @param PHPUnit_Framework_Test $test 75 * @param PHPUnit_Framework_AssertionFailedError $e 76 * @param float $time 77 */ 78 public function addFailure( PHPUnit\Framework\Test $test, PHPUnit\Framework\AssertionFailedError $e, float $time): void { 79 } 80 81 /** 82 * Incomplete test. 83 * 84 * @param PHPUnit_Framework_Test $test 85 * @param Exception $e 86 * @param float $time 87 */ 88 public function addIncompleteTest( PHPUnit\Framework\Test $test, Throwable $t, float $time): void { 89 } 90 91 /** 92 * Risky test. 93 * 94 * @param PHPUnit_Framework_Test $test 95 * @param Exception $e 96 * @param float $time 97 * @since Method available since Release 4.0.0 98 */ 99 public function addRiskyTest( PHPUnit\Framework\Test $test, Throwable $t, float $time): void { 100 } 101 102 /** 103 * Skipped test. 104 * 105 * @param PHPUnit_Framework_Test $test 106 * @param Exception $e 107 * @param float $time 108 */ 109 public function addSkippedTest( PHPUnit\Framework\Test $test, Throwable $t, float $time): void { 110 } 111 112 /** 113 * A test started. 114 * 115 * @param PHPUnit_Framework_Test $test 116 */ 117 public function startTest( PHPUnit\Framework\Test $test): void { 118 } 119 120 /** 121 * A test ended. 122 * 123 * @param PHPUnit_Framework_Test $test 124 * @param float $time 125 */ 126 public function endTest( PHPUnit\Framework\Test $test, float $time): void { 127 if ( ! $test instanceof PHPUnit_Framework_TestCase ) { 128 return; 129 } 130 131 $time = $this->toMilliseconds( $time ); 132 $threshold = $this->getSlowThreshold( $test ); 133 134 if ( $this->isSlow( $time, $threshold ) ) { 135 $this->addSlowTest( $test, $time ); 136 } 137 } 138 139 /** 140 * A test suite started. 141 * 142 * @param PHPUnit_Framework_TestSuite $suite 143 */ 144 public function startTestSuite( PHPUnit\Framework\TestSuite $suite): void { 145 $this->suites++; 146 } 147 148 /** 149 * A test suite ended. 150 * 151 * @param PHPUnit_Framework_TestSuite $suite 152 */ 153 public function endTestSuite( PHPUnit\Framework\TestSuite $suite): void { 154 $this->suites--; 155 156 if ( 0 === $this->suites && $this->hasSlowTests() ) { 157 arsort( $this->slow ); // Sort longest running tests to the top 158 159 $this->renderHeader(); 160 $this->renderBody(); 161 $this->renderFooter(); 162 } 163 } 164 165 /** 166 * Whether the given test execution time is considered slow. 167 * 168 * @param int $time Test execution time in milliseconds 169 * @param int $slowThreshold Test execution time at which a test should be considered slow (milliseconds) 170 * @return bool 171 */ 172 protected function isSlow( $time, $slowThreshold ) { 173 return $time >= $slowThreshold; 174 } 175 176 /** 177 * Stores a test as slow. 178 * 179 * @param PHPUnit_Framework_TestCase $test 180 * @param int $time Test execution time in milliseconds 181 */ 182 protected function addSlowTest( PHPUnit_Framework_TestCase $test, $time ) { 183 $label = $this->makeLabel( $test ); 184 185 $this->slow[ $label ] = $time; 186 } 187 188 /** 189 * Whether at least one test has been considered slow. 190 * 191 * @return bool 192 */ 193 protected function hasSlowTests() { 194 return ! empty( $this->slow ); 195 } 196 197 /** 198 * Convert PHPUnit's reported test time (microseconds) to milliseconds. 199 * 200 * @param float $time 201 * @return int 202 */ 203 protected function toMilliseconds( $time ) { 204 return (int) round( $time * 1000 ); 205 } 206 207 /** 208 * Label for describing a test. 209 * 210 * @param PHPUnit_Framework_TestCase $test 211 * @return string 212 */ 213 protected function makeLabel( PHPUnit_Framework_TestCase $test ) { 214 return sprintf( '%s:%s', get_class( $test ), $test->getName() ); 215 } 216 217 /** 218 * Calculate number of slow tests to report about. 219 * 220 * @return int 221 */ 222 protected function getReportLength() { 223 return min( count( $this->slow ), $this->reportLength ); 224 } 225 226 /** 227 * Find how many slow tests occurred that won't be shown due to list length. 228 * 229 * @return int Number of hidden slow tests 230 */ 231 protected function getHiddenCount() { 232 $total = count( $this->slow ); 233 $showing = $this->getReportLength( $this->slow ); 234 235 $hidden = 0; 236 if ( $total > $showing ) { 237 $hidden = $total - $showing; 238 } 239 240 return $hidden; 241 } 242 243 /** 244 * Renders slow test report header. 245 */ 246 protected function renderHeader() { 247 echo sprintf( "\n\nYou should really fix these slow tests (>%sms)...\n", $this->slowThreshold ); 248 } 249 250 /** 251 * Renders slow test report body. 252 */ 253 protected function renderBody() { 254 $slowTests = $this->slow; 255 256 $length = $this->getReportLength( $slowTests ); 257 for ( $i = 1; $i <= $length; ++$i ) { 258 $label = key( $slowTests ); 259 $time = array_shift( $slowTests ); 260 261 echo sprintf( " %s. %sms to run %s\n", $i, $time, $label ); 262 } 263 } 264 265 /** 266 * Renders slow test report footer. 267 */ 268 protected function renderFooter() { 269 if ( $hidden = $this->getHiddenCount( $this->slow ) ) { 270 echo sprintf( '...and there %s %s more above your threshold hidden from view', $hidden == 1 ? 'is' : 'are', $hidden ); 271 } 272 } 273 274 /** 275 * Populate options into class internals. 276 * 277 * @param array $options 278 */ 279 protected function loadOptions( array $options ) { 280 $this->slowThreshold = isset( $options['slowThreshold'] ) ? $options['slowThreshold'] : 500; 281 $this->reportLength = isset( $options['reportLength'] ) ? $options['reportLength'] : 10; 282 } 283 284 /** 285 * Get slow test threshold for given test. A TestCase can override the 286 * suite-wide slow threshold by using the annotation @slowThreshold with 287 * the threshold value in milliseconds. 288 * 289 * The following test will only be considered slow when its execution time 290 * reaches 5000ms (5 seconds): 291 * 292 * <code> 293 * 294 * @slowThreshold 5000 295 * public function testLongRunningProcess() {} 296 * </code> 297 * 298 * @param PHPUnit_Framework_TestCase $test 299 * @return int 300 */ 301 protected function getSlowThreshold( PHPUnit_Framework_TestCase $test ) { 302 $ann = $test->getAnnotations(); 303 304 return isset( $ann['method']['slowThreshold'][0] ) ? $ann['method']['slowThreshold'][0] : $this->slowThreshold; 305 } 306 } -
tests/phpunit/includes/phpunit7/testcase.php
1 <?php 2 3 require_once dirname(dirname( __FILE__ ) ) . '/abstract-testcase.php'; 4 5 /** 6 * Defines a basic fixture to run multiple tests. 7 * 8 * Resets the state of the WordPress installation before and after every test. 9 * 10 * Includes utility functions and assertions useful for testing WordPress. 11 * 12 * All WordPress unit tests should inherit from this class. 13 */ 14 class WP_UnitTestCase extends WP_UnitTestCase_Base { 15 /** 16 * Asserts that a condition is not false. 17 * 18 * This method has been backported from a more recent PHPUnit version, as tests running on PHP 5.2 use 19 * PHPUnit 3.6.x. 20 * 21 * @since 4.7.4 22 * 23 * @param bool $condition Condition to check. 24 * @param string $message Optional. Message to display when the assertion fails. 25 * 26 * @throws PHPUnit_Framework_AssertionFailedError 27 */ 28 public static function assertNotFalse( $condition, string $message = '' ): void { 29 self::assertThat( $condition, self::logicalNot( self::isFalse() ), $message ); 30 } 31 } -
tests/phpunit/includes/testcase-canonical.php
236 236 public function assertCanonical( $test_url, $expected, $ticket = 0, $expected_doing_it_wrong = array() ) { 237 237 $this->expected_doing_it_wrong = array_merge( $this->expected_doing_it_wrong, (array) $expected_doing_it_wrong ); 238 238 239 $ticket_ref = ( $ticket > 0 ) ? 'Ticket #' . $ticket : null;239 $ticket_ref = ( $ticket > 0 ) ? 'Ticket #' . $ticket : ''; 240 240 241 241 if ( is_string( $expected ) ) { 242 242 $expected = array( 'url' => $expected ); -
tests/phpunit/includes/testcase.php
1 1 <?php 2 2 3 require_once dirname( __FILE__ ) . '/factory.php'; 4 require_once dirname( __FILE__ ) . '/trac.php'; 3 require_once dirname( __FILE__ ) . '/abstract-testcase.php'; 5 4 5 6 6 /** 7 7 * Defines a basic fixture to run multiple tests. 8 8 * … … 12 12 * 13 13 * All WordPress unit tests should inherit from this class. 14 14 */ 15 class WP_UnitTestCase extends PHPUnit_Framework_TestCase { 16 17 protected static $forced_tickets = array(); 18 protected $expected_deprecated = array(); 19 protected $caught_deprecated = array(); 20 protected $expected_doing_it_wrong = array(); 21 protected $caught_doing_it_wrong = array(); 22 23 protected static $hooks_saved = array(); 24 protected static $ignore_files; 25 26 function __isset( $name ) { 27 return 'factory' === $name; 28 } 29 30 function __get( $name ) { 31 if ( 'factory' === $name ) { 32 return self::factory(); 33 } 34 } 35 15 class WP_UnitTestCase extends WP_UnitTestCase_Base { 36 16 /** 37 * Fetches the factory object for generating WordPress fixtures.38 *39 * @return WP_UnitTest_Factory The fixture factory.40 */41 protected static function factory() {42 static $factory = null;43 if ( ! $factory ) {44 $factory = new WP_UnitTest_Factory();45 }46 return $factory;47 }48 49 public static function get_called_class() {50 if ( function_exists( 'get_called_class' ) ) {51 return get_called_class();52 }53 54 // PHP 5.2 only55 $backtrace = debug_backtrace();56 // [0] WP_UnitTestCase::get_called_class()57 // [1] WP_UnitTestCase::setUpBeforeClass()58 if ( 'call_user_func' === $backtrace[2]['function'] ) {59 return $backtrace[2]['args'][0][0];60 }61 return $backtrace[2]['class'];62 }63 64 public static function setUpBeforeClass() {65 global $wpdb;66 67 $wpdb->suppress_errors = false;68 $wpdb->show_errors = true;69 $wpdb->db_connect();70 ini_set( 'display_errors', 1 );71 72 parent::setUpBeforeClass();73 74 $c = self::get_called_class();75 if ( ! method_exists( $c, 'wpSetUpBeforeClass' ) ) {76 self::commit_transaction();77 return;78 }79 80 call_user_func( array( $c, 'wpSetUpBeforeClass' ), self::factory() );81 82 self::commit_transaction();83 }84 85 public static function tearDownAfterClass() {86 parent::tearDownAfterClass();87 88 _delete_all_data();89 self::flush_cache();90 91 $c = self::get_called_class();92 if ( ! method_exists( $c, 'wpTearDownAfterClass' ) ) {93 self::commit_transaction();94 return;95 }96 97 call_user_func( array( $c, 'wpTearDownAfterClass' ) );98 99 self::commit_transaction();100 }101 102 function setUp() {103 set_time_limit( 0 );104 105 if ( ! self::$ignore_files ) {106 self::$ignore_files = $this->scan_user_uploads();107 }108 109 if ( ! self::$hooks_saved ) {110 $this->_backup_hooks();111 }112 113 global $wp_rewrite;114 115 $this->clean_up_global_scope();116 117 /*118 * When running core tests, ensure that post types and taxonomies119 * are reset for each test. We skip this step for non-core tests,120 * given the large number of plugins that register post types and121 * taxonomies at 'init'.122 */123 if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) {124 $this->reset_post_types();125 $this->reset_taxonomies();126 $this->reset_post_statuses();127 $this->reset__SERVER();128 129 if ( $wp_rewrite->permalink_structure ) {130 $this->set_permalink_structure( '' );131 }132 }133 134 $this->start_transaction();135 $this->expectDeprecated();136 add_filter( 'wp_die_handler', array( $this, 'get_wp_die_handler' ) );137 }138 139 /**140 * Detect post-test failure conditions.141 *142 * We use this method to detect expectedDeprecated and expectedIncorrectUsage annotations.143 *144 * @since 4.2.0145 */146 protected function assertPostConditions() {147 $this->expectedDeprecated();148 }149 150 /**151 * After a test method runs, reset any state in WordPress the test method might have changed.152 */153 function tearDown() {154 global $wpdb, $wp_query, $wp;155 $wpdb->query( 'ROLLBACK' );156 if ( is_multisite() ) {157 while ( ms_is_switched() ) {158 restore_current_blog();159 }160 }161 $wp_query = new WP_Query();162 $wp = new WP();163 164 // Reset globals related to the post loop and `setup_postdata()`.165 $post_globals = array( 'post', 'id', 'authordata', 'currentday', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages' );166 foreach ( $post_globals as $global ) {167 $GLOBALS[ $global ] = null;168 }169 170 remove_theme_support( 'html5' );171 remove_filter( 'query', array( $this, '_create_temporary_tables' ) );172 remove_filter( 'query', array( $this, '_drop_temporary_tables' ) );173 remove_filter( 'wp_die_handler', array( $this, 'get_wp_die_handler' ) );174 $this->_restore_hooks();175 wp_set_current_user( 0 );176 }177 178 function clean_up_global_scope() {179 $_GET = array();180 $_POST = array();181 self::flush_cache();182 }183 184 /**185 * Allow tests to be skipped on some automated runs186 *187 * For test runs on Travis for something other than trunk/master188 * we want to skip tests that only need to run for master.189 */190 public function skipOnAutomatedBranches() {191 // gentenv can be disabled192 if ( ! function_exists( 'getenv' ) ) {193 return false;194 }195 196 // https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables197 $travis_branch = getenv( 'TRAVIS_BRANCH' );198 $travis_pull_request = getenv( 'TRAVIS_PULL_REQUEST' );199 200 if ( false !== $travis_pull_request && 'master' !== $travis_branch ) {201 $this->markTestSkipped( 'For automated test runs, this test is only run on trunk/master' );202 }203 }204 205 /**206 * Allow tests to be skipped when Multisite is not in use.207 *208 * Use in conjunction with the ms-required group.209 */210 public function skipWithoutMultisite() {211 if ( ! is_multisite() ) {212 $this->markTestSkipped( 'Test only runs on Multisite' );213 }214 }215 216 /**217 * Allow tests to be skipped when Multisite is in use.218 *219 * Use in conjunction with the ms-excluded group.220 */221 public function skipWithMultisite() {222 if ( is_multisite() ) {223 $this->markTestSkipped( 'Test does not run on Multisite' );224 }225 }226 227 /**228 * Unregister existing post types and register defaults.229 *230 * Run before each test in order to clean up the global scope, in case231 * a test forgets to unregister a post type on its own, or fails before232 * it has a chance to do so.233 */234 protected function reset_post_types() {235 foreach ( get_post_types( array(), 'objects' ) as $pt ) {236 if ( empty( $pt->tests_no_auto_unregister ) ) {237 _unregister_post_type( $pt->name );238 }239 }240 create_initial_post_types();241 }242 243 /**244 * Unregister existing taxonomies and register defaults.245 *246 * Run before each test in order to clean up the global scope, in case247 * a test forgets to unregister a taxonomy on its own, or fails before248 * it has a chance to do so.249 */250 protected function reset_taxonomies() {251 foreach ( get_taxonomies() as $tax ) {252 _unregister_taxonomy( $tax );253 }254 create_initial_taxonomies();255 }256 257 /**258 * Unregister non-built-in post statuses.259 */260 protected function reset_post_statuses() {261 foreach ( get_post_stati( array( '_builtin' => false ) ) as $post_status ) {262 _unregister_post_status( $post_status );263 }264 }265 266 /**267 * Reset `$_SERVER` variables268 */269 protected function reset__SERVER() {270 tests_reset__SERVER();271 }272 273 /**274 * Saves the action and filter-related globals so they can be restored later.275 *276 * Stores $merged_filters, $wp_actions, $wp_current_filter, and $wp_filter277 * on a class variable so they can be restored on tearDown() using _restore_hooks().278 *279 * @global array $merged_filters280 * @global array $wp_actions281 * @global array $wp_current_filter282 * @global array $wp_filter283 * @return void284 */285 protected function _backup_hooks() {286 $globals = array( 'wp_actions', 'wp_current_filter' );287 foreach ( $globals as $key ) {288 self::$hooks_saved[ $key ] = $GLOBALS[ $key ];289 }290 self::$hooks_saved['wp_filter'] = array();291 foreach ( $GLOBALS['wp_filter'] as $hook_name => $hook_object ) {292 self::$hooks_saved['wp_filter'][ $hook_name ] = clone $hook_object;293 }294 }295 296 /**297 * Restores the hook-related globals to their state at setUp()298 * so that future tests aren't affected by hooks set during this last test.299 *300 * @global array $merged_filters301 * @global array $wp_actions302 * @global array $wp_current_filter303 * @global array $wp_filter304 * @return void305 */306 protected function _restore_hooks() {307 $globals = array( 'wp_actions', 'wp_current_filter' );308 foreach ( $globals as $key ) {309 if ( isset( self::$hooks_saved[ $key ] ) ) {310 $GLOBALS[ $key ] = self::$hooks_saved[ $key ];311 }312 }313 if ( isset( self::$hooks_saved['wp_filter'] ) ) {314 $GLOBALS['wp_filter'] = array();315 foreach ( self::$hooks_saved['wp_filter'] as $hook_name => $hook_object ) {316 $GLOBALS['wp_filter'][ $hook_name ] = clone $hook_object;317 }318 }319 }320 321 static function flush_cache() {322 global $wp_object_cache;323 $wp_object_cache->group_ops = array();324 $wp_object_cache->stats = array();325 $wp_object_cache->memcache_debug = array();326 $wp_object_cache->cache = array();327 if ( method_exists( $wp_object_cache, '__remoteset' ) ) {328 $wp_object_cache->__remoteset();329 }330 wp_cache_flush();331 wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details' ) );332 wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );333 }334 335 function start_transaction() {336 global $wpdb;337 $wpdb->query( 'SET autocommit = 0;' );338 $wpdb->query( 'START TRANSACTION;' );339 add_filter( 'query', array( $this, '_create_temporary_tables' ) );340 add_filter( 'query', array( $this, '_drop_temporary_tables' ) );341 }342 343 /**344 * Commit the queries in a transaction.345 *346 * @since 4.1.0347 */348 public static function commit_transaction() {349 global $wpdb;350 $wpdb->query( 'COMMIT;' );351 }352 353 function _create_temporary_tables( $query ) {354 if ( 'CREATE TABLE' === substr( trim( $query ), 0, 12 ) ) {355 return substr_replace( trim( $query ), 'CREATE TEMPORARY TABLE', 0, 12 );356 }357 return $query;358 }359 360 function _drop_temporary_tables( $query ) {361 if ( 'DROP TABLE' === substr( trim( $query ), 0, 10 ) ) {362 return substr_replace( trim( $query ), 'DROP TEMPORARY TABLE', 0, 10 );363 }364 return $query;365 }366 367 function get_wp_die_handler( $handler ) {368 return array( $this, 'wp_die_handler' );369 }370 371 function wp_die_handler( $message ) {372 if ( ! is_scalar( $message ) ) {373 $message = '0';374 }375 376 throw new WPDieException( $message );377 }378 379 function expectDeprecated() {380 $annotations = $this->getAnnotations();381 foreach ( array( 'class', 'method' ) as $depth ) {382 if ( ! empty( $annotations[ $depth ]['expectedDeprecated'] ) ) {383 $this->expected_deprecated = array_merge( $this->expected_deprecated, $annotations[ $depth ]['expectedDeprecated'] );384 }385 if ( ! empty( $annotations[ $depth ]['expectedIncorrectUsage'] ) ) {386 $this->expected_doing_it_wrong = array_merge( $this->expected_doing_it_wrong, $annotations[ $depth ]['expectedIncorrectUsage'] );387 }388 }389 add_action( 'deprecated_function_run', array( $this, 'deprecated_function_run' ) );390 add_action( 'deprecated_argument_run', array( $this, 'deprecated_function_run' ) );391 add_action( 'deprecated_hook_run', array( $this, 'deprecated_function_run' ) );392 add_action( 'doing_it_wrong_run', array( $this, 'doing_it_wrong_run' ) );393 add_action( 'deprecated_function_trigger_error', '__return_false' );394 add_action( 'deprecated_argument_trigger_error', '__return_false' );395 add_action( 'deprecated_hook_trigger_error', '__return_false' );396 add_action( 'doing_it_wrong_trigger_error', '__return_false' );397 }398 399 function expectedDeprecated() {400 $errors = array();401 402 $not_caught_deprecated = array_diff( $this->expected_deprecated, $this->caught_deprecated );403 foreach ( $not_caught_deprecated as $not_caught ) {404 $errors[] = "Failed to assert that $not_caught triggered a deprecated notice";405 }406 407 $unexpected_deprecated = array_diff( $this->caught_deprecated, $this->expected_deprecated );408 foreach ( $unexpected_deprecated as $unexpected ) {409 $errors[] = "Unexpected deprecated notice for $unexpected";410 }411 412 $not_caught_doing_it_wrong = array_diff( $this->expected_doing_it_wrong, $this->caught_doing_it_wrong );413 foreach ( $not_caught_doing_it_wrong as $not_caught ) {414 $errors[] = "Failed to assert that $not_caught triggered an incorrect usage notice";415 }416 417 $unexpected_doing_it_wrong = array_diff( $this->caught_doing_it_wrong, $this->expected_doing_it_wrong );418 foreach ( $unexpected_doing_it_wrong as $unexpected ) {419 $errors[] = "Unexpected incorrect usage notice for $unexpected";420 }421 422 // Perform an assertion, but only if there are expected or unexpected deprecated calls or wrongdoings423 if ( ! empty( $this->expected_deprecated ) ||424 ! empty( $this->expected_doing_it_wrong ) ||425 ! empty( $this->caught_deprecated ) ||426 ! empty( $this->caught_doing_it_wrong ) ) {427 $this->assertEmpty( $errors, implode( "\n", $errors ) );428 }429 }430 431 /**432 * Declare an expected `_deprecated_function()` or `_deprecated_argument()` call from within a test.433 *434 * @since 4.2.0435 *436 * @param string $deprecated Name of the function, method, class, or argument that is deprecated. Must match437 * first parameter of the `_deprecated_function()` or `_deprecated_argument()` call.438 */439 public function setExpectedDeprecated( $deprecated ) {440 array_push( $this->expected_deprecated, $deprecated );441 }442 443 /**444 * Declare an expected `_doing_it_wrong()` call from within a test.445 *446 * @since 4.2.0447 *448 * @param string $deprecated Name of the function, method, or class that appears in the first argument of the449 * source `_doing_it_wrong()` call.450 */451 public function setExpectedIncorrectUsage( $doing_it_wrong ) {452 array_push( $this->expected_doing_it_wrong, $doing_it_wrong );453 }454 455 /**456 * PHPUnit 6+ compatibility shim.457 *458 * @param mixed $exception459 * @param string $message460 * @param int|string $code461 */462 public function setExpectedException( $exception, $message = '', $code = null ) {463 if ( method_exists( 'PHPUnit_Framework_TestCase', 'setExpectedException' ) ) {464 parent::setExpectedException( $exception, $message, $code );465 } else {466 $this->expectException( $exception );467 if ( '' !== $message ) {468 $this->expectExceptionMessage( $message );469 }470 if ( null !== $code ) {471 $this->expectExceptionCode( $code );472 }473 }474 }475 476 function deprecated_function_run( $function ) {477 if ( ! in_array( $function, $this->caught_deprecated ) ) {478 $this->caught_deprecated[] = $function;479 }480 }481 482 function doing_it_wrong_run( $function ) {483 if ( ! in_array( $function, $this->caught_doing_it_wrong ) ) {484 $this->caught_doing_it_wrong[] = $function;485 }486 }487 488 function assertWPError( $actual, $message = '' ) {489 $this->assertInstanceOf( 'WP_Error', $actual, $message );490 }491 492 function assertNotWPError( $actual, $message = '' ) {493 if ( is_wp_error( $actual ) && '' === $message ) {494 $message = $actual->get_error_message();495 }496 $this->assertNotInstanceOf( 'WP_Error', $actual, $message );497 }498 499 function assertIXRError( $actual, $message = '' ) {500 $this->assertInstanceOf( 'IXR_Error', $actual, $message );501 }502 503 function assertNotIXRError( $actual, $message = '' ) {504 if ( $actual instanceof IXR_Error && '' === $message ) {505 $message = $actual->message;506 }507 $this->assertNotInstanceOf( 'IXR_Error', $actual, $message );508 }509 510 function assertEqualFields( $object, $fields ) {511 foreach ( $fields as $field_name => $field_value ) {512 if ( $object->$field_name != $field_value ) {513 $this->fail();514 }515 }516 }517 518 function assertDiscardWhitespace( $expected, $actual ) {519 $this->assertEquals( preg_replace( '/\s*/', '', $expected ), preg_replace( '/\s*/', '', $actual ) );520 }521 522 /**523 * Asserts that the contents of two un-keyed, single arrays are equal, without accounting for the order of elements.524 *525 * @since 3.5.0526 *527 * @param array $expected Expected array.528 * @param array $actual Array to check.529 */530 function assertEqualSets( $expected, $actual ) {531 sort( $expected );532 sort( $actual );533 $this->assertEquals( $expected, $actual );534 }535 536 /**537 * Asserts that the contents of two keyed, single arrays are equal, without accounting for the order of elements.538 *539 * @since 4.1.0540 *541 * @param array $expected Expected array.542 * @param array $actual Array to check.543 */544 function assertEqualSetsWithIndex( $expected, $actual ) {545 ksort( $expected );546 ksort( $actual );547 $this->assertEquals( $expected, $actual );548 }549 550 /**551 * Asserts that the given variable is a multidimensional array, and that all arrays are non-empty.552 *553 * @since 4.8.0554 *555 * @param array $array Array to check.556 */557 function assertNonEmptyMultidimensionalArray( $array ) {558 $this->assertTrue( is_array( $array ) );559 $this->assertNotEmpty( $array );560 561 foreach ( $array as $sub_array ) {562 $this->assertTrue( is_array( $sub_array ) );563 $this->assertNotEmpty( $sub_array );564 }565 }566 567 /**568 17 * Asserts that a condition is not false. 569 18 * 570 19 * This method has been backported from a more recent PHPUnit version, as tests running on PHP 5.2 use … … 580 29 public static function assertNotFalse( $condition, $message = '' ) { 581 30 self::assertThat( $condition, self::logicalNot( self::isFalse() ), $message ); 582 31 } 583 584 /**585 * Sets the global state to as if a given URL has been requested.586 *587 * This sets:588 * - The super globals.589 * - The globals.590 * - The query variables.591 * - The main query.592 *593 * @since 3.5.0594 *595 * @param string $url The URL for the request.596 */597 function go_to( $url ) {598 // note: the WP and WP_Query classes like to silently fetch parameters599 // from all over the place (globals, GET, etc), which makes it tricky600 // to run them more than once without very carefully clearing everything601 $_GET = $_POST = array();602 foreach ( array( 'query_string', 'id', 'postdata', 'authordata', 'day', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages', 'pagenow' ) as $v ) {603 if ( isset( $GLOBALS[ $v ] ) ) {604 unset( $GLOBALS[ $v ] );605 }606 }607 $parts = parse_url( $url );608 if ( isset( $parts['scheme'] ) ) {609 $req = isset( $parts['path'] ) ? $parts['path'] : '';610 if ( isset( $parts['query'] ) ) {611 $req .= '?' . $parts['query'];612 // parse the url query vars into $_GET613 parse_str( $parts['query'], $_GET );614 }615 } else {616 $req = $url;617 }618 if ( ! isset( $parts['query'] ) ) {619 $parts['query'] = '';620 }621 622 $_SERVER['REQUEST_URI'] = $req;623 unset( $_SERVER['PATH_INFO'] );624 625 self::flush_cache();626 unset( $GLOBALS['wp_query'], $GLOBALS['wp_the_query'] );627 $GLOBALS['wp_the_query'] = new WP_Query();628 $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];629 630 $public_query_vars = $GLOBALS['wp']->public_query_vars;631 $private_query_vars = $GLOBALS['wp']->private_query_vars;632 633 $GLOBALS['wp'] = new WP();634 $GLOBALS['wp']->public_query_vars = $public_query_vars;635 $GLOBALS['wp']->private_query_vars = $private_query_vars;636 637 _cleanup_query_vars();638 639 $GLOBALS['wp']->main( $parts['query'] );640 }641 642 /**643 * Allows tests to be skipped on single or multisite installs by using @group annotations.644 *645 * This is a custom extension of the PHPUnit requirements handling.646 *647 * Contains legacy code for skipping tests that are associated with an open Trac ticket. Core tests no longer648 * support this behaviour.649 *650 * @since 3.5.0651 */652 protected function checkRequirements() {653 parent::checkRequirements();654 655 $annotations = $this->getAnnotations();656 657 if ( ! empty( $annotations['group'] ) ) {658 if ( in_array( 'ms-required', $annotations['group'], true ) ) {659 $this->skipWithoutMultisite();660 }661 if ( in_array( 'ms-excluded', $annotations['group'], true ) ) {662 $this->skipWithMultisite();663 }664 }665 666 // Core tests no longer check against open Trac tickets, but others using WP_UnitTestCase may do so.667 if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) {668 return;669 }670 671 if ( WP_TESTS_FORCE_KNOWN_BUGS ) {672 return;673 }674 $tickets = PHPUnit_Util_Test::getTickets( get_class( $this ), $this->getName( false ) );675 foreach ( $tickets as $ticket ) {676 if ( is_numeric( $ticket ) ) {677 $this->knownWPBug( $ticket );678 } elseif ( 'Plugin' == substr( $ticket, 0, 6 ) ) {679 $ticket = substr( $ticket, 6 );680 if ( $ticket && is_numeric( $ticket ) ) {681 $this->knownPluginBug( $ticket );682 }683 }684 }685 }686 687 /**688 * Skips the current test if there is an open Trac ticket associated with it.689 *690 * @since 3.5.0691 *692 * @param int $ticket_id Ticket number.693 */694 function knownWPBug( $ticket_id ) {695 if ( WP_TESTS_FORCE_KNOWN_BUGS || in_array( $ticket_id, self::$forced_tickets ) ) {696 return;697 }698 if ( ! TracTickets::isTracTicketClosed( 'https://core.trac.wordpress.org', $ticket_id ) ) {699 $this->markTestSkipped( sprintf( 'WordPress Ticket #%d is not fixed', $ticket_id ) );700 }701 }702 703 /**704 * Skips the current test if there is an open Unit Test Trac ticket associated with it.705 *706 * @since 3.5.0707 *708 * @deprecated No longer used since the Unit Test Trac was merged into the Core Trac.709 *710 * @param int $ticket_id Ticket number.711 */712 function knownUTBug( $ticket_id ) {713 return;714 }715 716 /**717 * Skips the current test if there is an open Plugin Trac ticket associated with it.718 *719 * @since 3.5.0720 *721 * @param int $ticket_id Ticket number.722 */723 function knownPluginBug( $ticket_id ) {724 if ( WP_TESTS_FORCE_KNOWN_BUGS || in_array( 'Plugin' . $ticket_id, self::$forced_tickets ) ) {725 return;726 }727 if ( ! TracTickets::isTracTicketClosed( 'https://plugins.trac.wordpress.org', $ticket_id ) ) {728 $this->markTestSkipped( sprintf( 'WordPress Plugin Ticket #%d is not fixed', $ticket_id ) );729 }730 }731 732 /**733 * Adds a Trac ticket number to the `$forced_tickets` property.734 *735 * @since 3.5.0736 *737 * @param int $ticket Ticket number.738 */739 public static function forceTicket( $ticket ) {740 self::$forced_tickets[] = $ticket;741 }742 743 /**744 * Custom preparations for the PHPUnit process isolation template.745 *746 * When restoring global state between tests, PHPUnit defines all the constants that were already defined, and then747 * includes included files. This does not work with WordPress, as the included files define the constants.748 *749 * This method defines the constants after including files.750 *751 * @param Text_Template $template752 */753 function prepareTemplate( Text_Template $template ) {754 $template->setVar( array( 'constants' => '' ) );755 $template->setVar( array( 'wp_constants' => PHPUnit_Util_GlobalState::getConstantsAsString() ) );756 parent::prepareTemplate( $template );757 }758 759 /**760 * Creates a unique temporary file name.761 *762 * The directory in which the file is created depends on the environment configuration.763 *764 * @since 3.5.0765 *766 * @return string|bool Path on success, else false.767 */768 function temp_filename() {769 $tmp_dir = '';770 $dirs = array( 'TMP', 'TMPDIR', 'TEMP' );771 foreach ( $dirs as $dir ) {772 if ( isset( $_ENV[ $dir ] ) && ! empty( $_ENV[ $dir ] ) ) {773 $tmp_dir = $dir;774 break;775 }776 }777 if ( empty( $tmp_dir ) ) {778 $tmp_dir = '/tmp';779 }780 $tmp_dir = realpath( $tmp_dir );781 return tempnam( $tmp_dir, 'wpunit' );782 }783 784 /**785 * Checks each of the WP_Query is_* functions/properties against expected boolean value.786 *787 * Any properties that are listed by name as parameters will be expected to be true; all others are788 * expected to be false. For example, assertQueryTrue('is_single', 'is_feed') means is_single()789 * and is_feed() must be true and everything else must be false to pass.790 *791 * @since 2.5.0792 * @since 3.8.0 Moved from `Tests_Query_Conditionals` to `WP_UnitTestCase`.793 *794 * @param string $prop,... Any number of WP_Query properties that are expected to be true for the current request.795 */796 function assertQueryTrue() {797 global $wp_query;798 $all = array(799 'is_404',800 'is_admin',801 'is_archive',802 'is_attachment',803 'is_author',804 'is_category',805 'is_comment_feed',806 'is_date',807 'is_day',808 'is_embed',809 'is_feed',810 'is_front_page',811 'is_home',812 'is_month',813 'is_page',814 'is_paged',815 'is_post_type_archive',816 'is_posts_page',817 'is_preview',818 'is_robots',819 'is_search',820 'is_single',821 'is_singular',822 'is_tag',823 'is_tax',824 'is_time',825 'is_trackback',826 'is_year',827 );828 $true = func_get_args();829 830 foreach ( $true as $true_thing ) {831 $this->assertContains( $true_thing, $all, "Unknown conditional: {$true_thing}." );832 }833 834 $passed = true;835 $message = '';836 837 foreach ( $all as $query_thing ) {838 $result = is_callable( $query_thing ) ? call_user_func( $query_thing ) : $wp_query->$query_thing;839 840 if ( in_array( $query_thing, $true ) ) {841 if ( ! $result ) {842 $message .= $query_thing . ' is false but is expected to be true. ' . PHP_EOL;843 $passed = false;844 }845 } elseif ( $result ) {846 $message .= $query_thing . ' is true but is expected to be false. ' . PHP_EOL;847 $passed = false;848 }849 }850 851 if ( ! $passed ) {852 $this->fail( $message );853 }854 }855 856 /**857 * Selectively deletes a file.858 *859 * Does not delete a file if its path is set in the `$ignore_files` property.860 *861 * @param string $file File path.862 */863 function unlink( $file ) {864 $exists = is_file( $file );865 if ( $exists && ! in_array( $file, self::$ignore_files ) ) {866 //error_log( $file );867 unlink( $file );868 } elseif ( ! $exists ) {869 $this->fail( "Trying to delete a file that doesn't exist: $file" );870 }871 }872 873 /**874 * Selectively deletes files from a directory.875 *876 * Does not delete files if their paths are set in the `$ignore_files` property.877 *878 * @param string $path Directory path.879 */880 function rmdir( $path ) {881 $files = $this->files_in_dir( $path );882 foreach ( $files as $file ) {883 if ( ! in_array( $file, self::$ignore_files ) ) {884 $this->unlink( $file );885 }886 }887 }888 889 /**890 * Deletes files added to the `uploads` directory during tests.891 *892 * This method works in tandem with the `setUp()` and `rmdir()` methods:893 * - `setUp()` scans the `uploads` directory before every test, and stores its contents inside of the894 * `$ignore_files` property.895 * - `rmdir()` and its helper methods only delete files that are not listed in the `$ignore_files` property. If896 * called during `tearDown()` in tests, this will only delete files added during the previously run test.897 */898 function remove_added_uploads() {899 $uploads = wp_upload_dir();900 $this->rmdir( $uploads['basedir'] );901 }902 903 /**904 * Returns a list of all files contained inside a directory.905 *906 * @since 4.0.0907 *908 * @param string $dir Path to the directory to scan.909 *910 * @return array List of file paths.911 */912 function files_in_dir( $dir ) {913 $files = array();914 915 $iterator = new RecursiveDirectoryIterator( $dir );916 $objects = new RecursiveIteratorIterator( $iterator );917 foreach ( $objects as $name => $object ) {918 if ( is_file( $name ) ) {919 $files[] = $name;920 }921 }922 923 return $files;924 }925 926 /**927 * Returns a list of all files contained inside the `uploads` directory.928 *929 * @since 4.0.0930 *931 * @return array List of file paths.932 */933 function scan_user_uploads() {934 static $files = array();935 if ( ! empty( $files ) ) {936 return $files;937 }938 939 $uploads = wp_upload_dir();940 $files = $this->files_in_dir( $uploads['basedir'] );941 return $files;942 }943 944 /**945 * Deletes all directories contained inside a directory.946 *947 * @since 4.1.0948 *949 * @param string $path Path to the directory to scan.950 */951 function delete_folders( $path ) {952 $this->matched_dirs = array();953 if ( ! is_dir( $path ) ) {954 return;955 }956 957 $this->scandir( $path );958 foreach ( array_reverse( $this->matched_dirs ) as $dir ) {959 rmdir( $dir );960 }961 rmdir( $path );962 }963 964 /**965 * Retrieves all directories contained inside a directory and stores them in the `$matched_dirs` property. Hidden966 * directories are ignored.967 *968 * This is a helper for the `delete_folders()` method.969 *970 * @since 4.1.0971 *972 * @param string $dir Path to the directory to scan.973 */974 function scandir( $dir ) {975 foreach ( scandir( $dir ) as $path ) {976 if ( 0 !== strpos( $path, '.' ) && is_dir( $dir . '/' . $path ) ) {977 $this->matched_dirs[] = $dir . '/' . $path;978 $this->scandir( $dir . '/' . $path );979 }980 }981 }982 983 /**984 * Converts a microtime string into a float.985 *986 * @since 4.1.0987 *988 * @param string $microtime Time string generated by `microtime()`.989 *990 * @return float `microtime()` output as a float.991 */992 protected function _microtime_to_float( $microtime ) {993 $time_array = explode( ' ', $microtime );994 return array_sum( $time_array );995 }996 997 /**998 * Deletes a user from the database in a Multisite-agnostic way.999 *1000 * @since 4.3.01001 *1002 * @param int $user_id User ID.1003 *1004 * @return bool True if the user was deleted.1005 */1006 public static function delete_user( $user_id ) {1007 if ( is_multisite() ) {1008 return wpmu_delete_user( $user_id );1009 } else {1010 return wp_delete_user( $user_id );1011 }1012 }1013 1014 /**1015 * Resets permalinks and flushes rewrites.1016 *1017 * @since 4.4.01018 *1019 * @global WP_Rewrite $wp_rewrite1020 *1021 * @param string $structure Optional. Permalink structure to set. Default empty.1022 */1023 public function set_permalink_structure( $structure = '' ) {1024 global $wp_rewrite;1025 1026 $wp_rewrite->init();1027 $wp_rewrite->set_permalink_structure( $structure );1028 $wp_rewrite->flush_rules();1029 }1030 1031 /**1032 * Creates an attachment post from an uploaded file.1033 *1034 * @since 4.4.01035 *1036 * @param array $upload Array of information about the uploaded file, provided by wp_upload_bits().1037 * @param int $parent_post_id Optional. Parent post ID.1038 *1039 * @return int|WP_Error The attachment ID on success. The value 0 or WP_Error on failure.1040 */1041 function _make_attachment( $upload, $parent_post_id = 0 ) {1042 $type = '';1043 if ( ! empty( $upload['type'] ) ) {1044 $type = $upload['type'];1045 } else {1046 $mime = wp_check_filetype( $upload['file'] );1047 if ( $mime ) {1048 $type = $mime['type'];1049 }1050 }1051 1052 $attachment = array(1053 'post_title' => basename( $upload['file'] ),1054 'post_content' => '',1055 'post_type' => 'attachment',1056 'post_parent' => $parent_post_id,1057 'post_mime_type' => $type,1058 'guid' => $upload['url'],1059 );1060 1061 $id = wp_insert_attachment( $attachment, $upload['file'], $parent_post_id );1062 wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );1063 return $id;1064 }1065 1066 /**1067 * Updates the modified and modified GMT date of a post in the database.1068 *1069 * @since 4.8.01070 *1071 * @global wpdb $wpdb WordPress database abstraction object.1072 *1073 * @param int $post_id Post ID.1074 * @param string $date Post date, in the format YYYY-MM-DD HH:MM:SS.1075 *1076 * @return int|false 1 on success, or false on error.1077 */1078 protected function update_post_modified( $post_id, $date ) {1079 global $wpdb;1080 return $wpdb->update(1081 $wpdb->posts,1082 array(1083 'post_modified' => $date,1084 'post_modified_gmt' => $date,1085 ),1086 array(1087 'ID' => $post_id,1088 ),1089 array(1090 '%s',1091 '%s',1092 ),1093 array(1094 '%d',1095 )1096 );1097 }1098 32 } -
tests/phpunit/multisite.xml
34 34 <const name="WP_RUN_CORE_TESTS" value="1" /> 35 35 </php> 36 36 <listeners> 37 <listener class="SpeedTrapListener" file="tests/phpunit/includes/ speed-trap-listener.php">37 <listener class="SpeedTrapListener" file="tests/phpunit/includes/listener-loader.php"> 38 38 <arguments> 39 39 <array> 40 40 <element key="slowThreshold"> -
tests/phpunit/tests/post/query.php
673 673 674 674 $q->posts = $posts; 675 675 676 $methd = new \ReflectionMethod( 'WP_Query', 'set_found_posts' );676 $methd = new ReflectionMethod( 'WP_Query', 'set_found_posts' ); 677 677 $methd->setAccessible( true ); 678 678 $methd->invoke( $q, array( 'no_found_rows' => false ), array() ); 679 679