@@ -111,7 +111,12 @@ function test_various_substr() {
111111 putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR ' );
112112
113113 // Latin, kana, Latin, Latin combining, Thai combining, Hangul.
114- $ str = 'lムnöม้p를 ' ;
114+ $ str = 'lムnöม้p를 ' ; // 18 bytes.
115+
116+ // Large string.
117+ $ large_str_str_start = 65536 * 2 ;
118+ $ large_str = str_repeat ( 'a ' , $ large_str_str_start ) . $ str ;
119+ $ large_str_len = strlen ( $ large_str ); // 128K + 18 bytes.
115120
116121 if ( \cli \can_use_icu () ) {
117122 putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR=1 ' ); // Tests grapheme_substr().
@@ -124,6 +129,10 @@ function test_various_substr() {
124129 $ this ->assertSame ( 'lムnöม้p ' , \cli \safe_substr ( $ str , 0 , 6 ) );
125130 $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , 0 , 7 ) );
126131 $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , 0 , 8 ) );
132+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 19 ) ); // Start too large.
133+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 19 , 7 ) ); // Start too large, with length.
134+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 8 ) ); // Start same as length.
135+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 8 , 0 ) ); // Start same as length, with zero length.
127136 $ this ->assertSame ( '를 ' , \cli \safe_substr ( $ str , -1 ) );
128137 $ this ->assertSame ( 'p를 ' , \cli \safe_substr ( $ str , -2 ) );
129138 $ this ->assertSame ( 'ม้p를 ' , \cli \safe_substr ( $ str , -3 ) );
@@ -134,11 +143,18 @@ function test_various_substr() {
134143 $ this ->assertSame ( 'ムnöม้p를 ' , \cli \safe_substr ( $ str , -6 ) );
135144 $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , -7 ) );
136145 $ this ->assertSame ( 'lムnö ' , \cli \safe_substr ( $ str , -7 , 4 ) );
137- // $this->assertSame( 'lムnöม้p를', \cli\safe_substr( $str, -8 ) ); // grapheme_substr() returns false on this.
146+ $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , -8 ) );
147+ $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , -9 ) ); // Negative start too large.
148+
149+ $ this ->assertSame ( $ large_str , \cli \safe_substr ( $ large_str , 0 ) );
150+ $ this ->assertSame ( '' , \cli \safe_substr ( $ large_str , $ large_str_str_start , 0 ) );
151+ $ this ->assertSame ( 'l ' , \cli \safe_substr ( $ large_str , $ large_str_str_start , 1 ) );
152+ $ this ->assertSame ( 'lム ' , \cli \safe_substr ( $ large_str , $ large_str_str_start , 2 ) );
153+ $ this ->assertSame ( 'p를 ' , \cli \safe_substr ( $ large_str , -2 ) );
138154 }
139155
140156 if ( \cli \can_use_pcre_x () ) {
141- putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR=2 ' ); // Tests preg_match ( '/\X/u' ).
157+ putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR=2 ' ); // Tests preg_split ( '/\X/u' ).
142158 $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 0 , 0 ) );
143159 $ this ->assertSame ( 'l ' , \cli \safe_substr ( $ str , 0 , 1 ) );
144160 $ this ->assertSame ( 'lム ' , \cli \safe_substr ( $ str , 0 , 2 ) );
@@ -148,6 +164,10 @@ function test_various_substr() {
148164 $ this ->assertSame ( 'lムnöม้p ' , \cli \safe_substr ( $ str , 0 , 6 ) );
149165 $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , 0 , 7 ) );
150166 $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , 0 , 8 ) );
167+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 19 ) ); // Start too large.
168+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 19 , 7 ) ); // Start too large, with length.
169+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 8 ) ); // Start same as length.
170+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 8 , 0 ) ); // Start same as length, with zero length.
151171 $ this ->assertSame ( '를 ' , \cli \safe_substr ( $ str , -1 ) );
152172 $ this ->assertSame ( 'p를 ' , \cli \safe_substr ( $ str , -2 ) );
153173 $ this ->assertSame ( 'ม้p를 ' , \cli \safe_substr ( $ str , -3 ) );
@@ -159,6 +179,13 @@ function test_various_substr() {
159179 $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , -7 ) );
160180 $ this ->assertSame ( 'lムnö ' , \cli \safe_substr ( $ str , -7 , 4 ) );
161181 $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , -8 ) );
182+ $ this ->assertSame ( 'lムnöม้p를 ' , \cli \safe_substr ( $ str , -9 ) ); // Negative start too large.
183+
184+ $ this ->assertSame ( $ large_str , \cli \safe_substr ( $ large_str , 0 ) );
185+ $ this ->assertSame ( '' , \cli \safe_substr ( $ large_str , $ large_str_str_start , 0 ) );
186+ $ this ->assertSame ( 'l ' , \cli \safe_substr ( $ large_str , $ large_str_str_start , 1 ) );
187+ $ this ->assertSame ( 'lム ' , \cli \safe_substr ( $ large_str , $ large_str_str_start , 2 ) );
188+ $ this ->assertSame ( 'p를 ' , \cli \safe_substr ( $ large_str , -2 ) );
162189 }
163190
164191 if ( function_exists ( 'mb_substr ' ) ) {
@@ -174,8 +201,9 @@ function test_various_substr() {
174201 $ this ->assertSame ( '' , \cli \safe_substr ( $ str , 0 , 0 ) );
175202 $ this ->assertSame ( 'l ' , \cli \safe_substr ( $ str , 0 , 1 ) );
176203 $ this ->assertSame ( "l \xe3" , \cli \safe_substr ( $ str , 0 , 2 ) ); // Corrupt.
204+ $ this ->assertSame ( '' , \cli \safe_substr ( $ str , strlen ( $ str ) + 1 ) ); // Return '' not false to match behavior of other methods when `$start` > strlen.
177205
178- // Non-UTF-8 - both grapheme_substr() and preg_match ( '/\X/u' ) will fail.
206+ // Non-UTF-8 - both grapheme_substr() and preg_split ( '/\X/u' ) will fail.
179207
180208 putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_SUBSTR ' );
181209
@@ -392,10 +420,10 @@ function test_strwidth() {
392420
393421 if ( \cli \can_use_icu () ) {
394422 $ this ->assertSame ( 5 , \cli \strwidth ( $ str ) ); // Tests grapheme_strlen().
395- putenv ( 'PHP_CLI_TOOLS_TEST_STRWIDTH=2 ' ); // Test preg_match_all ( '/\X/u' ).
423+ putenv ( 'PHP_CLI_TOOLS_TEST_STRWIDTH=2 ' ); // Test preg_split ( '/\X/u' ).
396424 $ this ->assertSame ( 5 , \cli \strwidth ( $ str ) );
397425 } else {
398- $ this ->assertSame ( 5 , \cli \strwidth ( $ str ) ); // Tests preg_match_all ( '/\X/u' ).
426+ $ this ->assertSame ( 5 , \cli \strwidth ( $ str ) ); // Tests preg_split ( '/\X/u' ).
399427 }
400428
401429 if ( function_exists ( 'mb_strwidth ' ) && function_exists ( 'mb_detect_order ' ) ) {
@@ -422,10 +450,10 @@ function test_strwidth() {
422450
423451 if ( \cli \can_use_icu () ) {
424452 $ this ->assertSame ( 11 , \cli \strwidth ( $ str ) ); // Tests grapheme_strlen().
425- putenv ( 'PHP_CLI_TOOLS_TEST_STRWIDTH=2 ' ); // Test preg_match_all ( '/\X/u' ).
453+ putenv ( 'PHP_CLI_TOOLS_TEST_STRWIDTH=2 ' ); // Test preg_split ( '/\X/u' ).
426454 $ this ->assertSame ( 11 , \cli \strwidth ( $ str ) );
427455 } else {
428- $ this ->assertSame ( 11 , \cli \strwidth ( $ str ) ); // Tests preg_match_all ( '/\X/u' ).
456+ $ this ->assertSame ( 11 , \cli \strwidth ( $ str ) ); // Tests preg_split ( '/\X/u' ).
429457 }
430458
431459 if ( function_exists ( 'mb_strwidth ' ) && function_exists ( 'mb_detect_order ' ) ) {
@@ -434,7 +462,7 @@ function test_strwidth() {
434462 $ this ->assertSame ( 11 , \cli \strwidth ( $ str ) );
435463 }
436464
437- // Non-UTF-8 - both grapheme_strlen() and preg_match_all ( '/\X/u' ) will fail.
465+ // Non-UTF-8 - both grapheme_strlen() and preg_split ( '/\X/u' ) will fail.
438466
439467 putenv ( 'PHP_CLI_TOOLS_TEST_STRWIDTH ' );
440468
@@ -486,11 +514,11 @@ function test_safe_strlen() {
486514 putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN ' ); // Test grapheme_strlen().
487515 $ this ->assertSame ( 7 , \cli \safe_strlen ( $ str ) );
488516 if ( \cli \can_use_pcre_x () ) {
489- putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN=2 ' ); // Test preg_match_all ( '/\X/u' ).
517+ putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN=2 ' ); // Test preg_split ( '/\X/u' ).
490518 $ this ->assertSame ( 7 , \cli \safe_strlen ( $ str ) );
491519 }
492520 } elseif ( \cli \can_use_pcre_x () ) {
493- $ this ->assertSame ( 7 , \cli \safe_strlen ( $ str ) ); // Tests preg_match_all ( '/\X/u' ).
521+ $ this ->assertSame ( 7 , \cli \safe_strlen ( $ str ) ); // Tests preg_split ( '/\X/u' ).
494522 } else {
495523 putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN=8 ' ); // Test strlen().
496524 $ this ->assertSame ( 18 , \cli \safe_strlen ( $ str ) ); // strlen() - no. of bytes.
@@ -504,7 +532,7 @@ function test_safe_strlen() {
504532 $ this ->assertSame ( 9 , mb_strlen ( $ str , 'UTF-8 ' ) ); // mb_strlen() - counts the 2 combining chars.
505533 }
506534
507- // Non-UTF-8 - both grapheme_strlen() and preg_match_all ( '/\X/u' ) will fail.
535+ // Non-UTF-8 - both grapheme_strlen() and preg_split ( '/\X/u' ) will fail.
508536
509537 putenv ( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN ' );
510538
0 commit comments