[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

/tests/tests/format/ -> FormatTest.php (source)

   1  <?php
   2  
   3  /**
   4   * General formatting functions.
   5   */
   6  #[\PHPUnit\Framework\Attributes\Group('formatting')]
   7  class FormatTest extends PHPUnit\Framework\TestCase {
   8  
   9      /**
  10       * Data to serialize
  11       */
  12      static function serialize_data(): \Iterator
  13      {
  14          yield array( null );
  15          yield array( true );
  16          yield array( false );
  17          yield array( -25 );
  18          yield array( 25 );
  19          yield array( 1.1 );
  20          yield array( 'this string will be serialized' );
  21          yield array( "a\nb" );
  22          yield array( array() );
  23          yield array( array(1,1,2,3,5,8,13) );
  24          yield array( (object)array('test' => true, '3', 4) );
  25      }
  26  
  27      /**
  28       * Unserialized data
  29       */
  30      static function not_serialized_data(): \Iterator
  31      {
  32          yield array( 'a string' );
  33          yield array( ['array', 'yarra'] );
  34          yield array( 'garbage:a:0:garbage;' );
  35          // array( 'b:4;' ), // this test fails in WP test suite, not sure if intentional or what...
  36          yield array( 's:4:test;' );
  37      }
  38  
  39      /**
  40       * Check that yourls_is_serialized detects serialized data
  41       */
  42      #[\PHPUnit\Framework\Attributes\DataProvider('serialize_data')]
  43      public function test_is_serialized( $data ) {
  44          $this->assertTrue( yourls_is_serialized( serialize( $data ) ) );
  45      }
  46  
  47      /**
  48       * Check that yourls_is_serialized doesn't assume garbage is serialized
  49       */
  50      #[\PHPUnit\Framework\Attributes\DataProvider('not_serialized_data')]
  51      public function test_is_not_serialized( $data ) {
  52          $this->assertFalse( yourls_is_serialized( $data ) );
  53      }
  54  
  55      /**
  56       * yourls_maybe_unserialize() unserializes serialized data, and leaves the rest untouched
  57       */
  58      #[\PHPUnit\Framework\Attributes\DataProvider('serialize_data')]
  59      public function test_maybe_unserialize_serialized( $data ) {
  60          $this->assertEquals( $data, yourls_maybe_unserialize( serialize( $data ) ) );
  61      }
  62  
  63      /**
  64       * yourls_maybe_unserialize() returns non-serialized input as-is
  65       */
  66      #[\PHPUnit\Framework\Attributes\DataProvider('not_serialized_data')]
  67      public function test_maybe_unserialize_passthrough($data) {
  68          $this->assertSame( $data, yourls_maybe_unserialize( $data ) );
  69      }
  70  
  71      /**
  72       * Charsets used by yourls_rnd_string(). Structure: [type, expected character pool]
  73       */
  74      static function rnd_string_types(): \Iterator {
  75          yield 'type 1' => [ '1', '23456789bcdfghjkmnpqrstvwxyz' ];
  76          yield 'type 2' => [ '2', '23456789bcdfghjkmnpqrstvwxyzBCDFGHJKMNPQRSTVWXYZ' ];
  77          yield 'type 3' => [ '3', 'abcdefghijklmnopqrstuvwxyz' ];
  78          yield 'type 4' => [ '4', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ];
  79          yield 'type 5' => [ '5', '0123456789abcdefghijklmnopqrstuvwxyz' ];
  80          yield 'type 6' => [ '6', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ];
  81      }
  82  
  83      /**
  84       * yourls_rnd_string() honors the requested length and only uses characters from
  85       * the pool matching the requested type
  86       */
  87      #[\PHPUnit\Framework\Attributes\DataProvider('rnd_string_types')]
  88      public function test_rnd_string_types( $type, $pool ) {
  89          $str = yourls_rnd_string( 8, $type );
  90  
  91          $this->assertSame( 8, strlen( $str ) );
  92          // Every character belongs to the expected pool
  93          $this->assertSame( '', preg_replace( '/[' . preg_quote( $pool, '/' ) . ']/', '', $str ) );
  94      }
  95  
  96      /**
  97       * type 0 with a custom char list uses only that list
  98       *
  99       * Note: the result is str_shuffle()+substr(), so its length is capped at the
 100       * size of the pool ; we use a pool larger than the requested length.
 101       */
 102      public function test_rnd_string_custom_charlist() {
 103          $str = yourls_rnd_string( 6, '0', 'ABCDEFGHIJ' );
 104          $this->assertSame( 6, strlen( $str ) );
 105          $this->assertSame( '', preg_replace( '/[ABCDEFGHIJ]/', '', $str ) );
 106      }
 107  
 108      /**
 109       * Short URL charsets for the int<->string
 110       *
 111       *  - null    : the charset currently in effect (driven by YOURLS_URL_CONVERT)
 112       *  - base 36 : '0-9a-z'    (YOURLS_URL_CONVERT = 36, or anything but 62/64)
 113       *  - base 62 : '0-9a-zA-Z' (YOURLS_URL_CONVERT = 62 or 64)
 114       */
 115      static function conversion_charsets(): \Iterator {
 116          yield 'default (YOURLS_URL_CONVERT)' => array( null );
 117          yield 'base 36' => array( '0123456789abcdefghijklmnopqrstuvwxyz' );
 118          yield 'base 62' => array( '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' );
 119      }
 120  
 121      /**
 122       * Random string using only characters from $chars
 123       */
 124      private function rand_str_from( string $chars, int $len ): string {
 125          $max = strlen( $chars ) - 1;
 126          $string = '';
 127          for( $i = 0; $i < $len; $i++ ) {
 128              $string .= $chars[ mt_rand( 0, $max ) ];
 129          }
 130          // Drop leading zeros (int2string never emits them); never return empty
 131          return ltrim( $string, '0' ) ?: $chars[1];
 132      }
 133  
 134      /**
 135       * Integer (1337) to string (3jk) to integer
 136       */
 137      #[\PHPUnit\Framework\Attributes\DataProvider('conversion_charsets')]
 138      public function test_int_to_string_to_int( $chars ) {
 139          // 10 random integers
 140          for( $i=0; $i<10; $i++ ) {
 141              $integer = mt_rand( 1, 1000000 );
 142              $this->assertEquals( $integer, yourls_string2int( yourls_int2string( $integer, $chars ), $chars ) );
 143          }
 144      }
 145  
 146      /**
 147       * String (3jk) to integer (1337) to string
 148       */
 149      #[\PHPUnit\Framework\Attributes\DataProvider('conversion_charsets')]
 150      public function test_string_to_int_to_string( $chars ) {
 151          // Generate random strings from the charset actually in use
 152          $charset = $chars ?? yourls_get_shorturl_charset();
 153  
 154          for( $i=0; $i<10; $i++ ) {
 155              $string = $this->rand_str_from( $charset, mt_rand( 2, 10 ) );
 156              $this->assertEquals( $string, yourls_int2string( yourls_string2int( $string, $chars ), $chars ) );
 157          }
 158      }
 159  
 160      /**
 161       * Checking that yourls_unique_element_id is a unique string
 162       *
 163       */
 164      public function test_string2htmlid() {
 165          $id1 = yourls_unique_element_id();
 166          $id2 = yourls_unique_element_id();
 167          $id3 = yourls_unique_element_id('foo', 10);
 168          $id4 = yourls_unique_element_id();
 169          $this->assertIsString($id1);
 170          $this->assertIsString($id2);
 171          $this->assertNotSame($id1, $id2);
 172          $this->assertEquals('foo10', $id3, 'ID is built using the specified prefix and counter value.');
 173          $this->assertStringEndsWith('11', $id4, 'ID counter continues to increment from the last value.');
 174      }
 175  
 176      /**
 177       * Generating valid regexp from the allowed charset
 178       */
 179      function test_valid_regexp() {
 180          $pattern = yourls_make_regexp_pattern( yourls_get_shorturl_charset() );
 181  
 182          /* To validate a RegExp just run it against an empty string.
 183             If it returns explicit false (=== false), it's broken. Otherwise it's valid.
 184             From: https://stackoverflow.com/a/12941133/36850
 185             Cool to know :)
 186  
 187             We're testing it as used in yourls_sanitize_keyword()
 188             TODO: more random char strings to test?
 189          */
 190  
 191          $this->assertNotFalse( preg_match( '![^' . $pattern . ']!', '' ) );
 192      }
 193  
 194      /**
 195       * Trim long strings
 196       */
 197      function test_trim_long_strings() {
 198          $long = "The Plague That Makes Your Booty Move... It's The Infectious Grooves";
 199  
 200          $trim = "The Plague That Makes Your Booty Move... It's The Infec[...]";
 201          $this->assertSame( $trim, yourls_trim_long_string( $long ) );
 202  
 203          $trim = "The Plague That Makes Your Booty[...]";
 204          $this->assertSame( $trim, yourls_trim_long_string( $long, 37 ) );
 205  
 206          $trim = "The Plague That Makes Your Booty Mo..";
 207          $this->assertSame( $trim, yourls_trim_long_string( $long, 37, '..' ) );
 208      }
 209  
 210      /**
 211       * Return true for UTF8 strings
 212       *
 213       * Note: As of 1.7.1, function yourls_seem_utf8() is still unused. In 2.0 consider simply deleting it if still not needed
 214       */
 215      #[\PHPUnit\Framework\Attributes\DataProvider('valid_utf8')]
 216      function test_is_utf8( $string ) {
 217          $this->assertTrue( yourls_seems_utf8( $string ) );
 218      }
 219  
 220      /**
 221       * Return false for non UTF8 strings
 222       *
 223       * Note: As of 1.7.1, function yourls_seem_utf8() is still unused. In 2.0 consider simply deleting it if still not needed
 224       */
 225      #[\PHPUnit\Framework\Attributes\DataProvider('invalid_utf8')]
 226      function test_is_not_utf8( $string ) {
 227          $this->assertFalse( yourls_seems_utf8( $string ) );
 228      }
 229  
 230      static function valid_utf8() {
 231          return self::get_data( YOURLS_TESTDATA_DIR . '/formatting/utf-8.txt' );
 232      }
 233  
 234      static function invalid_utf8() {
 235          return self::get_data( YOURLS_TESTDATA_DIR . '/formatting/big5.txt' );
 236      }
 237  
 238      /**
 239       * Parse a file and return its content as a data provider
 240       */
 241      static function get_data( $filename ) {
 242          $strings = file( $filename );
 243          foreach ( $strings as &$string ) {
 244              $string = (array) trim( $string );
 245          }
 246          unset( $string );
 247          return $strings;
 248      }
 249  
 250      /**
 251       * Test yourls_backslashit
 252       */
 253      function test_backslashit() {
 254          $this->assertSame( '\h\e\l\l\o \w\o\r\l\d 123 !', yourls_backslashit( 'hello world 123 !' ) );
 255          $this->assertSame( '\\\1, 2, 3', yourls_backslashit( '1, 2, 3' ) );
 256      }
 257  
 258      /**
 259       * Test the bookmarklet generator
 260       *
 261       * Note: we're not testing that the bookmarklet generator produces valid JS code: the
 262       * bookmarklet class has tests for this, see https://github.com/ozh/bookmarkletgen
 263       * We're just testing that content is returned
 264       */
 265      function test_bookmarklet() {
 266          $code = yourls_make_bookmarklet( 'hello' );
 267          $this->assertTrue( is_string( $code ) );
 268      }
 269  
 270      /**
 271       * Test yourls_specialchars basics
 272       */
 273      function test_specialchars_decode_basics() {
 274          $html =  "&amp;&lt;hello world&gt;";
 275          $this->assertEquals( $html, yourls_specialchars( $html ) );
 276  
 277          $double = "&amp;amp;&amp;lt;hello world&amp;gt;";
 278          $this->assertEquals( $double, yourls_specialchars( $html, ENT_NOQUOTES, true ) );
 279      }
 280  
 281      /**
 282       * Test yourls_specialchars escape quotes
 283       */
 284      function test_specialchars_escapes_quotes() {
 285          $source = "\"'hello!'\"";
 286          $this->assertEquals( '"&#039;hello!&#039;"', yourls_specialchars( $source, 'single' ) );
 287          $this->assertEquals( "&quot;'hello!'&quot;", yourls_specialchars( $source, 'double' ) );
 288          $this->assertEquals( '&quot;&#039;hello!&#039;&quot;', yourls_specialchars( $source, ENT_QUOTES, true ) );
 289          $this->assertEquals( '&quot;&#039;hello!&#039;&quot;', yourls_specialchars( $source, 'omg', true ) ); // unaccepted value should be treated as ENT_QUOTES
 290          $this->assertEquals( $source, yourls_specialchars( $source ) );
 291      }
 292  
 293      /**
 294       * Test yourls_specialchars doesn't change allowed entities
 295       */
 296      function test_specialchars_allowed_entities() {
 297          foreach ( yourls_kses_allowed_entities() as $ent ) {
 298              $ent = '&' . $ent . ';';
 299              $this->assertEquals( $ent, yourls_specialchars( $ent ) );
 300          }
 301      }
 302  
 303      /**
 304       * Test yourls_specialchars with unallowed entities
 305       */
 306      function test_specialchars_unallowed_entities() {
 307          $ents = array( 'iacut', 'aposs', 'pos', 'apo', 'apo?', 'apo.*', '.*apo.*', 'apos ', ' apos', ' apos ' );
 308  
 309          foreach ( $ents as $ent ) {
 310              $escaped = '&amp;' . $ent . ';';
 311              $ent = '&' . $ent . ';';
 312              $this->assertEquals( $escaped, yourls_specialchars( $ent ) );
 313          }
 314      }
 315  
 316  }


Generated: Sat Jul 11 05:10:54 2026 Cross-referenced by PHPXref 0.7.1