- public static function provideParseErrors() {
- return [
- [ 'aaa' ],
- [ '{"j": 1 ] }' ],
- ];
- }
-
- /**
- * @dataProvider provideParseErrors
- * @param mixed $value
- */
- public function testParseErrors( $value ) {
- $st = FormatJson::parse( $value );
- $this->assertInstanceOf( Status::class, $st );
- $this->assertFalse( $st->isOK() );
- }
-
- public function provideStripComments() {
- return [
- [ '{"a":"b"}', '{"a":"b"}' ],
- [ "{\"a\":\"b\"}\n", "{\"a\":\"b\"}\n" ],
- [ '/*c*/{"c":"b"}', '{"c":"b"}' ],
- [ '{"a":"c"}/*c*/', '{"a":"c"}' ],
- [ '/*c//d*/{"c":"b"}', '{"c":"b"}' ],
- [ '{/*c*/"c":"b"}', '{"c":"b"}' ],
- [ "/*\nc\r\n*/{\"c\":\"b\"}", '{"c":"b"}' ],
- [ "//c\n{\"c\":\"b\"}", '{"c":"b"}' ],
- [ "//c\r\n{\"c\":\"b\"}", '{"c":"b"}' ],
- [ '{"a":"c"}//c', '{"a":"c"}' ],
- [ "{\"a-c\"://c\n\"b\"}", '{"a-c":"b"}' ],
- [ '{"/*a":"b"}', '{"/*a":"b"}' ],
- [ '{"a":"//b"}', '{"a":"//b"}' ],
- [ '{"a":"b/*c*/"}', '{"a":"b/*c*/"}' ],
- [ "{\"\\\"/*a\":\"b\"}", "{\"\\\"/*a\":\"b\"}" ],
- [ '', '' ],
- [ '/*c', '' ],
- [ '//c', '' ],
- [ '"http://example.com"', '"http://example.com"' ],
- [ "\0", "\0" ],
- [ '"Blåbærsyltetøy"', '"Blåbærsyltetøy"' ],
- ];
- }
-
- /**
- * @covers FormatJson::stripComments
- * @dataProvider provideStripComments
- * @param string $json
- * @param string $expect
- */
- public function testStripComments( $json, $expect ) {
- $this->assertSame( $expect, FormatJson::stripComments( $json ) );
- }
-
- public function provideParseStripComments() {
- return [
- [ '/* blah */true', true ],
- [ "// blah \ntrue", true ],
- [ '[ "a" , /* blah */ "b" ]', [ 'a', 'b' ] ],
- ];
- }
-
- /**
- * @covers FormatJson::parse
- * @covers FormatJson::stripComments
- * @dataProvider provideParseStripComments
- * @param string $json
- * @param mixed $expect
- */
- public function testParseStripComments( $json, $expect ) {
- $st = FormatJson::parse( $json, FormatJson::STRIP_COMMENTS );
- $this->assertInstanceOf( Status::class, $st );
- $this->assertTrue( $st->isGood() );
- $this->assertEquals( $expect, $st->getValue() );
- }
-
- /**
- * Generate a set of test cases for a particular combination of encoder options.
- *
- * @param array $unescapedGroups List of character groups to leave unescaped
- * @return array Arrays of unencoded strings and corresponding encoded strings
- */
- private static function getEncodeTestCases( array $unescapedGroups ) {
- $groups = [
- 'always' => [
- // Forward slash (always unescaped)
- '/' => '/',
-
- // Control characters
- "\0" => '\u0000',
- "\x08" => '\b',
- "\t" => '\t',
- "\n" => '\n',
- "\r" => '\r',
- "\f" => '\f',
- "\x1f" => '\u001f', // representative example
-
- // Double quotes
- '"' => '\"',
-
- // Backslashes
- '\\' => '\\\\',
- '\\\\' => '\\\\\\\\',
- '\\u00e9' => '\\\u00e9', // security check for Unicode unescaping
-
- // Line terminators
- "\xe2\x80\xa8" => '\u2028',
- "\xe2\x80\xa9" => '\u2029',
- ],
- 'unicode' => [
- "\xc3\xa9" => '\u00e9',
- "\xf0\x9d\x92\x9e" => '\ud835\udc9e', // U+1D49E, outside the BMP
- ],
- 'xmlmeta' => [
- '<' => '\u003C', // JSON_HEX_TAG uses uppercase hex digits
- '>' => '\u003E',
- '&' => '\u0026',
- ],
- ];
-
- $cases = [];
- foreach ( $groups as $name => $rules ) {
- $leaveUnescaped = in_array( $name, $unescapedGroups );
- foreach ( $rules as $from => $to ) {
- $cases[] = [ $from, '"' . ( $leaveUnescaped ? $from : $to ) . '"' ];
- }
- }
-
- return $cases;
- }
-
- public function provideEmptyJsonKeyStrings() {
- return [
- [
- '{"":"foo"}',
- '{"":"foo"}',
- ''
- ],
- [
- '{"_empty_":"foo"}',
- '{"_empty_":"foo"}',
- '_empty_' ],
- [
- '{"\u005F\u0065\u006D\u0070\u0074\u0079\u005F":"foo"}',
- '{"_empty_":"foo"}',
- '_empty_'
- ],
- [
- '{"_empty_":"bar","":"foo"}',
- '{"_empty_":"bar","":"foo"}',
- ''
- ],
- [
- '{"":"bar","_empty_":"foo"}',
- '{"":"bar","_empty_":"foo"}',
- '_empty_'
- ]
- ];
- }
-
- /**
- * @covers FormatJson::encode
- * @covers FormatJson::decode
- * @dataProvider provideEmptyJsonKeyStrings
- * @param string $json
- *
- * Decoding behavior with empty keys can be surprising.
- * See https://phabricator.wikimedia.org/T206411
- */
- public function testEmptyJsonKeyArray( $json, $expect, $php71Name ) {
- // Decoding to array is consistent across supported PHP versions
- $this->assertSame( $expect, FormatJson::encode(
- FormatJson::decode( $json, true ) ) );
-
- // Decoding to object differs between supported PHP versions
- $obj = FormatJson::decode( $json );
- if ( version_compare( PHP_VERSION, '7.1', '<' ) ) {
- $this->assertEquals( 'foo', $obj->_empty_ );
- } else {
- $this->assertEquals( 'foo', $obj->{$php71Name} );
- }
- }