WordPress.org

Make WordPress Core

Ticket #39309: 39309-tests.diff

File 39309-tests.diff, 13.8 KB (added by dd32, 3 months ago)
  • .travis.yml

    diff --git a/.travis.yml b/.travis.yml
    index 0e186dc8c7..009d64af26 100644
    a b env: 
    1212    - WP_TRAVISCI=travis:phpunit
    1313matrix:
    1414  include:
     15  - php: 7.3
     16    env: WP_TRAVISCI=travis:phpunit:upgrade
    1517  - php: 7.2
    1618    env: WP_TRAVISCI=travis:format
    1719  - php: 7.1
    matrix: 
    3335  fast_finish: true
    3436before_install:
    3537- |
    36   if [[ "$WP_TRAVISCI" == "travis:phpunit" ]]; then
     38  if [[ "$WP_TRAVISCI" == travis:phpunit* ]]; then
    3739      mysql -u root -e "CREATE DATABASE wordpress_tests;"
    3840      cp wp-tests-config-sample.php wp-tests-config.php
    3941      sed -i "s/youremptytestdbnamehere/wordpress_tests/" wp-tests-config.php
    before_script: 
    6062  export PATH=`composer config --list --global | grep '\[home\]' | { read a; echo "${a#* }/vendor/bin:$PATH"; }`
    6163- |
    6264  # Install the specified version of PHPUnit depending on the PHP version:
    63   if [[ "$WP_TRAVISCI" == "travis:phpunit" ]]; then
     65  if [[ "$WP_TRAVISCI" == travis:phpunit* ]]; then
    6466    case "$TRAVIS_PHP_VERSION" in
    6567      7.4snapshot|7.3|7.2|7.1|nightly)
    6668        echo "Using PHPUnit 7.x"
  • Gruntfile.js

    diff --git a/Gruntfile.js b/Gruntfile.js
    index 2397b11fa4..78c2f21724 100644
    a b module.exports = function(grunt) { 
    666666                                args: ['--verbose', '-c', 'phpunit.xml.dist', '--group', 'restapi-jsclient']
    667667                        }
    668668                },
     669                travis_phpunit_upgrade: {
     670                        'default' : {
     671                                cmd: 'phpunit',
     672                                args: [ '--verbose', '-c', 'phpunit.xml.dist', '--group', 'upgrade-tests' ]
     673                        }
     674                },
    669675                uglify: {
    670676                        options: {
    671677                                ASCIIOnly: true,
    module.exports = function(grunt) { 
    14071413                }, this.async());
    14081414        });
    14091415
     1416        grunt.registerMultiTask('travis_phpunit_upgrade', 'Runs Upgrade PHPUnit tests.', function() {
     1417                grunt.util.spawn({
     1418                        cmd: this.data.cmd,
     1419                        args: this.data.args,
     1420                        opts: {stdio: 'inherit'}
     1421                }, this.async());
     1422        });
     1423
    14101424        grunt.registerTask('qunit:compiled', 'Runs QUnit tests on compiled as well as uncompiled scripts.',
    14111425                ['build', 'copy:qunit', 'qunit']);
    14121426
    module.exports = function(grunt) { 
    14331447        // Travis CI tasks.
    14341448        grunt.registerTask('travis:js', 'Runs Javascript Travis CI tasks.', [ 'jshint:corejs', 'qunit:compiled' ]);
    14351449        grunt.registerTask('travis:phpunit', 'Runs PHPUnit Travis CI tasks.', [ 'build', 'phpunit' ]);
     1450        grunt.registerTask('travis:phpunit:upgrade', 'Runs Upgrade PHPUnit Travis CI tasks.', [ 'build', 'travis_phpunit_upgrade' ]);
    14361451        grunt.registerTask('travis:format', 'Runs Code formatting Travis CI tasks.', [ 'format:php:error' ]);
    14371452
    14381453        // Patch task.
  • phpunit.xml.dist

    diff --git a/phpunit.xml.dist b/phpunit.xml.dist
    index faef186978..70a131cb14 100644
    a b  
    3131                        <group>ms-files</group>
    3232                        <group>ms-required</group>
    3333                        <group>external-http</group>
     34                        <group>upgrade-tests</group>
    3435                </exclude>
    3536        </groups>
    3637        <logging>
  • tests/phpunit/includes/bootstrap.php

    diff --git a/tests/phpunit/includes/bootstrap.php b/tests/phpunit/includes/bootstrap.php
    index 23faca64e5..58e0c51e73 100644
    a b function wp_tests_options( $value ) { 
    145145require dirname( __FILE__ ) . '/testcase-xmlrpc.php';
    146146require dirname( __FILE__ ) . '/testcase-ajax.php';
    147147require dirname( __FILE__ ) . '/testcase-canonical.php';
     148require dirname( __FILE__ ) . '/testcase-upgrade.php';
    148149require dirname( __FILE__ ) . '/exceptions.php';
    149150require dirname( __FILE__ ) . '/utils.php';
    150151require dirname( __FILE__ ) . '/spy-rest-server.php';
    151152require dirname( __FILE__ ) . '/class-wp-rest-test-search-handler.php';
    152153require dirname( __FILE__ ) . '/class-wp-fake-block-type.php';
     154require dirname( __FILE__ ) . '/class-wp-tests-upgrader-skin.php';
    153155
    154156/**
    155157 * A class to handle additional command line arguments passed to the script.
    function __construct( $argv ) { 
    168170                        'ajax'          => true,
    169171                        'ms-files'      => true,
    170172                        'external-http' => true,
     173                        'upgrade-tests' => true,
    171174                );
    172175
    173176                while ( current( $argv ) ) {
  • new file tests/phpunit/includes/class-wp-tests-upgrader-skin.php

    diff --git a/tests/phpunit/includes/class-wp-tests-upgrader-skin.php b/tests/phpunit/includes/class-wp-tests-upgrader-skin.php
    new file mode 100644
    index 0000000000..6200387666
    - +  
     1<?php
     2
     3require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
     4
     5class WP_Tests_Upgrader_Skin extends Automatic_Upgrader_Skin {
     6        function header() {}
     7        function footer() {}
     8        // Assume it's all fine and dandy when we're running in tests. We're not testing Filesystem access afterall.
     9        function request_filesystem_credentials( $error = false, $context = '', $allow_relaxed_file_ownership = false ) {
     10                return true;
     11        }
     12}
  • new file tests/phpunit/includes/testcase-upgrade.php

    diff --git a/tests/phpunit/includes/testcase-upgrade.php b/tests/phpunit/includes/testcase-upgrade.php
    new file mode 100644
    index 0000000000..e86d63c069
    - +  
     1<?php
     2
     3abstract class WP_Upgrader_UnitTestCase extends WP_UnitTestCase {
     4
     5        // This might not actually install the plugin, as it may already exist.
     6        // We're not interested in actually installing the plugin though, just the steps prior to the install.
     7        function install_plugin_and_return_messages( $plugin_slug ) {
     8                include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' ); // For plugins_api()
     9
     10                if ( preg_match( '!^https?://!i', $plugin_slug ) ) {
     11                        // The $plugin_slug looked like a URL, so we'll install that.
     12                        $package_url = $plugin_slug;
     13                } else {
     14                        $api = plugins_api( 'plugin_information', array( 'slug' => $plugin_slug ) );
     15                        // Temporary error
     16                        if ( is_wp_error( $api ) ) {
     17                                wp_die( $api );
     18                        }
     19                        $package_url = $api->download_link;
     20                }
     21
     22                $skin     = new WP_Tests_Upgrader_Skin();
     23                $upgrader = new Plugin_Upgrader( $skin );
     24                $upgrader->install( $package_url );
     25
     26                return $skin->get_upgrade_messages();
     27        }
     28
     29        // TODO Filter - Ensure that all requests to WordPress.org include the nostats parameter.
     30
     31        // Filter - Ensure WordPress has a single invalid key.
     32        function filter_wp_trusted_keys_only_invalid_key() {
     33                return array(
     34                        $this->helper_random_public_key(),
     35                );
     36        }
     37        // Filter - Prefix a random key to WordPress's existing keys.
     38        function filter_wp_trusted_keys_prefix_invalid_key( $keys ) {
     39                return array_merge(
     40                        array( $this->helper_random_public_key() ),
     41                        $keys
     42                );
     43        }
     44        // Helper - Generate a new random public key.
     45        function helper_random_public_key() {
     46                static $key = false;
     47                if ( $key ) {
     48                        return $key;
     49                }
     50
     51                // Generate a new key.
     52                $random_keypair    = sodium_crypto_sign_keypair();
     53                $random_public_key = sodium_crypto_sign_publickey( $random_keypair );
     54                return base64_encode( $random_public_key );
     55        }
     56}
  • tests/phpunit/multisite.xml

    diff --git a/tests/phpunit/multisite.xml b/tests/phpunit/multisite.xml
    index 620b20fc0d..8eba4921bc 100644
    a b  
    4040                        <group>ms-excluded</group>
    4141                        <group>external-http</group>
    4242                        <group>oembed-headers</group>
     43                        <group>upgrade-tests</group>
    4344                </exclude>
    4445        </groups>
    4546        <listeners>
  • new file tests/phpunit/tests/upgrade/plugins.php

    diff --git a/tests/phpunit/tests/upgrade/plugins.php b/tests/phpunit/tests/upgrade/plugins.php
    new file mode 100644
    index 0000000000..7381b898a3
    - +  
     1<?php
     2
     3class Plugin_Upgrader_Tests extends WP_Upgrader_UnitTestCase {
     4        /**
     5         * Integration test - Install a plugin, make sure it succeeds.
     6         * @group upgrade-tests
     7         */
     8        function test_install_plugin_hello_dolly() {
     9                $messages = $this->install_plugin_and_return_messages( 'hello-dolly' );
     10                $this->assertContains( 'Plugin installed successfully.', $messages );
     11
     12                /*
     13                foreach ( $messages as $message ) {
     14                        // TODO: This is a bit fragile and has to be kept in sync with verify_file_signature(), and needs to be enabled for all plugins first.
     15                        $this->assertNotContains( 'could not be verified', $message );
     16                }
     17                */
     18
     19                // Now install it again, it should fail.
     20                $messages = $this->install_plugin_and_return_messages( 'hello-dolly' );
     21                $this->assertNotContains( 'Plugin installed successfully.', $messages );
     22        }
     23
     24        /**
     25         * Integration test - Install a plugin, make sure it succeeds.
     26         * @group upgrade-tests
     27         */
     28        function test_install_plugin_hello_dolly_signing_failure() {
     29
     30                add_filter( 'wp_trusted_keys', array( $this, 'filter_wp_trusted_keys_only_invalid_key' ) );
     31
     32                // We don't care if this installation succeeds, we just need to get to the 'downloading' phase which is before it bails because it's already installed.
     33                $messages = $this->install_plugin_and_return_messages( 'hello-dolly' );
     34
     35                remove_filter( 'wp_trusted_keys', array( $this, 'filter_wp_trusted_keys_only_invalid_key' ) );
     36
     37                $signing_failed = false;
     38                foreach ( $messages as $message ) {
     39                        $signing_failed = $signing_failed || ( false !== stripos( $message, 'could not be verified' ) );
     40                }
     41
     42                $this->assertTrue( $signing_failed );
     43        }
     44
     45        /**
     46         * Integration test - Install a plugin, make sure it succeeds.
     47         * @group upgrade-tests
     48         */
     49        function test_install_plugin_hello_dolly_add_bad_key() {
     50                $this->markTestSkipped( 'Plugins do not yet have signatures.' );
     51
     52                add_filter( 'wp_trusted_keys', array( $this, 'filter_wp_trusted_keys_prefix_invalid_key' ) );
     53
     54                // We don't care if this installation succeeds, we just want to make sure that
     55                $messages = $this->install_plugin_and_return_messages( 'hello-dolly' );
     56
     57                remove_filter( 'wp_trusted_keys', array( $this, 'filter_wp_trusted_keys_prefix_invalid_key' ) );
     58
     59                // There should be NO update strings which mention failures, if this plugin has signatures available.
     60                foreach ( $messages as $message ) {
     61                        // TODO: This is a bit fragile and has to be kept in sync with verify_file_signature()
     62                        $this->assertNotContains( 'could not be verified', $message );
     63                }
     64        }
     65
     66        /**
     67         * Integration test - Install a plugin from Github, make sure it succeeds.
     68         * @group upgrade-tests
     69         */
     70        function test_install_plugin_github_wordpress_importer() {
     71                $messages = $this->install_plugin_and_return_messages( 'https://github.com/WordPress/wordpress-importer/archive/master.zip' );
     72
     73                $this->assertContains( 'Plugin installed successfully.', $messages );
     74
     75                foreach ( $messages as $message ) {
     76                        // TODO: This is a bit fragile and has to be kept in sync with verify_file_signature()
     77                        $this->assertNotContains( 'could not be verified', $message );
     78                }
     79        }
     80
     81        /**
     82         * Integration test - Install a plugin, check updates pass.
     83         * @group upgrade-tests
     84         */
     85        function test_update_plugin_hello_dolly() {
     86                $hello_dolly = WP_PLUGIN_DIR . '/hello-dolly/hello.php';
     87                // If the plugins already installed from another test, save some time.
     88                if ( ! file_exists( $hello_dolly ) ) {
     89                        $messages = $this->install_plugin_and_return_messages( 'hello-dolly' );
     90                        $this->assertContains( 'Plugin installed successfully.', $messages );
     91                }
     92
     93                // Lower the version string of the plugin..
     94                $contents = file_get_contents( $hello_dolly );
     95                $contents = preg_replace_callback(
     96                        '!^([\s*]*Version:\s*)([\d.]+)$!im',
     97                        function( $m ) {
     98                                return $m[1] . ( floatval( $m[2] ) - 0.1 );
     99                        },
     100                        $contents
     101                );
     102                file_put_contents( $hello_dolly, $contents );
     103
     104                // Get the update..
     105                wp_update_plugins();
     106
     107                $skin     = new WP_Tests_Upgrader_Skin();
     108                $upgrader = new Plugin_Upgrader( $skin );
     109                $result   = $upgrader->upgrade(
     110                        plugin_basename( $hello_dolly )
     111                );
     112
     113                $messages = $skin->get_upgrade_messages();
     114
     115                $this->assertTrue( $result );
     116                $this->assertContains( 'Plugin updated successfully.', $messages );
     117
     118                /*
     119                foreach ( $messages as $message ) {
     120                        // TODO: This is a bit fragile and has to be kept in sync with verify_file_signature(), and needs to be enabled for all plugins first.
     121                        $this->assertNotContains( 'could not be verified', $message );
     122                }
     123                */
     124
     125        }
     126
     127        function tearDown() {
     128                delete_plugins(
     129                        [
     130                                'hello-dolly/hello.php',
     131                                'wordpress-importer-master/wordpress-importer.php',
     132                        ]
     133                );
     134        }
     135}
  • new file tests/phpunit/tests/upgrade/zz-core.php

    diff --git a/tests/phpunit/tests/upgrade/themes.php b/tests/phpunit/tests/upgrade/themes.php
    new file mode 100644
    index 0000000000..e69de29bb2
    diff --git a/tests/phpunit/tests/upgrade/zz-core.php b/tests/phpunit/tests/upgrade/zz-core.php
    new file mode 100644
    index 0000000000..9b901825f4
    - +  
     1<?php
     2
     3// Note: This file is named 'zz-core.php' in an attempt to run it last within travis runs of this group.
     4// There's surely a better way, but this solves it for now.
     5
     6class Core_Upgrader_Tests extends WP_Upgrader_UnitTestCase {
     7        /**
     8         * Integration test - Test a reinstall of WordPress.
     9         * @group upgrade-tests
     10         */
     11        function test_core_reinstall() {
     12                if ( ! getenv( 'WP_TRAVISCI' ) ) {
     13                        $this->markTestSkipped( "We don't appear to be running in a travis environment." );
     14                }
     15
     16                // $skin will get first few update messages, and then they'll be available through `update_feedback` instead.
     17                $skin = new WP_Tests_Upgrader_Skin();
     18                add_filter( 'update_feedback', [ $skin, 'feedback' ], 0, 1 );
     19
     20                wp_version_check();
     21                // Assume that the first upgrade included is either development, or latest.
     22                $update = get_site_transient( 'update_core' )->updates[0];
     23
     24                WP_Filesystem( [], ABSPATH, true );
     25                $upgrader = new Core_Upgrader( $skin );
     26                $result   = $upgrader->upgrade(
     27                        $update,
     28                        array(
     29                                'allow_relaxed_file_ownership' => true,
     30                        )
     31                );
     32
     33                remove_filter( 'update_feedback', [ $skin, 'feedback' ], 1 );
     34
     35                $messages = $skin->get_upgrade_messages();
     36                foreach ( $messages as $message ) {
     37                        // TODO: This is a bit fragile and has to be kept in sync with verify_file_signature()
     38                        $this->assertNotContains( 'could not be verified', $message );
     39                }
     40
     41                // $result is the new version on success
     42
     43                $this->assertNotWPError( $result );
     44                $this->assertNotFalse( $result );
     45                $this->assertGreaterThanOrEqual( 1, did_action( '_core_updated_successfully' ) );
     46
     47        }
     48}