MediaWiki  REL1_23
FormatJsonTest.php
Go to the documentation of this file.
00001 <?php
00002 
00006 class FormatJsonTest extends MediaWikiTestCase {
00007 
00008     public static function provideEncoderPrettyPrinting() {
00009         return array(
00010             // Four spaces
00011             array( true, '    ' ),
00012             array( '    ', '    ' ),
00013             // Two spaces
00014             array( '  ', '  ' ),
00015             // One tab
00016             array( "\t", "\t" ),
00017         );
00018     }
00019 
00023     public function testEncoderPrettyPrinting( $pretty, $expectedIndent ) {
00024         $obj = array(
00025             'emptyObject' => new stdClass,
00026             'emptyArray' => array(),
00027             'string' => 'foobar\\',
00028             'filledArray' => array(
00029                 array(
00030                     123,
00031                     456,
00032                 ),
00033                 // Nested json works without problems
00034                 '"7":["8",{"9":"10"}]',
00035                 // Whitespace clean up doesn't touch strings that look alike
00036                 "{\n\t\"emptyObject\": {\n\t},\n\t\"emptyArray\": [ ]\n}",
00037             ),
00038         );
00039 
00040         // No trailing whitespace, no trailing linefeed
00041         $json = '{
00042     "emptyObject": {},
00043     "emptyArray": [],
00044     "string": "foobar\\\\",
00045     "filledArray": [
00046         [
00047             123,
00048             456
00049         ],
00050         "\"7\":[\"8\",{\"9\":\"10\"}]",
00051         "{\n\t\"emptyObject\": {\n\t},\n\t\"emptyArray\": [ ]\n}"
00052     ]
00053 }';
00054 
00055         $json = str_replace( "\r", '', $json ); // Windows compat
00056         $json = str_replace( "\t", $expectedIndent, $json );
00057         $this->assertSame( $json, FormatJson::encode( $obj, $pretty ) );
00058     }
00059 
00060     public static function provideEncodeDefault() {
00061         return self::getEncodeTestCases( array() );
00062     }
00063 
00067     public function testEncodeDefault( $from, $to ) {
00068         $this->assertSame( $to, FormatJson::encode( $from ) );
00069     }
00070 
00071     public static function provideEncodeUtf8() {
00072         return self::getEncodeTestCases( array( 'unicode' ) );
00073     }
00074 
00078     public function testEncodeUtf8( $from, $to ) {
00079         $this->assertSame( $to, FormatJson::encode( $from, false, FormatJson::UTF8_OK ) );
00080     }
00081 
00082     public static function provideEncodeXmlMeta() {
00083         return self::getEncodeTestCases( array( 'xmlmeta' ) );
00084     }
00085 
00089     public function testEncodeXmlMeta( $from, $to ) {
00090         $this->assertSame( $to, FormatJson::encode( $from, false, FormatJson::XMLMETA_OK ) );
00091     }
00092 
00093     public static function provideEncodeAllOk() {
00094         return self::getEncodeTestCases( array( 'unicode', 'xmlmeta' ) );
00095     }
00096 
00100     public function testEncodeAllOk( $from, $to ) {
00101         $this->assertSame( $to, FormatJson::encode( $from, false, FormatJson::ALL_OK ) );
00102     }
00103 
00104     public function testEncodePhpBug46944() {
00105         $this->assertNotEquals(
00106             '\ud840\udc00',
00107             strtolower( FormatJson::encode( "\xf0\xa0\x80\x80" ) ),
00108             'Test encoding an broken json_encode character (U+20000)'
00109         );
00110     }
00111 
00112     public function testDecodeReturnType() {
00113         $this->assertInternalType(
00114             'object',
00115             FormatJson::decode( '{"Name": "Cheeso", "Rank": 7}' ),
00116             'Default to object'
00117         );
00118 
00119         $this->assertInternalType(
00120             'array',
00121             FormatJson::decode( '{"Name": "Cheeso", "Rank": 7}', true ),
00122             'Optional array'
00123         );
00124     }
00125 
00132     private static function getEncodeTestCases( array $unescapedGroups ) {
00133         $groups = array(
00134             'always' => array(
00135                 // Forward slash (always unescaped)
00136                 '/' => '/',
00137 
00138                 // Control characters
00139                 "\0" => '\u0000',
00140                 "\x08" => '\b',
00141                 "\t" => '\t',
00142                 "\n" => '\n',
00143                 "\r" => '\r',
00144                 "\f" => '\f',
00145                 "\x1f" => '\u001f', // representative example
00146 
00147                 // Double quotes
00148                 '"' => '\"',
00149 
00150                 // Backslashes
00151                 '\\' => '\\\\',
00152                 '\\\\' => '\\\\\\\\',
00153                 '\\u00e9' => '\\\u00e9', // security check for Unicode unescaping
00154 
00155                 // Line terminators
00156                 "\xe2\x80\xa8" => '\u2028',
00157                 "\xe2\x80\xa9" => '\u2029',
00158             ),
00159             'unicode' => array(
00160                 "\xc3\xa9" => '\u00e9',
00161                 "\xf0\x9d\x92\x9e" => '\ud835\udc9e', // U+1D49E, outside the BMP
00162             ),
00163             'xmlmeta' => array(
00164                 '<' => '\u003C', // JSON_HEX_TAG uses uppercase hex digits
00165                 '>' => '\u003E',
00166                 '&' => '\u0026',
00167             ),
00168         );
00169 
00170         $cases = array();
00171         foreach ( $groups as $name => $rules ) {
00172             $leaveUnescaped = in_array( $name, $unescapedGroups );
00173             foreach ( $rules as $from => $to ) {
00174                 $cases[] = array( $from, '"' . ( $leaveUnescaped ? $from : $to ) . '"' );
00175             }
00176         }
00177 
00178         return $cases;
00179     }
00180 }