WordPress.org

Make WordPress Core


Ignore:
Timestamp:
12/10/2014 10:56:25 PM (6 years ago)
Author:
pento
Message:

WPDB: In [30345,30346,30366,30375], we added sanity checks for saving posts containing emoji. We need to revert these checks for now, as they're not ready for release in 4.1.

See #21212.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/4.1/tests/phpunit/tests/db/charset.php

    r30699 r30807  
    1 <?php
    2 
    3 require_once dirname( dirname( __FILE__ ) ) . '/db.php';
    4 
    5 /**
    6  * Test WPDB methods
    7  *
    8  * @group wpdb
    9  */
    10 class Tests_DB_Charset extends WP_UnitTestCase {
    11 
    12     /**
    13      * Our special WPDB
    14      * @var resource
    15      */
    16     protected static $_wpdb;
    17 
    18     public static function setUpBeforeClass() {
    19         self::$_wpdb = new wpdb_exposed_methods_for_testing();
    20     }
    21 
    22     /**
    23      * @ticket 21212
    24      */
    25     function data_strip_invalid_text() {
    26         $fields = array(
    27             'latin1' => array(
    28                 // latin1. latin1 never changes.
    29                 'charset'  => 'latin1',
    30                 'value'    => "\xf0\x9f\x8e\xb7",
    31                 'expected' => "\xf0\x9f\x8e\xb7"
    32             ),
    33             'ascii' => array(
    34                 // ascii gets special treatment, make sure it's covered
    35                 'charset'  => 'ascii',
    36                 'value'    => 'Hello World',
    37                 'expected' => 'Hello World'
    38             ),
    39             'utf8' => array(
    40                 // utf8 only allows <= 3-byte chars
    41                 'charset'  => 'utf8',
    42                 'value'    => "H€llo\xf0\x9f\x98\x88World¢",
    43                 'expected' => 'H€lloWorld¢'
    44             ),
    45             'utf8mb3' => array(
    46                 // utf8mb3 should behave the same an utf8
    47                 'charset'  => 'utf8mb3',
    48                 'value'    => "H€llo\xf0\x9f\x98\x88World¢",
    49                 'expected' => 'H€lloWorld¢'
    50             ),
    51             'utf8mb4' => array(
    52                 // utf8mb4 allows 4-byte characters, too
    53                 'charset'  => 'utf8mb4',
    54                 'value'    => "H€llo\xf0\x9f\x98\x88World¢",
    55                 'expected' => "H€llo\xf0\x9f\x98\x88World¢"
    56             ),
    57             'koi8r' => array(
    58                 // koi8r is a character set that needs to be checked in MySQL
    59                 'charset'  => 'koi8r',
    60                 'value'    => "\xfdord\xf2ress",
    61                 'expected' => "\xfdord\xf2ress",
    62                 'db'       => true
    63             ),
    64             'hebrew' => array(
    65                 // hebrew needs to be checked in MySQL, too
    66                 'charset'  => 'hebrew',
    67                 'value'    => "\xf9ord\xf7ress",
    68                 'expected' => "\xf9ord\xf7ress",
    69                 'db'       => true
    70             ),
    71             'false' => array(
    72                 // false is a column with no character set (ie, a number column)
    73                 'charset'  => false,
    74                 'value'    => 100,
    75                 'expected' => 100
    76             ),
    77         );
    78 
    79         if ( function_exists( 'mb_convert_encoding' ) ) {
    80             // big5 is a non-Unicode multibyte charset
    81             $utf8 = "a\xe5\x85\xb1b"; // UTF-8 Character 20849
    82             $big5 = mb_convert_encoding( $utf8, 'BIG-5', 'UTF-8' );
    83             $conv_utf8 = mb_convert_encoding( $big5, 'UTF-8', 'BIG-5' );
    84             // Make sure PHP's multibyte conversions are working correctly
    85             $this->assertNotEquals( $utf8, $big5 );
    86             $this->assertEquals( $utf8, $conv_utf8 );
    87 
    88             $fields['big5'] = array(
    89                 'charset'  => 'big5',
    90                 'value'    => $big5,
    91                 'expected' => $big5
    92             );
    93         }
    94 
    95         // The data above is easy to edit. Now, prepare it for the data provider.
    96         $data_provider = $multiple = $multiple_expected = array();
    97         foreach ( $fields as $test_case => $field ) {
    98             $expected = $field;
    99             $expected['value'] = $expected['expected'];
    100             unset( $expected['expected'], $field['expected'] );
    101 
    102             // We're keeping track of these for our multiple-field test.
    103             $multiple[] = $field;
    104             $multiple_expected[] = $expected;
    105 
    106             // strip_invalid_text() expects an array of fields. We're testing one field at a time.
    107             $data = array( $field );
    108             $expected = array( $expected );
    109 
    110             // First argument is field data. Second is expected. Third is the message.
    111             $data_provider[] = array( $data, $expected, $test_case );
    112         }
    113 
    114         // Time for our test of multiple fields at once.
    115         $data_provider[] = array( $multiple, $multiple_expected, 'multiple fields/charsets' );
    116 
    117         return $data_provider;
    118     }
    119 
    120     /**
    121      * @dataProvider data_strip_invalid_text
    122      * @ticket 21212
    123      */
    124     function test_strip_invalid_text( $data, $expected, $message ) {
    125         if ( $data[0]['charset'] === 'koi8r' ) {
    126             self::$_wpdb->query( 'SET NAMES koi8r' );
    127         }
    128         $actual = self::$_wpdb->strip_invalid_text( $data );
    129         $this->assertSame( $expected, $actual, $message );
    130     }
    131 
    132     /**
    133      * @ ticket 21212
    134      */
    135     function test_process_fields_failure() {
    136         global $wpdb;
    137         $data = array( 'post_content' => "H€llo\xf0\x9f\x98\x88World¢" );
    138         $this->assertFalse( self::$_wpdb->process_fields( $wpdb->posts, $data, null ) );
    139     }
    140 
    141     /**
    142      * @ticket 21212
    143      */
    144     function data_process_field_charsets() {
    145         $charset = $GLOBALS['wpdb']->charset; // This is how all tables were installed
    146         // 'value' and 'format' are $data, 'charset' ends up as part of $expected
    147 
    148         $no_string_fields = array(
    149             'post_parent' => array( 'value' => 10, 'format' => '%d', 'charset' => false ),
    150             'comment_count' => array( 'value' => 0, 'format' => '%d', 'charset' => false ),
    151         );
    152 
    153         $all_ascii_fields = array(
    154             'post_content' => array( 'value' => 'foo foo foo!', 'format' => '%s', 'charset' => false ),
    155             'post_excerpt' => array( 'value' => 'bar bar bar!', 'format' => '%s', 'charset' => false ),
    156         );
    157 
    158         // This is the same data used in process_field_charsets_for_nonexistent_table()
    159         $non_ascii_string_fields = array(
    160             'post_content' => array( 'value' => '¡foo foo foo!', 'format' => '%s', 'charset' => $charset, 'ascii' => false ),
    161             'post_excerpt' => array( 'value' => '¡bar bar bar!', 'format' => '%s', 'charset' => $charset, 'ascii' => false ),
    162         );
    163 
    164         $vars = get_defined_vars();
    165         unset( $vars['charset'] );
    166         foreach ( $vars as $var_name => $var ) {
    167             $data = $expected = $var;
    168             foreach ( $data as &$datum ) {
    169                 // 'charset' and 'ascii' are part of the expected return only.
    170                 unset( $datum['charset'], $datum['ascii'] );
    171             }
    172 
    173             $vars[ $var_name ] = array( $data, $expected, $var_name );
    174         }
    175 
    176         return array_values( $vars );
    177     }
    178 
    179     /**
    180      * @dataProvider data_process_field_charsets
    181      * @ticket 21212
    182      */
    183     function test_process_field_charsets( $data, $expected, $message ) {
    184         $actual = self::$_wpdb->process_field_charsets( $data, $GLOBALS['wpdb']->posts );
    185         $this->assertSame( $expected, $actual, $message );
    186     }
    187 
    188     /**
    189      * The test this test depends on first verifies that this
    190      * would normally work against the posts table.
    191      *
    192      * @ticket 21212
    193      * @depends test_process_field_charsets
    194      */
    195     function test_process_field_charsets_on_nonexistent_table() {
    196         $data = array( 'post_content' => array( 'value' => '¡foo foo foo!', 'format' => '%s' ) );
    197         self::$_wpdb->suppress_errors( true );
    198         $this->assertFalse( self::$_wpdb->process_field_charsets( $data, 'nonexistent_table' ) );
    199         self::$_wpdb->suppress_errors( false );
    200     }
    201 
    202     /**
    203      * @ticket 21212
    204      */
    205     function test_check_ascii() {
    206         $ascii = "\0\t\n\r '" . '!"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
    207         $this->assertTrue( self::$_wpdb->check_ascii( $ascii ) );
    208     }
    209 
    210     /**
    211      * @ticket 21212
    212      */
    213     function test_check_ascii_false() {
    214         $this->assertFalse( self::$_wpdb->check_ascii( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ¡©«' ) );
    215     }
    216 
    217     /**
    218      * @ticket 21212
    219      */
    220     function test_strip_invalid_text_for_column() {
    221         global $wpdb;
    222         // Invalid 3-byte and 4-byte sequences
    223         $value = "H€llo\xe0\x80\x80World\xf0\xff\xff\xff¢";
    224         $expected = "H€lloWorld¢";
    225         $actual = $wpdb->strip_invalid_text_for_column( $wpdb->posts, 'post_content', $value );
    226         $this->assertEquals( $expected, $actual );
    227     }
    228 
    229     /**
    230      * Set of table definitions for testing wpdb::get_table_charset and wpdb::get_column_charset
    231      * @var array
    232      */
    233     protected $table_and_column_defs = array(
    234         array(
    235             'definition'      => '( a INT, b FLOAT )',
    236             'table_expected'  => false,
    237             'column_expected' => array( 'a' => false, 'b' => false )
    238         ),
    239         array(
    240             'definition'      => '( a VARCHAR(50) CHARACTER SET big5, b TEXT CHARACTER SET big5 )',
    241             'table_expected'  => 'big5',
    242             'column_expected' => array( 'a' => 'big5', 'b' => 'big5' )
    243         ),
    244         array(
    245             'definition'      => '( a VARCHAR(50) CHARACTER SET big5, b BINARY )',
    246             'table_expected'  => 'binary',
    247             'column_expected' => array( 'a' => 'big5', 'b' => false )
    248         ),
    249         array(
    250             'definition'      => '( a VARCHAR(50) CHARACTER SET latin1, b BLOB )',
    251             'table_expected'  => 'binary',
    252             'column_expected' => array( 'a' => 'latin1', 'b' => false )
    253         ),
    254         array(
    255             'definition'      => '( a VARCHAR(50) CHARACTER SET latin1, b TEXT CHARACTER SET koi8r )',
    256             'table_expected'  => 'koi8r',
    257             'column_expected' => array( 'a' => 'latin1', 'b' => 'koi8r' )
    258         ),
    259         array(
    260             'definition'      => '( a VARCHAR(50) CHARACTER SET utf8mb3, b TEXT CHARACTER SET utf8mb3 )',
    261             'table_expected'  => 'utf8',
    262             'column_expected' => array( 'a' => 'utf8', 'b' => 'utf8' )
    263         ),
    264         array(
    265             'definition'      => '( a VARCHAR(50) CHARACTER SET utf8, b TEXT CHARACTER SET utf8mb4 )',
    266             'table_expected'  => 'utf8',
    267             'column_expected' => array( 'a' => 'utf8', 'b' => 'utf8mb4' )
    268         ),
    269         array(
    270             'definition'      => '( a VARCHAR(50) CHARACTER SET big5, b TEXT CHARACTER SET koi8r )',
    271             'table_expected'  => 'ascii',
    272             'column_expected' => array( 'a' => 'big5', 'b' => 'koi8r' )
    273         ),
    274     );
    275 
    276     /**
    277      * @ticket 21212
    278      */
    279     function data_test_get_table_charset() {
    280         $table_name = 'test_get_table_charset';
    281 
    282         $vars = array();
    283         foreach( $this->table_and_column_defs as $value ) {
    284             $this_table_name = $table_name . '_' . rand_str( 5 );
    285             $drop = "DROP TABLE IF EXISTS $this_table_name";
    286             $create = "CREATE TABLE $this_table_name {$value['definition']}";
    287             $vars[] = array( $drop, $create, $this_table_name, $value['table_expected'] );
    288         }
    289 
    290         return $vars;
    291     }
    292 
    293     /**
    294      * @dataProvider data_test_get_table_charset
    295      * @ticket 21212
    296      */
    297     function test_get_table_charset( $drop, $create, $table, $expected_charset ) {
    298         self::$_wpdb->query( $drop );
    299 
    300         if ( ! self::$_wpdb->has_cap( 'utf8mb4' ) && preg_match( '/utf8mb[34]/i', $create ) ) {
    301             $this->markTestSkipped( "This version of MySQL doesn't support utf8mb4." );
    302             return;
    303         }
    304 
    305         self::$_wpdb->query( $create );
    306 
    307         $charset = self::$_wpdb->get_table_charset( $table );
    308         $this->assertEquals( $charset, $expected_charset );
    309 
    310         $charset = self::$_wpdb->get_table_charset( strtoupper( $table ) );
    311         $this->assertEquals( $charset, $expected_charset );
    312 
    313         self::$_wpdb->query( $drop );
    314     }
    315 
    316     /**
    317      * @ticket 21212
    318      */
    319     function data_test_get_column_charset() {
    320         $table_name = 'test_get_column_charset';
    321 
    322         $vars = array();
    323         foreach( $this->table_and_column_defs as $value ) {
    324             $this_table_name = $table_name . '_' . rand_str( 5 );
    325             $drop = "DROP TABLE IF EXISTS $this_table_name";
    326             $create = "CREATE TABLE $this_table_name {$value['definition']}";
    327             $vars[] = array( $drop, $create, $this_table_name, $value['column_expected'] );
    328         }
    329 
    330         return $vars;
    331     }
    332 
    333     /**
    334      * @dataProvider data_test_get_column_charset
    335      * @ticket 21212
    336      */
    337     function test_get_column_charset( $drop, $create, $table, $expected_charset ) {
    338         self::$_wpdb->query( $drop );
    339 
    340         if ( ! self::$_wpdb->has_cap( 'utf8mb4' ) && preg_match( '/utf8mb[34]/i', $create ) ) {
    341             $this->markTestSkipped( "This version of MySQL doesn't support utf8mb4." );
    342             return;
    343         }
    344 
    345         self::$_wpdb->query( $create );
    346 
    347         foreach ( $expected_charset as $column => $charset ) {
    348             $this->assertEquals( $charset, self::$_wpdb->get_col_charset( $table, $column ) );
    349             $this->assertEquals( $charset, self::$_wpdb->get_col_charset( strtoupper( $table ), strtoupper( $column ) ) );
    350         }
    351 
    352         self::$_wpdb->query( $drop );
    353     }
    354 
    355     /**
    356      * @dataProvider data_test_get_column_charset
    357      * @ticket 21212
    358      */
    359     function test_get_column_charset_non_mysql( $drop, $create, $table, $columns ) {
    360         self::$_wpdb->query( $drop );
    361 
    362         if ( ! self::$_wpdb->has_cap( 'utf8mb4' ) && preg_match( '/utf8mb[34]/i', $create ) ) {
    363             $this->markTestSkipped( "This version of MySQL doesn't support utf8mb4." );
    364             return;
    365         }
    366 
    367         self::$_wpdb->is_mysql = false;
    368 
    369         self::$_wpdb->query( $create );
    370 
    371         $columns = array_keys( $columns );
    372         foreach ( $columns as $column => $charset ) {
    373             $this->assertEquals( false, self::$_wpdb->get_col_charset( $table, $column ) );
    374         }
    375 
    376         self::$_wpdb->query( $drop );
    377 
    378         self::$_wpdb->is_mysql = true;
    379     }
    380 
    381     /**
    382      * @ticket 21212
    383      */
    384     function data_strip_invalid_text_from_query() {
    385         $table_name = 'strip_invalid_text_from_query_table';
    386         $data = array(
    387             array(
    388                 // binary tables don't get stripped
    389                 "( a VARCHAR(50) CHARACTER SET utf8, b BINARY )", // create
    390                 "('foo\xf0\x9f\x98\x88bar', 'foo')",              // query
    391                 "('foo\xf0\x9f\x98\x88bar', 'foo')"               // expected result
    392             ),
    393             array(
    394                 // utf8/utf8mb4 tables default to utf8
    395                 "( a VARCHAR(50) CHARACTER SET utf8, b VARCHAR(50) CHARACTER SET utf8mb4 )",
    396                 "('foo\xf0\x9f\x98\x88bar', 'foo')",
    397                 "('foobar', 'foo')"
    398             ),
    399         );
    400 
    401         foreach( $data as &$value ) {
    402             $this_table_name = $table_name . '_' . rand_str( 5 );
    403 
    404             $value[0] = "CREATE TABLE $this_table_name {$value[0]}";
    405             $value[1] = "INSERT INTO $this_table_name VALUES {$value[1]}";
    406             $value[2] = "INSERT INTO $this_table_name VALUES {$value[2]}";
    407             $value[3] = "DROP TABLE IF EXISTS $this_table_name";
    408         }
    409         unset( $value );
    410 
    411         return $data;
    412     }
    413 
    414     /**
    415      * @dataProvider data_strip_invalid_text_from_query
    416      * @ticket 21212
    417      */
    418     function test_strip_invalid_text_from_query( $create, $query, $expected, $drop ) {
    419         self::$_wpdb->query( $drop );
    420 
    421         if ( ! self::$_wpdb->has_cap( 'utf8mb4' ) && preg_match( '/utf8mb[34]/i', $create ) ) {
    422             $this->markTestSkipped( "This version of MySQL doesn't support utf8mb4." );
    423             return;
    424         }
    425 
    426         self::$_wpdb->query( $create );
    427 
    428         $return = self::$_wpdb->strip_invalid_text_from_query( $query );
    429         $this->assertEquals( $expected, $return );
    430 
    431         self::$_wpdb->query( $drop );
    432     }
    433 
    434     /**
    435      * @ticket 21212
    436      */
    437     function test_invalid_characters_in_query() {
    438         global $wpdb;
    439         $this->assertFalse( $wpdb->query( "INSERT INTO {$wpdb->posts} (post_content) VALUES ('foo\xf0\x9f\x98\x88bar')" ) );
    440     }
    441 }
Note: See TracChangeset for help on using the changeset viewer.