xarxaprod-wp-theme/vendor/wp-cli/php-cli-tools/tests/test-cli.php

554 lines
26 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
use cli\Colors;
class testsCli extends PHPUnit_Framework_TestCase {
function setUp() {
// Reset enable state
\cli\Colors::enable( null );
// Empty the cache
\cli\Colors::clearStringCache();
}
function test_string_length() {
$this->assertEquals( \cli\Colors::length( 'x' ), 1 );
$this->assertEquals( \cli\Colors::length( '日' ), 1 );
}
function test_string_width() {
$this->assertEquals( \cli\Colors::width( 'x' ), 1 );
$this->assertEquals( \cli\Colors::width( '日' ), 2 ); // Double-width char.
}
function test_encoded_string_length() {
$this->assertEquals( \cli\Colors::length( 'hello' ), 5 );
$this->assertEquals( \cli\Colors::length( 'óra' ), 3 );
$this->assertEquals( \cli\Colors::length( '日本語' ), 3 );
}
function test_encoded_string_width() {
$this->assertEquals( \cli\Colors::width( 'hello' ), 5 );
$this->assertEquals( \cli\Colors::width( 'óra' ), 3 );
$this->assertEquals( \cli\Colors::width( '日本語' ), 6 ); // 3 double-width chars.
}
function test_encoded_string_pad() {
$this->assertEquals( 6, strlen( \cli\Colors::pad( 'hello', 6 ) ) );
$this->assertEquals( 7, strlen( \cli\Colors::pad( 'óra', 6 ) ) ); // special characters take one byte
$this->assertEquals( 9, strlen( \cli\Colors::pad( '日本語', 6 ) ) ); // each character takes two bytes
$this->assertEquals( 17, strlen( \cli\Colors::pad( 'עִבְרִית', 6 ) ) ); // process Hebrew vowels
$this->assertEquals( 6, strlen( \cli\Colors::pad( 'hello', 6, false, false, STR_PAD_RIGHT ) ) );
$this->assertEquals( 7, strlen( \cli\Colors::pad( 'óra', 6, false, false, STR_PAD_LEFT ) ) ); // special characters take one byte
$this->assertEquals( 9, strlen( \cli\Colors::pad( '日本語', 6, false, false, STR_PAD_BOTH ) ) ); // each character takes two bytes
$this->assertSame( 4, strpos( \cli\Colors::pad( 'hello', 10, false, false, STR_PAD_RIGHT ), 'o' ) );
$this->assertSame( 9, strpos( \cli\Colors::pad( 'hello', 10, false, false, STR_PAD_LEFT ), 'o' ) );
$this->assertSame( 6, strpos( \cli\Colors::pad( 'hello', 10, false, false, STR_PAD_BOTH ), 'o' ) );
$this->assertSame( 1, strpos( \cli\Colors::pad( 'hello', 10, false, false, STR_PAD_RIGHT ), 'e' ) );
$this->assertSame( 6, strpos( \cli\Colors::pad( 'hello', 10, false, false, STR_PAD_LEFT ), 'e' ) );
$this->assertSame( 3, strpos( \cli\Colors::pad( 'hello', 10, false, false, STR_PAD_BOTH ), 'e' ) );
}
function test_colorized_string_pad() {
// Colors enabled.
Colors::enable( true );
$x = Colors::colorize( '%Gx%n', true ); // colorized `x` string
$ora = Colors::colorize( "%Góra%n", true ); // colorized `óra` string
$this->assertSame( 22, strlen( Colors::pad( $x, 11 ) ) );
$this->assertSame( 22, strlen( Colors::pad( $x, 11, false /*pre_colorized*/ ) ) );
$this->assertSame( 22, strlen( Colors::pad( $x, 11, true /*pre_colorized*/ ) ) );
$this->assertSame( 23, strlen( Colors::pad( $ora, 11 ) ) ); // +1 for two-byte "ó".
$this->assertSame( 23, strlen( Colors::pad( $ora, 11, false /*pre_colorized*/ ) ) );
$this->assertSame( 23, strlen( Colors::pad( $ora, 11, true /*pre_colorized*/ ) ) );
// Colors disabled.
Colors::disable( true );
$this->assertFalse( Colors::shouldColorize() );
$this->assertSame( 20, strlen( Colors::pad( $x, 20 ) ) );
$this->assertSame( 20, strlen( Colors::pad( $x, 20, false /*pre_colorized*/ ) ) );
$this->assertSame( 31, strlen( Colors::pad( $x, 20, true /*pre_colorized*/ ) ) );
$this->assertSame( 21, strlen( Colors::pad( $ora, 20 ) ) ); // +1 for two-byte "ó".
$this->assertSame( 21, strlen( Colors::pad( $ora, 20, false /*pre_colorized*/ ) ) );
$this->assertSame( 32, strlen( Colors::pad( $ora, 20, true /*pre_colorized*/ ) ) );
}
function test_encoded_substr() {
$this->assertEquals( \cli\safe_substr( \cli\Colors::pad( 'hello', 6), 0, 2 ), 'he' );
$this->assertEquals( \cli\safe_substr( \cli\Colors::pad( 'óra', 6), 0, 2 ), 'ór' );
$this->assertEquals( \cli\safe_substr( \cli\Colors::pad( '日本語', 6), 0, 2 ), '日本' );
$this->assertSame( 'el', \cli\safe_substr( Colors::pad( 'hello', 6 ), 1, 2 ) );
$this->assertSame( 'a ', \cli\safe_substr( Colors::pad( 'óra', 6 ), 2, 2 ) );
$this->assertSame( ' ', \cli\safe_substr( Colors::pad( 'óra', 6 ), 5, 2 ) );
$this->assertSame( '本語', \cli\safe_substr( Colors::pad( '日本語', 8 ), 1, 2 ) );
$this->assertSame( '語 ', \cli\safe_substr( Colors::pad( '日本語', 8 ), 2, 2 ) );
$this->assertSame( ' ', \cli\safe_substr( Colors::pad( '日本語', 8 ), -1 ) );
$this->assertSame( ' ', \cli\safe_substr( Colors::pad( '日本語', 8 ), -1, 2 ) );
$this->assertSame( '語 ', \cli\safe_substr( Colors::pad( '日本語', 8 ), -3, 3 ) );
}
function test_various_substr() {
// Save.
$test_safe_substr = getenv( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR' );
if ( function_exists( 'mb_detect_order' ) ) {
$mb_detect_order = mb_detect_order();
}
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR' );
// Latin, kana, Latin, Latin combining, Thai combining, Hangul.
$str = 'lムnöม้p를'; // 18 bytes.
// Large string.
$large_str_str_start = 65536 * 2;
$large_str = str_repeat( 'a', $large_str_str_start ) . $str;
$large_str_len = strlen( $large_str ); // 128K + 18 bytes.
if ( \cli\can_use_icu() ) {
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR=1' ); // Tests grapheme_substr().
$this->assertSame( '', \cli\safe_substr( $str, 0, 0 ) );
$this->assertSame( 'l', \cli\safe_substr( $str, 0, 1 ) );
$this->assertSame( 'lム', \cli\safe_substr( $str, 0, 2 ) );
$this->assertSame( 'lムn', \cli\safe_substr( $str, 0, 3 ) );
$this->assertSame( 'lムnö', \cli\safe_substr( $str, 0, 4 ) );
$this->assertSame( 'lムnöม้', \cli\safe_substr( $str, 0, 5 ) );
$this->assertSame( 'lムnöม้p', \cli\safe_substr( $str, 0, 6 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, 0, 7 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, 0, 8 ) );
$this->assertSame( '', \cli\safe_substr( $str, 19 ) ); // Start too large.
$this->assertSame( '', \cli\safe_substr( $str, 19, 7 ) ); // Start too large, with length.
$this->assertSame( '', \cli\safe_substr( $str, 8 ) ); // Start same as length.
$this->assertSame( '', \cli\safe_substr( $str, 8, 0 ) ); // Start same as length, with zero length.
$this->assertSame( '를', \cli\safe_substr( $str, -1 ) );
$this->assertSame( 'p를', \cli\safe_substr( $str, -2 ) );
$this->assertSame( 'ม้p를', \cli\safe_substr( $str, -3 ) );
$this->assertSame( 'öม้p를', \cli\safe_substr( $str, -4 ) );
$this->assertSame( 'öม้p', \cli\safe_substr( $str, -4, 3 ) );
$this->assertSame( 'nö', \cli\safe_substr( $str, -5, 2 ) );
$this->assertSame( 'ム', \cli\safe_substr( $str, -6, 1 ) );
$this->assertSame( 'ムnöม้p를', \cli\safe_substr( $str, -6 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, -7 ) );
$this->assertSame( 'lムnö', \cli\safe_substr( $str, -7, 4 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, -8 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, -9 ) ); // Negative start too large.
$this->assertSame( $large_str, \cli\safe_substr( $large_str, 0 ) );
$this->assertSame( '', \cli\safe_substr( $large_str, $large_str_str_start, 0 ) );
$this->assertSame( 'l', \cli\safe_substr( $large_str, $large_str_str_start, 1 ) );
$this->assertSame( 'lム', \cli\safe_substr( $large_str, $large_str_str_start, 2 ) );
$this->assertSame( 'p를', \cli\safe_substr( $large_str, -2 ) );
}
if ( \cli\can_use_pcre_x() ) {
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR=2' ); // Tests preg_split( '/\X/u' ).
$this->assertSame( '', \cli\safe_substr( $str, 0, 0 ) );
$this->assertSame( 'l', \cli\safe_substr( $str, 0, 1 ) );
$this->assertSame( 'lム', \cli\safe_substr( $str, 0, 2 ) );
$this->assertSame( 'lムn', \cli\safe_substr( $str, 0, 3 ) );
$this->assertSame( 'lムnö', \cli\safe_substr( $str, 0, 4 ) );
$this->assertSame( 'lムnöม้', \cli\safe_substr( $str, 0, 5 ) );
$this->assertSame( 'lムnöม้p', \cli\safe_substr( $str, 0, 6 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, 0, 7 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, 0, 8 ) );
$this->assertSame( '', \cli\safe_substr( $str, 19 ) ); // Start too large.
$this->assertSame( '', \cli\safe_substr( $str, 19, 7 ) ); // Start too large, with length.
$this->assertSame( '', \cli\safe_substr( $str, 8 ) ); // Start same as length.
$this->assertSame( '', \cli\safe_substr( $str, 8, 0 ) ); // Start same as length, with zero length.
$this->assertSame( '를', \cli\safe_substr( $str, -1 ) );
$this->assertSame( 'p를', \cli\safe_substr( $str, -2 ) );
$this->assertSame( 'ม้p를', \cli\safe_substr( $str, -3 ) );
$this->assertSame( 'öม้p를', \cli\safe_substr( $str, -4 ) );
$this->assertSame( 'öม้p', \cli\safe_substr( $str, -4, 3 ) );
$this->assertSame( 'nö', \cli\safe_substr( $str, -5, 2 ) );
$this->assertSame( 'ム', \cli\safe_substr( $str, -6, 1 ) );
$this->assertSame( 'ムnöม้p를', \cli\safe_substr( $str, -6 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, -7 ) );
$this->assertSame( 'lムnö', \cli\safe_substr( $str, -7, 4 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, -8 ) );
$this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, -9 ) ); // Negative start too large.
$this->assertSame( $large_str, \cli\safe_substr( $large_str, 0 ) );
$this->assertSame( '', \cli\safe_substr( $large_str, $large_str_str_start, 0 ) );
$this->assertSame( 'l', \cli\safe_substr( $large_str, $large_str_str_start, 1 ) );
$this->assertSame( 'lム', \cli\safe_substr( $large_str, $large_str_str_start, 2 ) );
$this->assertSame( 'p를', \cli\safe_substr( $large_str, -2 ) );
}
if ( function_exists( 'mb_substr' ) ) {
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR=4' ); // Tests mb_substr().
$this->assertSame( '', \cli\safe_substr( $str, 0, 0 ) );
$this->assertSame( 'l', \cli\safe_substr( $str, 0, 1 ) );
$this->assertSame( 'lム', \cli\safe_substr( $str, 0, 2 ) );
$this->assertSame( 'lムn', \cli\safe_substr( $str, 0, 3 ) );
$this->assertSame( 'lムno', \cli\safe_substr( $str, 0, 4 ) ); // Wrong.
}
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR=8' ); // Tests substr().
$this->assertSame( '', \cli\safe_substr( $str, 0, 0 ) );
$this->assertSame( 'l', \cli\safe_substr( $str, 0, 1 ) );
$this->assertSame( "l\xe3", \cli\safe_substr( $str, 0, 2 ) ); // Corrupt.
$this->assertSame( '', \cli\safe_substr( $str, strlen( $str ) + 1 ) ); // Return '' not false to match behavior of other methods when `$start` > strlen.
// Non-UTF-8 - both grapheme_substr() and preg_split( '/\X/u' ) will fail.
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR' );
if ( function_exists( 'mb_substr' ) && function_exists( 'mb_detect_order' ) ) {
// Latin-1
mb_detect_order( array( 'UTF-8', 'ISO-8859-1' ) );
$str = "\xe0b\xe7"; // "àbç" in ISO-8859-1
$this->assertSame( "\xe0b", \cli\safe_substr( $str, 0, 2 ) );
$this->assertSame( "\xe0b", mb_substr( $str, 0, 2, 'ISO-8859-1' ) );
}
// Restore.
putenv( false == $test_safe_substr ? 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR' : "PHP_CLI_TOOLS_TEST_SAFE_SUBSTR=$test_safe_substr" );
if ( function_exists( 'mb_detect_order' ) ) {
mb_detect_order( $mb_detect_order );
}
}
function test_is_width_encoded_substr() {
$this->assertSame( 'he', \cli\safe_substr( Colors::pad( 'hello', 6 ), 0, 2, true /*is_width*/ ) );
$this->assertSame( 'ór', \cli\safe_substr( Colors::pad( 'óra', 6 ), 0, 2, true /*is_width*/ ) );
$this->assertSame( '日', \cli\safe_substr( Colors::pad( '日本語', 8 ), 0, 2, true /*is_width*/ ) );
$this->assertSame( '日', \cli\safe_substr( Colors::pad( '日本語', 8 ), 0, 3, true /*is_width*/ ) );
$this->assertSame( '日本', \cli\safe_substr( Colors::pad( '日本語', 8 ), 0, 4, true /*is_width*/ ) );
$this->assertSame( '日本語', \cli\safe_substr( Colors::pad( '日本語', 8 ), 0, 6, true /*is_width*/ ) );
$this->assertSame( '日本語 ', \cli\safe_substr( Colors::pad( '日本語', 8 ), 0, 7, true /*is_width*/ ) );
$this->assertSame( 'el', \cli\safe_substr( Colors::pad( 'hello', 6 ), 1, 2, true /*is_width*/ ) );
$this->assertSame( 'a ', \cli\safe_substr( Colors::pad( 'óra', 6 ), 2, 2, true /*is_width*/ ) );
$this->assertSame( ' ', \cli\safe_substr( Colors::pad( 'óra', 6 ), 5, 2, true /*is_width*/ ) );
$this->assertSame( '', \cli\safe_substr( '1日4本語90', 0, 0, true /*is_width*/ ) );
$this->assertSame( '1', \cli\safe_substr( '1日4本語90', 0, 1, true /*is_width*/ ) );
$this->assertSame( '1', \cli\safe_substr( '1日4本語90', 0, 2, true /*is_width*/ ) );
$this->assertSame( '1日', \cli\safe_substr( '1日4本語90', 0, 3, true /*is_width*/ ) );
$this->assertSame( '1日4', \cli\safe_substr( '1日4本語90', 0, 4, true /*is_width*/ ) );
$this->assertSame( '1日4', \cli\safe_substr( '1日4本語90', 0, 5, true /*is_width*/ ) );
$this->assertSame( '1日4本', \cli\safe_substr( '1日4本語90', 0, 6, true /*is_width*/ ) );
$this->assertSame( '1日4本', \cli\safe_substr( '1日4本語90', 0, 7, true /*is_width*/ ) );
$this->assertSame( '1日4本語', \cli\safe_substr( '1日4本語90', 0, 8, true /*is_width*/ ) );
$this->assertSame( '1日4本語9', \cli\safe_substr( '1日4本語90', 0, 9, true /*is_width*/ ) );
$this->assertSame( '1日4本語90', \cli\safe_substr( '1日4本語90', 0, 10, true /*is_width*/ ) );
$this->assertSame( '1日4本語90', \cli\safe_substr( '1日4本語90', 0, 11, true /*is_width*/ ) );
$this->assertSame( '日', \cli\safe_substr( '1日4本語90', 1, 2, true /*is_width*/ ) );
$this->assertSame( '日4', \cli\safe_substr( '1日4本語90', 1, 3, true /*is_width*/ ) );
$this->assertSame( '4本語9', \cli\safe_substr( '1日4本語90', 2, 6, true /*is_width*/ ) );
$this->assertSame( '本', \cli\safe_substr( '1日4本語90', 3, 1, true /*is_width*/ ) );
$this->assertSame( '本', \cli\safe_substr( '1日4本語90', 3, 2, true /*is_width*/ ) );
$this->assertSame( '本', \cli\safe_substr( '1日4本語90', 3, 3, true /*is_width*/ ) );
$this->assertSame( '本語', \cli\safe_substr( '1日4本語90', 3, 4, true /*is_width*/ ) );
$this->assertSame( '本語9', \cli\safe_substr( '1日4本語90', 3, 5, true /*is_width*/ ) );
$this->assertSame( '0', \cli\safe_substr( '1日4本語90', 6, 1, true /*is_width*/ ) );
$this->assertSame( '', \cli\safe_substr( '1日4本語90', 7, 1, true /*is_width*/ ) );
$this->assertSame( '', \cli\safe_substr( '1日4本語90', 6, 0, true /*is_width*/ ) );
$this->assertSame( '0', \cli\safe_substr( '1日4本語90', -1, 3, true /*is_width*/ ) );
$this->assertSame( '90', \cli\safe_substr( '1日4本語90', -2, 3, true /*is_width*/ ) );
$this->assertSame( '語9', \cli\safe_substr( '1日4本語90', -3, 3, true /*is_width*/ ) );
$this->assertSame( '本語9', \cli\safe_substr( '1日4本語90', -4, 5, true /*is_width*/ ) );
}
function test_colorized_string_length() {
$this->assertEquals( \cli\Colors::length( \cli\Colors::colorize( '%Gx%n', true ) ), 1 );
$this->assertEquals( \cli\Colors::length( \cli\Colors::colorize( '%G日%n', true ) ), 1 );
}
function test_colorized_string_width() {
// Colors enabled.
Colors::enable( true );
$x = Colors::colorize( '%Gx%n', true );
$dw = Colors::colorize( '%G日%n', true ); // Double-width char.
$this->assertSame( 1, Colors::width( $x ) );
$this->assertSame( 1, Colors::width( $x, false /*pre_colorized*/ ) );
$this->assertSame( 1, Colors::width( $x, true /*pre_colorized*/ ) );
$this->assertSame( 2, Colors::width( $dw ) );
$this->assertSame( 2, Colors::width( $dw, false /*pre_colorized*/ ) );
$this->assertSame( 2, Colors::width( $dw, true /*pre_colorized*/ ) );
// Colors disabled.
Colors::disable( true );
$this->assertFalse( Colors::shouldColorize() );
$this->assertSame( 12, Colors::width( $x ) );
$this->assertSame( 12, Colors::width( $x, false /*pre_colorized*/ ) );
$this->assertSame( 1, Colors::width( $x, true /*pre_colorized*/ ) );
$this->assertSame( 13, Colors::width( $dw ) );
$this->assertSame( 13, Colors::width( $dw, false /*pre_colorized*/ ) );
$this->assertSame( 2, Colors::width( $dw, true /*pre_colorized*/ ) );
}
function test_colorize_string_is_colored() {
$original = '%Gx';
$colorized = "\033[32;1mx";
$this->assertEquals( \cli\Colors::colorize( $original, true ), $colorized );
}
function test_colorize_when_colorize_is_forced() {
$original = '%gx%n';
$this->assertEquals( \cli\Colors::colorize( $original, false ), 'x' );
}
function test_binary_string_is_converted_back_to_original_string() {
$string = 'x';
$string_with_color = '%b' . $string;
$colorized_string = "\033[34m$string";
// Ensure colorization is applied correctly
$this->assertEquals( \cli\Colors::colorize( $string_with_color, true ), $colorized_string );
// Ensure that the colorization is reverted
$this->assertEquals( \cli\Colors::decolorize( $colorized_string ), $string );
}
function test_string_cache() {
$string = 'x';
$string_with_color = '%k' . $string;
$colorized_string = "\033[30m$string";
// Ensure colorization works
$this->assertEquals( \cli\Colors::colorize( $string_with_color, true ), $colorized_string );
// Test that the value was cached appropriately
$test_cache = array(
'passed' => $string_with_color,
'colorized' => $colorized_string,
'decolorized' => $string,
);
$real_cache = \cli\Colors::getStringCache();
// Test that the cache value exists
$this->assertTrue( isset( $real_cache[ md5( $string_with_color ) ] ) );
// Test that the cache value is correctly set
$this->assertEquals( $test_cache, $real_cache[ md5( $string_with_color ) ] );
}
function test_string_cache_colorize() {
$string = 'x';
$string_with_color = '%k' . $string;
$colorized_string = "\033[30m$string";
// Colors enabled.
Colors::enable( true );
// Ensure colorization works
$this->assertSame( $colorized_string, Colors::colorize( $string_with_color ) );
$this->assertSame( $colorized_string, Colors::colorize( $string_with_color ) );
// Colors disabled.
Colors::disable( true );
$this->assertFalse( Colors::shouldColorize() );
// Ensure it doesn't come from the cache.
$this->assertSame( $string, Colors::colorize( $string_with_color ) );
$this->assertSame( $string, Colors::colorize( $string_with_color ) );
// Check that escaped % isn't stripped on putting into cache.
$string = 'x%%n';
$string_with_color = '%k' . $string;
$this->assertSame( 'x%n', Colors::colorize( $string_with_color ) );
$this->assertSame( 'x%n', Colors::colorize( $string_with_color ) );
}
function test_decolorize() {
// Colors enabled.
Colors::enable( true );
$string = '%kx%%n%n';
$colorized_string = Colors::colorize( $string );
$both_string = '%gfoo' . $colorized_string . 'bar%%%n';
$this->assertSame( 'x%n', Colors::decolorize( $string ) );
$this->assertSame( 'x', Colors::decolorize( $colorized_string ) );
$this->assertSame( 'fooxbar%', Colors::decolorize( $both_string ) );
$this->assertSame( $string, Colors::decolorize( $string, 1 /*keep_tokens*/ ) );
$this->assertSame( 'x%n', Colors::decolorize( $colorized_string, 1 /*keep_tokens*/ ) );
$this->assertSame( '%gfoox%nbar%%%n', Colors::decolorize( $both_string, 1 /*keep_tokens*/ ) );
$this->assertSame( 'x%n', Colors::decolorize( $string, 2 /*keep_encodings*/ ) );
$this->assertSame( 'x', Colors::decolorize( $colorized_string, 2 /*keep_encodings*/ ) );
$this->assertSame( 'fooxbar%', Colors::decolorize( $both_string, 2 /*keep_encodings*/ ) );
$this->assertSame( $string, Colors::decolorize( $string, 3 /*noop*/ ) );
$this->assertSame( $colorized_string, Colors::decolorize( $colorized_string, 3 /*noop*/ ) );
$this->assertSame( $both_string, Colors::decolorize( $both_string, 3 /*noop*/ ) );
}
function test_strwidth() {
// Save.
$test_strwidth = getenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH' );
if ( function_exists( 'mb_detect_order' ) ) {
$mb_detect_order = mb_detect_order();
}
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH' );
// UTF-8.
// 4 characters, one a double-width Han = 5 spacing chars, with 2 combining chars. Adapted from http://unicode.org/faq/char_combmark.html#7 (combining acute accent added after "a").
$str = "a\xCC\x81\xE0\xA4\xA8\xE0\xA4\xBF\xE4\xBA\x9C\xF0\x90\x82\x83";
if ( \cli\can_use_icu() ) {
$this->assertSame( 5, \cli\strwidth( $str ) ); // Tests grapheme_strlen().
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH=2' ); // Test preg_split( '/\X/u' ).
$this->assertSame( 5, \cli\strwidth( $str ) );
} else {
$this->assertSame( 5, \cli\strwidth( $str ) ); // Tests preg_split( '/\X/u' ).
}
if ( function_exists( 'mb_strwidth' ) && function_exists( 'mb_detect_order' ) ) {
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH=4' ); // Test mb_strwidth().
mb_detect_order( array( 'UTF-8', 'ISO-8859-1' ) );
$this->assertSame( 5, \cli\strwidth( $str ) );
}
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH=8' ); // Test safe_strlen().
if ( \cli\can_use_icu() || \cli\can_use_pcre_x() ) {
$this->assertSame( 4, \cli\strwidth( $str ) ); // safe_strlen() (correctly) does not account for double-width Han so out by 1.
} elseif ( function_exists( 'mb_strlen' ) && function_exists( 'mb_detect_order' ) ) {
$this->assertSame( 4, \cli\strwidth( $str ) ); // safe_strlen() (correctly) does not account for double-width Han so out by 1.
$this->assertSame( 6, mb_strlen( $str, 'UTF-8' ) );
} else {
$this->assertSame( 16, \cli\strwidth( $str ) ); // strlen() - no. of bytes.
$this->assertSame( 16, strlen( $str ) );
}
// Nepali जस्ट ट॓स्ट गर्दै - 1st word: 3 spacing + 1 combining, 2nd word: 3 spacing + 2 combining, 3rd word: 3 spacing + 2 combining = 9 spacing chars + 2 spaces = 11 chars.
$str = "\xe0\xa4\x9c\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\x9f \xe0\xa4\x9f\xe0\xa5\x93\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\x9f \xe0\xa4\x97\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\xa6\xe0\xa5\x88";
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH' );
if ( \cli\can_use_icu() ) {
$this->assertSame( 11, \cli\strwidth( $str ) ); // Tests grapheme_strlen().
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH=2' ); // Test preg_split( '/\X/u' ).
$this->assertSame( 11, \cli\strwidth( $str ) );
} else {
$this->assertSame( 11, \cli\strwidth( $str ) ); // Tests preg_split( '/\X/u' ).
}
if ( function_exists( 'mb_strwidth' ) && function_exists( 'mb_detect_order' ) ) {
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH=4' ); // Test mb_strwidth().
mb_detect_order( array( 'UTF-8' ) );
$this->assertSame( 11, \cli\strwidth( $str ) );
}
// Non-UTF-8 - both grapheme_strlen() and preg_split( '/\X/u' ) will fail.
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH' );
if ( function_exists( 'mb_strwidth' ) && function_exists( 'mb_detect_order' ) ) {
// Latin-1
mb_detect_order( array( 'UTF-8', 'ISO-8859-1' ) );
$str = "\xe0b\xe7"; // "àbç" in ISO-8859-1
$this->assertSame( 3, \cli\strwidth( $str ) ); // Test mb_strwidth().
$this->assertSame( 3, mb_strwidth( $str, 'ISO-8859-1' ) );
// Shift JIS.
mb_detect_order( array( 'UTF-8', 'SJIS' ) );
$str = "\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd\x90\xa2\x8a\x45!"; // "こャにちは世界!" ("Hello world!") in Shift JIS - 7 double-width chars plus Latin exclamation mark.
$this->assertSame( 15, \cli\strwidth( $str ) ); // Test mb_strwidth().
$this->assertSame( 15, mb_strwidth( $str, 'SJIS' ) );
putenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH=8' ); // Test safe_strlen().
if ( function_exists( 'mb_strlen' ) && function_exists( 'mb_detect_order' ) ) {
$this->assertSame( 8, \cli\strwidth( $str ) ); // mb_strlen() - doesn't allow for double-width.
$this->assertSame( 8, mb_strlen( $str, 'SJIS' ) );
} else {
$this->assertSame( 15, \cli\strwidth( $str ) ); // strlen() - no. of bytes.
$this->assertSame( 15, strlen( $str ) );
}
}
// Restore.
putenv( false == $test_strwidth ? 'PHP_CLI_TOOLS_TEST_STRWIDTH' : "PHP_CLI_TOOLS_TEST_STRWIDTH=$test_strwidth" );
if ( function_exists( 'mb_detect_order' ) ) {
mb_detect_order( $mb_detect_order );
}
}
function test_safe_strlen() {
// Save.
$test_safe_strlen = getenv( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN' );
if ( function_exists( 'mb_detect_order' ) ) {
$mb_detect_order = mb_detect_order();
}
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN' );
// UTF-8.
// ASCII l, 3-byte kana, ASCII n, ASCII o + 2-byte combining umlaut, 6-byte Thai combining, ASCII, 3-byte Hangul. grapheme length 7, bytes 18.
$str = 'lムnöม้p를';
if ( \cli\can_use_icu() ) {
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN' ); // Test grapheme_strlen().
$this->assertSame( 7, \cli\safe_strlen( $str ) );
if ( \cli\can_use_pcre_x() ) {
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN=2' ); // Test preg_split( '/\X/u' ).
$this->assertSame( 7, \cli\safe_strlen( $str ) );
}
} elseif ( \cli\can_use_pcre_x() ) {
$this->assertSame( 7, \cli\safe_strlen( $str ) ); // Tests preg_split( '/\X/u' ).
} else {
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN=8' ); // Test strlen().
$this->assertSame( 18, \cli\safe_strlen( $str ) ); // strlen() - no. of bytes.
$this->assertSame( 18, strlen( $str ) );
}
if ( function_exists( 'mb_strlen' ) && function_exists( 'mb_detect_order' ) ) {
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN=4' ); // Test mb_strlen().
mb_detect_order( array( 'UTF-8', 'ISO-8859-1' ) );
$this->assertSame( 7, \cli\safe_strlen( $str ) );
$this->assertSame( 9, mb_strlen( $str, 'UTF-8' ) ); // mb_strlen() - counts the 2 combining chars.
}
// Non-UTF-8 - both grapheme_strlen() and preg_split( '/\X/u' ) will fail.
putenv( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN' );
if ( function_exists( 'mb_strlen' ) && function_exists( 'mb_detect_order' ) ) {
// Latin-1
mb_detect_order( array( 'UTF-8', 'ISO-8859-1' ) );
$str = "\xe0b\xe7"; // "àbç" in ISO-8859-1
$this->assertSame( 3, \cli\safe_strlen( $str ) ); // Test mb_strlen().
$this->assertSame( 3, mb_strlen( $str, 'ISO-8859-1' ) );
}
// Restore.
putenv( false == $test_safe_strlen ? 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN' : "PHP_CLI_TOOLS_TEST_SAFE_STRLEN=$test_safe_strlen" );
if ( function_exists( 'mb_detect_order' ) ) {
mb_detect_order( $mb_detect_order );
}
}
}